From dc449cba919bdcdcfb84431127d3005485ca2b25 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Tue, 28 Jun 2022 11:01:53 +0200 Subject: [PATCH 01/34] read json file --- overviewer_core/textures.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index b809d242f..30bbf86a8 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -16,6 +16,7 @@ from collections import OrderedDict import sys import imp +import json import os import os.path import zipfile @@ -31,6 +32,7 @@ BLOCKTEX = "assets/minecraft/textures/block/" +BLOCKMOD = "assets/minecraft/models/" # global variables to collate information in @material decorators blockmap_generators = {} @@ -830,6 +832,36 @@ def generate_texture_tuple(self, img): return None return (img, self.generate_opaque_mask(img)) + modelcache = {} + + def load_model(self, modelname): + if modelname in self.modelcache: + return self.modelcache[modelname] + + fileobj = self.find_file(BLOCKMOD + modelname + '.json', verbose=logging.getLogger().isEnabledFor(logging.DEBUG)) + self.modelcache[modelname] = json.load(fileobj) + fileobj.close() + + if 'parent' in self.modelcache[modelname]: + self.load_model(self.modelcache[modelname]['parent'].removeprefix('minecraft:')) + + return self.modelcache[modelname] + + def load_image_from_model(self, modelname): + data = self.load_model('block/' + modelname) + + # Iterating through the json + # list + for i in self.modelcache: + print(self.modelcache[i]) + + # Closing file + ## 2. validate renderable type + ## 3. determine draw method + ## 4. return img + return null + + ## ## The other big one: @material and associated framework ## @@ -875,7 +907,7 @@ def func_wrapper(texobj, blockid, data): except TypeError: if kwargs.get(prop, False): properties[prop].update([block]) - + # populate blockmap_generators with our function for d in data: blockmap_generators[(block, d)] = func_wrapper @@ -933,6 +965,7 @@ def inner_billboard(self, unused_id, unused_data): @material(blockid=1, data=list(range(7)), solid=True) def stone(self, blockid, data): if data == 0: # regular old-school stone + self.load_image_from_model('stone') img = self.load_image_texture("assets/minecraft/textures/block/stone.png") elif data == 1: # granite img = self.load_image_texture("assets/minecraft/textures/block/granite.png") From 0f86fb36939b1feaaca0522de52def8b08d74922 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Tue, 28 Jun 2022 17:46:28 +0200 Subject: [PATCH 02/34] rad textures and succesfully render stone and cobblestone --- overviewer_core/textures.py | 153 ++++++++++++++++++++++++++++++------ 1 file changed, 130 insertions(+), 23 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 30bbf86a8..7ebf9068e 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -14,6 +14,7 @@ # with the Overviewer. If not, see . from collections import OrderedDict +import re import sys import imp import json @@ -30,8 +31,7 @@ from . import util - -BLOCKTEX = "assets/minecraft/textures/block/" +BLOCKTEX = "assets/minecraft/textures/" BLOCKMOD = "assets/minecraft/models/" # global variables to collate information in @material decorators @@ -832,36 +832,141 @@ def generate_texture_tuple(self, img): return None return (img, self.generate_opaque_mask(img)) - modelcache = {} + models = {} def load_model(self, modelname): - if modelname in self.modelcache: - return self.modelcache[modelname] + if modelname in self.models: + return self.models[modelname] fileobj = self.find_file(BLOCKMOD + modelname + '.json', verbose=logging.getLogger().isEnabledFor(logging.DEBUG)) - self.modelcache[modelname] = json.load(fileobj) + self.models[modelname] = json.load(fileobj) fileobj.close() - if 'parent' in self.modelcache[modelname]: - self.load_model(self.modelcache[modelname]['parent'].removeprefix('minecraft:')) - - return self.modelcache[modelname] + if 'parent' in self.models[modelname]: + parent = self.load_model(re.sub('.*:','',self.models[modelname]['parent'])) + if 'textures' in parent: + self.models[modelname]['textures'].update(parent['textures']) + if 'elements' in parent: + if 'elements' in self.models[modelname]: + self.models[modelname]['elements'].update(parent['elements']) + else: + self.models[modelname]['elements'] = parent['elements'] + del self.models[modelname]['parent'] + + return self.models[modelname] def load_image_from_model(self, modelname): data = self.load_model('block/' + modelname) - # Iterating through the json - # list - for i in self.modelcache: - print(self.modelcache[i]) + # print(json.dumps(data, indent=4)) + img = Image.new("RGBA", (24,24), self.bgcolor) + + # for each elements + for elem in data['elements']: + # determine all 6 faces from the 'from' and 'to' fields + if 'west' in elem['faces']: + direction = 'west' + print('westside') + texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) + texture = self.transform_texture(direction, texture) + texture = texture.transpose(Image.FLIP_LEFT_RIGHT) + texture = self.adjust_lighting(texture) + + alpha_over(img, texture, self.transrights(direction), texture) + elif 'east' in elem['faces']: + direction = 'east' + print('eastside') + texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) + texture = self.transform_texture(direction, texture) + texture = texture.transpose(Image.FLIP_LEFT_RIGHT) + texture = self.adjust_lighting(texture) + + alpha_over(img, texture, (0,0), texture) + if 'north' in elem['faces']: + direction = 'north' + print('northside') + texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) + texture = self.transform_texture(direction, texture) + texture = self.adjust_lighting(texture) + + alpha_over(img, texture, (0,6), texture) + elif 'south' in elem['faces']: + direction = 'south' + print('southside') + texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) + texture = self.transform_texture(direction, texture) + texture = self.adjust_lighting(texture) + + alpha_over(img, texture, (12,0), texture) + if 'up' in elem['faces']: + direction = 'up' + print('upside') + texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) + texture = self.transform_texture(direction, texture) + + alpha_over(img, texture, (0,0), texture) + elif 'down' in elem['faces']: + direction = 'down' + texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) + texture = self.transform_texture(direction, texture) + + alpha_over(img, texture, (0,12), texture) + + # draw each face - # Closing file - ## 2. validate renderable type - ## 3. determine draw method - ## 4. return img - return null + # TODO: this is not acceptable in a generic model reader, only applicable on full blocks + # Manually touch up 6 pixels that leave a gap because of how the + # shearing works out. This makes the blocks perfectly tessellate-able + for x,y in [(13,23), (17,21), (21,19)]: + # Copy a pixel to x,y from x-1,y + img.putpixel((x,y), img.getpixel((x-1,y))) + for x,y in [(3,4), (7,2), (11,0)]: + # Copy a pixel to x,y from x+1,y + img.putpixel((x,y), img.getpixel((x+1,y))) + return img + def adjust_lighting(self, texture): + # Darken this side + sidealpha = texture.split()[3] + texture = ImageEnhance.Brightness(texture).enhance(0.8) + texture.putalpha(sidealpha) + + return texture + + def transform_texture(self, direction, texture): + match direction: + case 'down' | 'up': + return self.transform_image_top(texture) + case 'north'| 'south' | 'west' | 'east': + return self.transform_image_side(texture) + case _: + raise Exception() + + def find_texture_from_model(self, face, textureset): + if face.startswith('#'): + return self.find_texture_from_model(textureset[face[1:]], textureset) + else: + return self.load_image_texture(BLOCKTEX + re.sub('.*:','',face) + '.png') + + # todo: use to implement non-full blocks + def determine_face_coords(self, fromdim, todim, direction): + match direction: + case 'down': + return 0 + case 'up': + return 0 + case 'north': + return 0 + case 'south': + return 0 + case 'west': + return 0 + case 'east': + return 0 + case _: + raise Exception() + ## ## The other big one: @material and associated framework ## @@ -965,7 +1070,7 @@ def inner_billboard(self, unused_id, unused_data): @material(blockid=1, data=list(range(7)), solid=True) def stone(self, blockid, data): if data == 0: # regular old-school stone - self.load_image_from_model('stone') + return self.load_image_from_model('stone') img = self.load_image_texture("assets/minecraft/textures/block/stone.png") elif data == 1: # granite img = self.load_image_texture("assets/minecraft/textures/block/granite.png") @@ -1008,7 +1113,9 @@ def dirt_blocks(self, blockid, data): # cobblestone -block(blockid=4, top_image="assets/minecraft/textures/block/cobblestone.png") +@material(blockid=4, data=0, solid=True) +def cobblestone(self, blockid, data): + return self.load_image_from_model('cobblestone') # wooden planks @material(blockid=5, data=list(range(8)), solid=True) @@ -1206,8 +1313,8 @@ def wood(self, blockid, data): top_f, side_f = wood_tex[blockid].get(wood_type, wood_tex[blockid][0]) if not side_f: side_f = top_f - top = self.load_image_texture(BLOCKTEX + top_f) - side = self.load_image_texture(BLOCKTEX + side_f) + top = self.load_image_texture(BLOCKTEX + 'block/' + top_f) + side = self.load_image_texture(BLOCKTEX + 'block/' + side_f) # choose orientation and paste textures if wood_orientation == 0: From 107829f317d0fe460e98bfd2a7f6311158d5b824 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Tue, 28 Jun 2022 23:01:54 +0200 Subject: [PATCH 03/34] eod commit --- overviewer_core/textures.py | 105 +++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 37 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 7ebf9068e..9cec174a1 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -860,56 +860,49 @@ def load_image_from_model(self, modelname): # print(json.dumps(data, indent=4)) img = Image.new("RGBA", (24,24), self.bgcolor) + fullblock = 1 # for each elements for elem in data['elements']: # determine all 6 faces from the 'from' and 'to' fields if 'west' in elem['faces']: direction = 'west' - print('westside') - texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) + texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']).copy() + if 'uv' in elem['faces'][direction]: + fullblock = 0 + print('uv defined for ' + modelname + ' in ' + elem['__comment'] + ' as ' + str(elem['faces'][direction]['uv'])) + texture = self.crop_to_transparancy(texture, elem['faces'][direction]['uv']) texture = self.transform_texture(direction, texture) texture = texture.transpose(Image.FLIP_LEFT_RIGHT) - texture = self.adjust_lighting(texture) + texture = self.adjust_lighting(direction,texture) - alpha_over(img, texture, self.transrights(direction), texture) + alpha_over(img, texture, (12,6), texture) + + return img elif 'east' in elem['faces']: direction = 'east' - print('eastside') - texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) - texture = self.transform_texture(direction, texture) - texture = texture.transpose(Image.FLIP_LEFT_RIGHT) - texture = self.adjust_lighting(texture) + texture = self.draw_face(direction, elem, data, modelname) alpha_over(img, texture, (0,0), texture) if 'north' in elem['faces']: direction = 'north' - print('northside') - texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) - texture = self.transform_texture(direction, texture) - texture = self.adjust_lighting(texture) + texture = self.draw_face(direction, elem, data, modelname) alpha_over(img, texture, (0,6), texture) elif 'south' in elem['faces']: - direction = 'south' - print('southside') - texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) - texture = self.transform_texture(direction, texture) - texture = self.adjust_lighting(texture) + texture = self.draw_face(direction, elem, data, modelname) alpha_over(img, texture, (12,0), texture) if 'up' in elem['faces']: direction = 'up' - print('upside') - texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) - texture = self.transform_texture(direction, texture) + texture = self.draw_face(direction, elem, data, modelname) alpha_over(img, texture, (0,0), texture) elif 'down' in elem['faces']: direction = 'down' - texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']) - texture = self.transform_texture(direction, texture) - + + texture = self.draw_face(direction, elem, data, modelname) + alpha_over(img, texture, (0,12), texture) # draw each face @@ -917,28 +910,51 @@ def load_image_from_model(self, modelname): # TODO: this is not acceptable in a generic model reader, only applicable on full blocks # Manually touch up 6 pixels that leave a gap because of how the # shearing works out. This makes the blocks perfectly tessellate-able - for x,y in [(13,23), (17,21), (21,19)]: - # Copy a pixel to x,y from x-1,y - img.putpixel((x,y), img.getpixel((x-1,y))) - for x,y in [(3,4), (7,2), (11,0)]: - # Copy a pixel to x,y from x+1,y - img.putpixel((x,y), img.getpixel((x+1,y))) + if fullblock == 1: + for x,y in [(13,23), (17,21), (21,19)]: + # Copy a pixel to x,y from x-1,y + img.putpixel((x,y), img.getpixel((x-1,y))) + for x,y in [(3,4), (7,2), (11,0)]: + # Copy a pixel to x,y from x+1,y + img.putpixel((x,y), img.getpixel((x+1,y))) return img - def adjust_lighting(self, texture): - # Darken this side - sidealpha = texture.split()[3] - texture = ImageEnhance.Brightness(texture).enhance(0.8) - texture.putalpha(sidealpha) + def draw_face(self, direction, elem, data, modelname): + texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']).copy() + if 'uv' in elem['faces'][direction]: + print('uv defined for ' + modelname) + ImageDraw.Draw(texture).rectangle((0,0,0,0), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + texture = self.transform_texture(direction, texture) + texture = self.adjust_lighting(direction,texture) return texture + def adjust_lighting(self, direction, texture): + match direction: + case 'down' | 'up': + return texture + case 'south' | 'west': + sidealpha = texture.split()[3] + texture = ImageEnhance.Brightness(texture).enhance(0.8) + texture.putalpha(sidealpha) + return texture + case 'north' | 'east': + sidealpha = texture.split()[3] + texture = ImageEnhance.Brightness(texture).enhance(0.9) + texture.putalpha(sidealpha) + return texture + case _: + raise Exception() + + def transform_texture(self, direction, texture): match direction: case 'down' | 'up': return self.transform_image_top(texture) - case 'north'| 'south' | 'west' | 'east': + case 'north'| 'south': + return self.transform_image_side(texture) + case 'west' | 'east': return self.transform_image_side(texture) case _: raise Exception() @@ -951,6 +967,8 @@ def find_texture_from_model(self, face, textureset): # todo: use to implement non-full blocks def determine_face_coords(self, fromdim, todim, direction): + # "from": [0, 0, 0], + # "to": [16, 16, 16], match direction: case 'down': return 0 @@ -967,6 +985,18 @@ def determine_face_coords(self, fromdim, todim, direction): case _: raise Exception() + def crop_to_transparancy(self, img, area): + # [0, 2, 4, 14] + # top + ImageDraw.Draw(img).rectangle((area[2],0,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) + # bottom + ImageDraw.Draw(img).rectangle((0,0,area[0],16),outline=(0,0,0,0),fill=(0,0,0,0)) + # left + ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) + # right + ImageDraw.Draw(img).rectangle((0,area[3],16,16),outline=(0,0,0,0),fill=(0,0,0,0)) + return img + ## ## The other big one: @material and associated framework ## @@ -5268,7 +5298,8 @@ def anvil(self, blockid, data): # get the correct textures # the bits 0x4 and 0x8 determine how damaged is the anvil if (data & 0xc) == 0: # non damaged anvil - top = self.load_image_texture("assets/minecraft/textures/block/anvil_top.png") + # top = self.load_image_texture("assets/minecraft/textures/block/anvil_top.png") + return self.load_image_from_model('anvil') elif (data & 0xc) == 0x4: # slightly damaged top = self.load_image_texture("assets/minecraft/textures/block/chipped_anvil_top.png") elif (data & 0xc) == 0x8: # very damaged From 8c4b8dd89302b930469b6a6a456b56d505fc3259 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Wed, 29 Jun 2022 11:08:43 +0200 Subject: [PATCH 04/34] focus on full blocks for now --- overviewer_core/textures.py | 180 +++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 87 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 9cec174a1..fcf1eadea 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -860,71 +860,86 @@ def load_image_from_model(self, modelname): # print(json.dumps(data, indent=4)) img = Image.new("RGBA", (24,24), self.bgcolor) - fullblock = 1 + + print(modelname + ' ' + str(self.rotation)) # for each elements for elem in data['elements']: # determine all 6 faces from the 'from' and 'to' fields if 'west' in elem['faces']: - direction = 'west' - texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']).copy() - if 'uv' in elem['faces'][direction]: - fullblock = 0 - print('uv defined for ' + modelname + ' in ' + elem['__comment'] + ' as ' + str(elem['faces'][direction]['uv'])) - texture = self.crop_to_transparancy(texture, elem['faces'][direction]['uv']) - texture = self.transform_texture(direction, texture) - texture = texture.transpose(Image.FLIP_LEFT_RIGHT) - texture = self.adjust_lighting(direction,texture) - + texture = self.draw_face('west', elem, data, modelname) alpha_over(img, texture, (12,6), texture) - - return img elif 'east' in elem['faces']: - direction = 'east' - texture = self.draw_face(direction, elem, data, modelname) - + texture = self.draw_face('east', elem, data, modelname) alpha_over(img, texture, (0,0), texture) - if 'north' in elem['faces']: - direction = 'north' - texture = self.draw_face(direction, elem, data, modelname) + if 'north' in elem['faces']: + texture = self.draw_face('north', elem, data, modelname) alpha_over(img, texture, (0,6), texture) elif 'south' in elem['faces']: - texture = self.draw_face(direction, elem, data, modelname) - + texture = self.draw_face('south', elem, data, modelname) alpha_over(img, texture, (12,0), texture) - if 'up' in elem['faces']: - direction = 'up' - texture = self.draw_face(direction, elem, data, modelname) + if 'up' in elem['faces']: + texture = self.draw_face('up', elem, data, modelname) alpha_over(img, texture, (0,0), texture) elif 'down' in elem['faces']: - direction = 'down' - - texture = self.draw_face(direction, elem, data, modelname) - + texture = self.draw_face('down', elem, data, modelname) alpha_over(img, texture, (0,12), texture) # draw each face - # TODO: this is not acceptable in a generic model reader, only applicable on full blocks # Manually touch up 6 pixels that leave a gap because of how the # shearing works out. This makes the blocks perfectly tessellate-able - if fullblock == 1: - for x,y in [(13,23), (17,21), (21,19)]: - # Copy a pixel to x,y from x-1,y - img.putpixel((x,y), img.getpixel((x-1,y))) - for x,y in [(3,4), (7,2), (11,0)]: - # Copy a pixel to x,y from x+1,y - img.putpixel((x,y), img.getpixel((x+1,y))) + for x,y in [(13,23), (17,21), (21,19)]: + # Copy a pixel to x,y from x-1,y + img.putpixel((x,y), img.getpixel((x-1,y))) + for x,y in [(3,4), (7,2), (11,0)]: + # Copy a pixel to x,y from x+1,y + img.putpixel((x,y), img.getpixel((x+1,y))) return img + # def translate_rotation(self, direction, rotation): + # match direction: + # case 'down': + # return 'down' + # case 'up': + # return 'up' + # case 'north': + # return self.cards(rotation) + # case 'south': + # return self.cards(rotation + 1) + # case 'west': + # return self.cards(rotation + 2) + # case 'east': + # return self.cards(rotation + 3) + # case _: + # raise Exception() + + # def cards(self, rotation): + # print(rotation) + # rotation = rotation % 4 + # print(rotation) + # match rotation: + # case 0: + # return 'north' + # case 1: + # return 'south' + # case 2: + # return 'west' + # case 3: + # return 'east' + # case _: + # raise Exception() + def draw_face(self, direction, elem, data, modelname): + # direction = self.translate_rotation(direction, self.rotation) texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']).copy() - if 'uv' in elem['faces'][direction]: - print('uv defined for ' + modelname) - ImageDraw.Draw(texture).rectangle((0,0,0,0), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + # if 'uv' in elem['faces'][direction]: + # print('uv defined for ' + modelname + ' in ' + elem['__comment'] + ' as ' + str(elem['faces'][direction]['uv'])) + # texture = self.crop_to_transparancy(texture, elem['faces'][direction]['uv']) + # texture = self.adjust_rotation(direction, texture) texture = self.transform_texture(direction, texture) texture = self.adjust_lighting(direction,texture) @@ -947,7 +962,6 @@ def adjust_lighting(self, direction, texture): case _: raise Exception() - def transform_texture(self, direction, texture): match direction: case 'down' | 'up': @@ -955,7 +969,8 @@ def transform_texture(self, direction, texture): case 'north'| 'south': return self.transform_image_side(texture) case 'west' | 'east': - return self.transform_image_side(texture) + texture = self.transform_image_side(texture) + return texture.transpose(Image.FLIP_LEFT_RIGHT) case _: raise Exception() @@ -965,37 +980,28 @@ def find_texture_from_model(self, face, textureset): else: return self.load_image_texture(BLOCKTEX + re.sub('.*:','',face) + '.png') - # todo: use to implement non-full blocks - def determine_face_coords(self, fromdim, todim, direction): - # "from": [0, 0, 0], - # "to": [16, 16, 16], - match direction: - case 'down': - return 0 - case 'up': - return 0 - case 'north': - return 0 - case 'south': - return 0 - case 'west': - return 0 - case 'east': - return 0 - case _: - raise Exception() - - def crop_to_transparancy(self, img, area): - # [0, 2, 4, 14] - # top - ImageDraw.Draw(img).rectangle((area[2],0,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) - # bottom - ImageDraw.Draw(img).rectangle((0,0,area[0],16),outline=(0,0,0,0),fill=(0,0,0,0)) - # left - ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) - # right - ImageDraw.Draw(img).rectangle((0,area[3],16,16),outline=(0,0,0,0),fill=(0,0,0,0)) - return img + # def crop_to_transparancy(self, img, area): + # img = img.copy() + # # top + # ImageDraw.Draw(img).rectangle((area[2],0,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) + # # right + # ImageDraw.Draw(img).rectangle((0,area[3],16,16),outline=(0,0,0,0),fill=(0,0,0,0)) + # # bottom + # ImageDraw.Draw(img).rectangle((0,0,area[0],16),outline=(0,0,0,0),fill=(0,0,0,0)) + # # left + # ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) + # return img + + # def adjust_rotation(self, direction, texture): + # match direction: + # case 'down' | 'up': + # return texture.rotate(90) + # case 'south' | 'west': + # return texture.rotate(90) + # case 'north' | 'east': + # return texture.rotate(0) + # case _: + # raise Exception() ## ## The other big one: @material and associated framework @@ -1101,7 +1107,6 @@ def inner_billboard(self, unused_id, unused_data): def stone(self, blockid, data): if data == 0: # regular old-school stone return self.load_image_from_model('stone') - img = self.load_image_texture("assets/minecraft/textures/block/stone.png") elif data == 1: # granite img = self.load_image_texture("assets/minecraft/textures/block/granite.png") elif data == 2: # polished granite @@ -2896,21 +2901,23 @@ def darken_image(img_src, darken_value): @material(blockid=11367, data=list(range(4)), solid=True) def loom(self, blockid, data): - # Do rotation - data = (self.rotation + data) % 4 - top_rot = [180, 90, 0, 270][data] - side3_tex = "front" if data == 1 else "side" - side4_tex = "front" if data == 0 else "side" + return self.load_image_from_model('loom') - tex_path = "assets/minecraft/textures/block" - top = self.load_image_texture("{}/loom_top.png".format(tex_path)).copy() - side3 = self.load_image_texture("{}/loom_{}.png".format(tex_path, side3_tex)) - side4 = self.load_image_texture("{}/loom_{}.png".format(tex_path, side4_tex)).copy() - top = top.rotate(top_rot) - side4 = side4.transpose(Image.FLIP_LEFT_RIGHT) + # data = (self.rotation + data) % 4 - return self.build_full_block(top, None, None, side3, side4, None) + # top_rot = [180, 90, 0, 270][data] + # side3_tex = "front" if data == 1 else "side" + # side4_tex = "front" if data == 0 else "side" + + # tex_path = "assets/minecraft/textures/block" + # top = self.load_image_texture("{}/loom_top.png".format(tex_path)).copy() + # side3 = self.load_image_texture("{}/loom_{}.png".format(tex_path, side3_tex)) + # side4 = self.load_image_texture("{}/loom_{}.png".format(tex_path, side4_tex)).copy() + # top = top.rotate(top_rot) + # side4 = side4.transpose(Image.FLIP_LEFT_RIGHT) + + # return self.build_full_block(top, None, None, side3, side4, None) @material(blockid=11368, data=list(range(4)), transparent=True, solid=True, nospawn=True) @@ -5298,8 +5305,7 @@ def anvil(self, blockid, data): # get the correct textures # the bits 0x4 and 0x8 determine how damaged is the anvil if (data & 0xc) == 0: # non damaged anvil - # top = self.load_image_texture("assets/minecraft/textures/block/anvil_top.png") - return self.load_image_from_model('anvil') + top = self.load_image_texture("assets/minecraft/textures/block/anvil_top.png") elif (data & 0xc) == 0x4: # slightly damaged top = self.load_image_texture("assets/minecraft/textures/block/chipped_anvil_top.png") elif (data & 0xc) == 0x8: # very damaged From 37953c4d90717cbd45948390c93c3b3f888ba0bb Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Wed, 29 Jun 2022 21:01:31 +0200 Subject: [PATCH 05/34] proper rotation for loom block --- overviewer_core/textures.py | 157 +++++++++++++++++------------------- 1 file changed, 74 insertions(+), 83 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index fcf1eadea..94e5e83ef 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -854,37 +854,34 @@ def load_model(self, modelname): del self.models[modelname]['parent'] return self.models[modelname] - - def load_image_from_model(self, modelname): - data = self.load_model('block/' + modelname) + + def build_block_from_model(self, modelname, blockstate={}): + colmodel = self.load_model('block/' + modelname) # print(json.dumps(data, indent=4)) img = Image.new("RGBA", (24,24), self.bgcolor) - print(modelname + ' ' + str(self.rotation)) - # for each elements - for elem in data['elements']: - # determine all 6 faces from the 'from' and 'to' fields + for elem in colmodel['elements']: if 'west' in elem['faces']: - texture = self.draw_face('west', elem, data, modelname) + texture = self.draw_face('west', elem, colmodel, blockstate) alpha_over(img, texture, (12,6), texture) elif 'east' in elem['faces']: - texture = self.draw_face('east', elem, data, modelname) + texture = self.draw_face('east', elem, colmodel, blockstate) alpha_over(img, texture, (0,0), texture) if 'north' in elem['faces']: - texture = self.draw_face('north', elem, data, modelname) + texture = self.draw_face('north', elem, colmodel, blockstate) alpha_over(img, texture, (0,6), texture) elif 'south' in elem['faces']: - texture = self.draw_face('south', elem, data, modelname) + texture = self.draw_face('south', elem, colmodel, blockstate) alpha_over(img, texture, (12,0), texture) if 'up' in elem['faces']: - texture = self.draw_face('up', elem, data, modelname) + texture = self.draw_face('up', elem, colmodel, blockstate) alpha_over(img, texture, (0,0), texture) elif 'down' in elem['faces']: - texture = self.draw_face('down', elem, data, modelname) + texture = self.draw_face('down', elem, colmodel, blockstate) alpha_over(img, texture, (0,12), texture) # draw each face @@ -900,47 +897,32 @@ def load_image_from_model(self, modelname): return img - # def translate_rotation(self, direction, rotation): - # match direction: - # case 'down': - # return 'down' - # case 'up': - # return 'up' - # case 'north': - # return self.cards(rotation) - # case 'south': - # return self.cards(rotation + 1) - # case 'west': - # return self.cards(rotation + 2) - # case 'east': - # return self.cards(rotation + 3) - # case _: - # raise Exception() - - # def cards(self, rotation): - # print(rotation) - # rotation = rotation % 4 - # print(rotation) - # match rotation: - # case 0: - # return 'north' - # case 1: - # return 'south' - # case 2: - # return 'west' - # case 3: - # return 'east' - # case _: - # raise Exception() - - def draw_face(self, direction, elem, data, modelname): - # direction = self.translate_rotation(direction, self.rotation) - texture = self.find_texture_from_model(elem['faces'][direction]['texture'], data['textures']).copy() - # if 'uv' in elem['faces'][direction]: - # print('uv defined for ' + modelname + ' in ' + elem['__comment'] + ' as ' + str(elem['faces'][direction]['uv'])) - # texture = self.crop_to_transparancy(texture, elem['faces'][direction]['uv']) - # texture = self.adjust_rotation(direction, texture) - texture = self.transform_texture(direction, texture) + # def determine_face(self, blockrotation, worldrotation, face): + # if rendered orientation is south or west -> draw front + # # if I want to draw the + + def numvalue_orientation(self, orientation): + return {'south': 0, 'west': 1, 'north': 2, 'east': 3}[orientation] + + def orientation_from_numvalue(self, orientation): + return {0:'south', 1:'west', 2:'north', 3:'east'}[orientation] + + def map_facing_to_real(self, blockfacing, targetblockface): + if ((blockfacing in {'up','down'}) | (targetblockface in {'up','down'})): + return targetblockface + return self.orientation_from_numvalue((self.numvalue_orientation(targetblockface) + [0,3,2,1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2)*2) % 4) + + def draw_face(self, direction, elem, data, blockstate): + textureface = direction + if 'facing' in blockstate: + textureface = self.map_facing_to_real(blockstate['facing'], direction) + + texture = self.find_texture_from_model(elem['faces'][textureface]['texture'], data['textures']).copy() + if 'uv' in elem['faces'][textureface]: + print('uv defined in ' + elem['__comment'] + ' as ' + str(elem['faces'][textureface]['uv'])) + texture = self.crop_to_transparancy(texture, elem['faces'][textureface]['uv']) + texture = self.adjust_rotation(textureface, texture) + texture = self.transform_texture(direction, texture, blockstate) texture = self.adjust_lighting(direction,texture) return texture @@ -962,46 +944,50 @@ def adjust_lighting(self, direction, texture): case _: raise Exception() - def transform_texture(self, direction, texture): + def transform_texture(self, direction, texture, blockstate): match direction: case 'down' | 'up': - return self.transform_image_top(texture) + top_rotation = 0 + if 'facing' in blockstate: + top_rotation = [180, 90, 0, 270][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] + return self.transform_image_top(texture.rotate(top_rotation)) case 'north'| 'south': - return self.transform_image_side(texture) + texture = self.transform_image_side(texture) case 'west' | 'east': texture = self.transform_image_side(texture) - return texture.transpose(Image.FLIP_LEFT_RIGHT) + texture = texture.transpose(Image.FLIP_LEFT_RIGHT) case _: raise Exception() + + return texture def find_texture_from_model(self, face, textureset): if face.startswith('#'): return self.find_texture_from_model(textureset[face[1:]], textureset) else: return self.load_image_texture(BLOCKTEX + re.sub('.*:','',face) + '.png') + + def crop_to_transparancy(self, img, area): + # top + ImageDraw.Draw(img).rectangle((area[2],0,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) + # right + ImageDraw.Draw(img).rectangle((0,area[3],16,16),outline=(0,0,0,0),fill=(0,0,0,0)) + # bottom + ImageDraw.Draw(img).rectangle((0,0,area[0],16),outline=(0,0,0,0),fill=(0,0,0,0)) + # left + ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) + return img - # def crop_to_transparancy(self, img, area): - # img = img.copy() - # # top - # ImageDraw.Draw(img).rectangle((area[2],0,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) - # # right - # ImageDraw.Draw(img).rectangle((0,area[3],16,16),outline=(0,0,0,0),fill=(0,0,0,0)) - # # bottom - # ImageDraw.Draw(img).rectangle((0,0,area[0],16),outline=(0,0,0,0),fill=(0,0,0,0)) - # # left - # ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) - # return img - - # def adjust_rotation(self, direction, texture): - # match direction: - # case 'down' | 'up': - # return texture.rotate(90) - # case 'south' | 'west': - # return texture.rotate(90) - # case 'north' | 'east': - # return texture.rotate(0) - # case _: - # raise Exception() + def adjust_rotation(self, direction, texture): + match direction: + case 'down' | 'up': + return texture.rotate(90) + case 'south' | 'west': + return texture.rotate(90) + case 'north' | 'east': + return texture.rotate(0) + case _: + raise Exception() ## ## The other big one: @material and associated framework @@ -1106,7 +1092,7 @@ def inner_billboard(self, unused_id, unused_data): @material(blockid=1, data=list(range(7)), solid=True) def stone(self, blockid, data): if data == 0: # regular old-school stone - return self.load_image_from_model('stone') + return self.build_block_from_model('stone') elif data == 1: # granite img = self.load_image_texture("assets/minecraft/textures/block/granite.png") elif data == 2: # polished granite @@ -1150,7 +1136,7 @@ def dirt_blocks(self, blockid, data): # cobblestone @material(blockid=4, data=0, solid=True) def cobblestone(self, blockid, data): - return self.load_image_from_model('cobblestone') + return self.build_block_from_model('cobblestone') # wooden planks @material(blockid=5, data=list(range(8)), solid=True) @@ -2902,7 +2888,11 @@ def darken_image(img_src, darken_value): @material(blockid=11367, data=list(range(4)), solid=True) def loom(self, blockid, data): - return self.load_image_from_model('loom') + # normalize data so it can be used by a generic method + blockstate = {} + blockstate['facing'] = {0:'south', 1:'west', 2:'north', 3:'east'}[data] + + return self.build_block_from_model('loom', blockstate) # data = (self.rotation + data) % 4 @@ -5305,6 +5295,7 @@ def anvil(self, blockid, data): # get the correct textures # the bits 0x4 and 0x8 determine how damaged is the anvil if (data & 0xc) == 0: # non damaged anvil + # return self.build_block_from_model('anvil') top = self.load_image_texture("assets/minecraft/textures/block/anvil_top.png") elif (data & 0xc) == 0x4: # slightly damaged top = self.load_image_texture("assets/minecraft/textures/block/chipped_anvil_top.png") From fdb63562d990e8ab3ff94fe00e274b31626bcb46 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Wed, 29 Jun 2022 21:13:45 +0200 Subject: [PATCH 06/34] modelblock method --- overviewer_core/textures.py | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 94e5e83ef..33a63dca7 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -1042,6 +1042,17 @@ def func_wrapper(texobj, blockid, data): return func_wrapper return inner_material +# shortcut function for pure blocks, default to solid, nodata +def modelblock(blockid=[], name=None): + + if name is None: + raise ValueError("block name was not provided") + + @material(blockid=blockid) + def inner_block(self, unused_id, unused_data): + return self.build_block_from_model(name) + return inner_block + # shortcut function for pure blocks, default to solid, nodata def block(blockid=[], top_image=None, side_image=None, **kwargs): new_kwargs = {'solid' : True, 'nodata' : True} @@ -1132,11 +1143,7 @@ def dirt_blocks(self, blockid, data): return self.build_block(top_img, side_img) - -# cobblestone -@material(blockid=4, data=0, solid=True) -def cobblestone(self, blockid, data): - return self.build_block_from_model('cobblestone') +modelblock(blockid=4, name='cobblestone') # wooden planks @material(blockid=5, data=list(range(8)), solid=True) @@ -2887,29 +2894,11 @@ def darken_image(img_src, darken_value): @material(blockid=11367, data=list(range(4)), solid=True) def loom(self, blockid, data): - # normalize data so it can be used by a generic method blockstate = {} blockstate['facing'] = {0:'south', 1:'west', 2:'north', 3:'east'}[data] - return self.build_block_from_model('loom', blockstate) - # data = (self.rotation + data) % 4 - - # top_rot = [180, 90, 0, 270][data] - # side3_tex = "front" if data == 1 else "side" - # side4_tex = "front" if data == 0 else "side" - - # tex_path = "assets/minecraft/textures/block" - # top = self.load_image_texture("{}/loom_top.png".format(tex_path)).copy() - # side3 = self.load_image_texture("{}/loom_{}.png".format(tex_path, side3_tex)) - # side4 = self.load_image_texture("{}/loom_{}.png".format(tex_path, side4_tex)).copy() - # top = top.rotate(top_rot) - # side4 = side4.transpose(Image.FLIP_LEFT_RIGHT) - - # return self.build_full_block(top, None, None, side3, side4, None) - - @material(blockid=11368, data=list(range(4)), transparent=True, solid=True, nospawn=True) def stonecutter(self, blockid, data): # Do rotation From cb2d5b86a8b2854191374e0963e7b793913efa52 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Wed, 29 Jun 2022 22:56:47 +0200 Subject: [PATCH 07/34] added blocks to new texture build method --- overviewer_core/textures.py | 78 ++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 33a63dca7..3ed02902b 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -864,24 +864,24 @@ def build_block_from_model(self, modelname, blockstate={}): # for each elements for elem in colmodel['elements']: if 'west' in elem['faces']: - texture = self.draw_face('west', elem, colmodel, blockstate) + texture = self.draw_face('west', elem, colmodel, blockstate, modelname) alpha_over(img, texture, (12,6), texture) elif 'east' in elem['faces']: - texture = self.draw_face('east', elem, colmodel, blockstate) + texture = self.draw_face('east', elem, colmodel, blockstate, modelname) alpha_over(img, texture, (0,0), texture) if 'north' in elem['faces']: - texture = self.draw_face('north', elem, colmodel, blockstate) + texture = self.draw_face('north', elem, colmodel, blockstate, modelname) alpha_over(img, texture, (0,6), texture) elif 'south' in elem['faces']: - texture = self.draw_face('south', elem, colmodel, blockstate) + texture = self.draw_face('south', elem, colmodel, blockstate, modelname) alpha_over(img, texture, (12,0), texture) if 'up' in elem['faces']: - texture = self.draw_face('up', elem, colmodel, blockstate) + texture = self.draw_face('up', elem, colmodel, blockstate, modelname) alpha_over(img, texture, (0,0), texture) elif 'down' in elem['faces']: - texture = self.draw_face('down', elem, colmodel, blockstate) + texture = self.draw_face('down', elem, colmodel, blockstate, modelname) alpha_over(img, texture, (0,12), texture) # draw each face @@ -912,16 +912,16 @@ def map_facing_to_real(self, blockfacing, targetblockface): return targetblockface return self.orientation_from_numvalue((self.numvalue_orientation(targetblockface) + [0,3,2,1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2)*2) % 4) - def draw_face(self, direction, elem, data, blockstate): + def draw_face(self, direction, elem, data, blockstate, modelname): textureface = direction if 'facing' in blockstate: textureface = self.map_facing_to_real(blockstate['facing'], direction) texture = self.find_texture_from_model(elem['faces'][textureface]['texture'], data['textures']).copy() if 'uv' in elem['faces'][textureface]: - print('uv defined in ' + elem['__comment'] + ' as ' + str(elem['faces'][textureface]['uv'])) + print('uv defined in ' + modelname + ' as ' + str(elem['faces'][textureface]['uv'])) texture = self.crop_to_transparancy(texture, elem['faces'][textureface]['uv']) - texture = self.adjust_rotation(textureface, texture) + texture = self.adjust_rotation(textureface, texture, modelname) texture = self.transform_texture(direction, texture, blockstate) texture = self.adjust_lighting(direction,texture) @@ -978,12 +978,14 @@ def crop_to_transparancy(self, img, area): ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) return img - def adjust_rotation(self, direction, texture): + def adjust_rotation(self, direction, texture, modelname): match direction: case 'down' | 'up': return texture.rotate(90) - case 'south' | 'west': + case 'south': return texture.rotate(90) + case 'west': + return texture.rotate(0) case 'north' | 'east': return texture.rotate(0) case _: @@ -1105,43 +1107,37 @@ def stone(self, blockid, data): if data == 0: # regular old-school stone return self.build_block_from_model('stone') elif data == 1: # granite - img = self.load_image_texture("assets/minecraft/textures/block/granite.png") + return self.build_block_from_model('granite') elif data == 2: # polished granite - img = self.load_image_texture("assets/minecraft/textures/block/polished_granite.png") + return self.build_block_from_model('polished_granite') elif data == 3: # diorite - img = self.load_image_texture("assets/minecraft/textures/block/diorite.png") + return self.build_block_from_model('diorite') elif data == 4: # polished diorite - img = self.load_image_texture("assets/minecraft/textures/block/polished_diorite.png") + return self.build_block_from_model('polished_diorite') elif data == 5: # andesite - img = self.load_image_texture("assets/minecraft/textures/block/andesite.png") + return self.build_block_from_model('andesite') elif data == 6: # polished andesite - img = self.load_image_texture("assets/minecraft/textures/block/polished_andesite.png") - return self.build_block(img, img) + return self.build_block_from_model('polished_andesite') @material(blockid=2, data=list(range(11))+[0x10,], solid=True) def grass(self, blockid, data): # 0x10 bit means SNOW - side_img = self.load_image_texture("assets/minecraft/textures/block/grass_block_side.png") if data & 0x10: - side_img = self.load_image_texture("assets/minecraft/textures/block/grass_block_snow.png") - img = self.build_block(self.load_image_texture("assets/minecraft/textures/block/grass_block_top.png"), side_img) - if not data & 0x10: + return self.build_block_from_model('grass_block_snow') + else: + img = self.build_block_from_model('grass_block') alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture) - return img - + return img # dirt @material(blockid=3, data=list(range(3)), solid=True) def dirt_blocks(self, blockid, data): - texture_map = [{"top": "dirt", "side": "dirt"}, # Normal - {"top": "coarse_dirt", "side": "coarse_dirt"}, # Coarse - {"top": "podzol_top", "side": "podzol_side"}] # Podzol - top_img = self.load_image_texture("assets/minecraft/textures/block/%s.png" - % texture_map[data]["top"]) - side_img = self.load_image_texture("assets/minecraft/textures/block/%s.png" - % texture_map[data]["side"]) - - return self.build_block(top_img, side_img) + if data == 0: + return self.build_block_from_model('dirt') + if data == 1: + return self.build_block_from_model('coarse_dirt') + if data == 2: + return self.build_block_from_model('podzol') modelblock(blockid=4, name='cobblestone') @@ -1149,21 +1145,21 @@ def dirt_blocks(self, blockid, data): @material(blockid=5, data=list(range(8)), solid=True) def wooden_planks(self, blockid, data): if data == 0: # normal - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/oak_planks.png"), self.load_image_texture("assets/minecraft/textures/block/oak_planks.png")) + return self.build_block_from_model('oak_planks') if data == 1: # pine - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/spruce_planks.png"),self.load_image_texture("assets/minecraft/textures/block/spruce_planks.png")) + return self.build_block_from_model('spruce_planks') if data == 2: # birch - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/birch_planks.png"),self.load_image_texture("assets/minecraft/textures/block/birch_planks.png")) + return self.build_block_from_model('birch_planks') if data == 3: # jungle wood - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/jungle_planks.png"),self.load_image_texture("assets/minecraft/textures/block/jungle_planks.png")) + return self.build_block_from_model('jungle_planks') if data == 4: # acacia - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/acacia_planks.png"),self.load_image_texture("assets/minecraft/textures/block/acacia_planks.png")) + return self.build_block_from_model('acacia_planks') if data == 5: # dark oak - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/dark_oak_planks.png"),self.load_image_texture("assets/minecraft/textures/block/dark_oak_planks.png")) + return self.build_block_from_model('dark_oak_planks') if data == 6: # crimson - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/crimson_planks.png"),self.load_image_texture("assets/minecraft/textures/block/crimson_planks.png")) + return self.build_block_from_model('crimson_planks') if data == 7: # warped - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/warped_planks.png"),self.load_image_texture("assets/minecraft/textures/block/warped_planks.png")) + return self.build_block_from_model('warped_planks') @material(blockid=6, data=list(range(16)), transparent=True) def saplings(self, blockid, data): From fdda6d364e63389c00aac5c1b8370b2d0bdefca2 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Mon, 4 Jul 2022 07:46:46 +0200 Subject: [PATCH 08/34] added few blocks to generic rendering --- overviewer_core/textures.py | 44 ++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 3ed02902b..cd12f57fa 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -1121,11 +1121,12 @@ def stone(self, blockid, data): @material(blockid=2, data=list(range(11))+[0x10,], solid=True) def grass(self, blockid, data): - # 0x10 bit means SNOW if data & 0x10: return self.build_block_from_model('grass_block_snow') else: - img = self.build_block_from_model('grass_block') + # TODO: generify biome texture overlay + side_img = self.load_image_texture("assets/minecraft/textures/block/grass_block_side.png") + img = self.build_block(self.load_image_texture("assets/minecraft/textures/block/grass_block_top.png"), side_img) alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture) return img @@ -1163,6 +1164,7 @@ def wooden_planks(self, blockid, data): @material(blockid=6, data=list(range(16)), transparent=True) def saplings(self, blockid, data): + # TODO: generify block/cross # usual saplings tex = self.load_image_texture("assets/minecraft/textures/block/oak_sapling.png") @@ -1187,16 +1189,18 @@ def saplings(self, blockid, data): sprite(blockid=11413, imagename="assets/minecraft/textures/block/bamboo_stage0.png") # bedrock -block(blockid=7, top_image="assets/minecraft/textures/block/bedrock.png") +modelblock(blockid=7, name='bedrock') +#glass +modelblock(blockid=20, name='glass') + +# TODO: There is no transparency information in the model json files. The png files do contain transparancy. Create static list for this data. # water, glass, and ice (no inner surfaces) # uses pseudo-ancildata found in iterate.c -@material(blockid=[8, 9, 20, 79, 95], data=list(range(512)), fluid=(8, 9), transparent=True, nospawn=True, solid=(79, 20, 95)) +@material(blockid=[8, 9, 79, 95], data=list(range(512)), fluid=(8, 9), transparent=True, nospawn=True, solid=(79, 20, 95)) def no_inner_surfaces(self, blockid, data): if blockid == 8 or blockid == 9: texture = self.load_water() - elif blockid == 20: - texture = self.load_image_texture("assets/minecraft/textures/block/glass.png") elif blockid == 95: texture = self.load_image_texture("assets/minecraft/textures/block/%s_stained_glass.png" % color_map[data & 0x0f]) else: @@ -1210,17 +1214,7 @@ def no_inner_surfaces(self, blockid, data): top = texture else: top = None - - if (data & 0b0001) == 1: - side1 = texture # top left - else: - side1 = None - - if (data & 0b1000) == 8: - side2 = texture # top right - else: - side2 = None - + if (data & 0b0010) == 2: side3 = texture # bottom left else: @@ -1238,6 +1232,7 @@ def no_inner_surfaces(self, blockid, data): img = self.build_full_block(top,None,None,side3,side4) return img +# TODO: generify rendering fluids @material(blockid=[10, 11], data=list(range(16)), fluid=True, transparent=False, nospawn=True) def lava(self, blockid, data): lavatex = self.load_lava() @@ -1247,19 +1242,18 @@ def lava(self, blockid, data): @material(blockid=12, data=list(range(2)), solid=True) def sand_blocks(self, blockid, data): if data == 0: # normal - img = self.build_block(self.load_image_texture("assets/minecraft/textures/block/sand.png"), self.load_image_texture("assets/minecraft/textures/block/sand.png")) - if data == 1: # red - img = self.build_block(self.load_image_texture("assets/minecraft/textures/block/red_sand.png"), self.load_image_texture("assets/minecraft/textures/block/red_sand.png")) - return img + return self.build_block_from_model('sand') + else: # red + return self.build_block_from_model('red_sand') # gravel -block(blockid=13, top_image="assets/minecraft/textures/block/gravel.png") +modelblock(blockid=13, name='gravel') # gold ore -block(blockid=14, top_image="assets/minecraft/textures/block/gold_ore.png") +modelblock(blockid=14, name='gold_ore') # iron ore -block(blockid=15, top_image="assets/minecraft/textures/block/iron_ore.png") +modelblock(blockid=15, name='iron_ore') # coal ore -block(blockid=16, top_image="assets/minecraft/textures/block/coal_ore.png") +modelblock(blockid=16, name='coal_ore') @material(blockid=[17, 162, 11306, 11307, 11308, 11309, 11310, 11311, 1008, 1009, 1126], data=list(range(12)), solid=True) From ffa786cbda7b21dc45d6f30c9743fa82e375106a Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Mon, 4 Jul 2022 17:40:51 +0200 Subject: [PATCH 09/34] added axis rotation --- overviewer_core/textures.py | 230 ++++++++++++++++++++++-------------- 1 file changed, 139 insertions(+), 91 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index cd12f57fa..6a381d8be 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -897,31 +897,56 @@ def build_block_from_model(self, modelname, blockstate={}): return img - # def determine_face(self, blockrotation, worldrotation, face): - # if rendered orientation is south or west -> draw front - # # if I want to draw the - def numvalue_orientation(self, orientation): return {'south': 0, 'west': 1, 'north': 2, 'east': 3}[orientation] def orientation_from_numvalue(self, orientation): return {0:'south', 1:'west', 2:'north', 3:'east'}[orientation] + # translates rotation to real face value def map_facing_to_real(self, blockfacing, targetblockface): if ((blockfacing in {'up','down'}) | (targetblockface in {'up','down'})): return targetblockface return self.orientation_from_numvalue((self.numvalue_orientation(targetblockface) + [0,3,2,1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2)*2) % 4) + + def map_axis_to_real(self, axis, textureface): + match axis: + case 'x': + return {'up':'north','north':'down','down':'south','south':'up','east':'east','west':'west'}[textureface] + case 'y': + return textureface + case 'z': + return {'up':'west','west':'down','down':'east','east':'up','north':'north','south':'south'}[textureface] + case _: + raise Exception() + + def axis_rotation(self, axis, face, texture): + match axis: + case 'x': + rotation = {'up':0,'north':0,'down':0,'south':0,'east':90,'west':90}[face] + return texture.rotate(rotation) + case 'y': + return texture + case 'z': + rotation = {'up':0,'west':0,'down':0,'east':0,'north':270,'south':270}[face] + return texture.rotate(rotation) + case _: + raise Exception() def draw_face(self, direction, elem, data, blockstate, modelname): textureface = direction if 'facing' in blockstate: textureface = self.map_facing_to_real(blockstate['facing'], direction) + if 'axis' in blockstate: + textureface = self.map_axis_to_real(blockstate['axis'], direction) texture = self.find_texture_from_model(elem['faces'][textureface]['texture'], data['textures']).copy() if 'uv' in elem['faces'][textureface]: print('uv defined in ' + modelname + ' as ' + str(elem['faces'][textureface]['uv'])) texture = self.crop_to_transparancy(texture, elem['faces'][textureface]['uv']) texture = self.adjust_rotation(textureface, texture, modelname) + if 'axis' in blockstate: + texture = self.axis_rotation(blockstate['axis'], direction, texture) texture = self.transform_texture(direction, texture, blockstate) texture = self.adjust_lighting(direction,texture) @@ -990,7 +1015,9 @@ def adjust_rotation(self, direction, texture, modelname): return texture.rotate(0) case _: raise Exception() - + +## In my quest to generify reading model json files I've found there is no simple way to deduce the BlockProperty (KNOWN, TRANSPARENT, SOLID, FLUID, NOSPAWN) of a block. Do you have any suggestion how I could detrmine these properties, short of just keeping a hard-coded list of these blocks? + ## ## The other big one: @material and associated framework ## @@ -1191,9 +1218,6 @@ def saplings(self, blockid, data): # bedrock modelblock(blockid=7, name='bedrock') -#glass -modelblock(blockid=20, name='glass') - # TODO: There is no transparency information in the model json files. The png files do contain transparancy. Create static list for this data. # water, glass, and ice (no inner surfaces) # uses pseudo-ancildata found in iterate.c @@ -1201,6 +1225,8 @@ def saplings(self, blockid, data): def no_inner_surfaces(self, blockid, data): if blockid == 8 or blockid == 9: texture = self.load_water() + elif blockid == 20: + texture = self.load_image_texture("assets/minecraft/textures/block/glass.png") elif blockid == 95: texture = self.load_image_texture("assets/minecraft/textures/block/%s_stained_glass.png" % color_map[data & 0x0f]) else: @@ -1258,90 +1284,112 @@ def sand_blocks(self, blockid, data): @material(blockid=[17, 162, 11306, 11307, 11308, 11309, 11310, 11311, 1008, 1009, 1126], data=list(range(12)), solid=True) def wood(self, blockid, data): - # extract orientation and wood type frorm data bits - wood_type = data & 3 - wood_orientation = data & 12 - if self.rotation == 1: - if wood_orientation == 4: wood_orientation = 8 - elif wood_orientation == 8: wood_orientation = 4 - elif self.rotation == 3: - if wood_orientation == 4: wood_orientation = 8 - elif wood_orientation == 8: wood_orientation = 4 - - # dictionary of blockid : { wood_type : (top, side) } - wood_tex = { - 17: { - 0: ("oak_log_top.png", "oak_log.png"), - 1: ("spruce_log_top.png", "spruce_log.png"), - 2: ("birch_log_top.png", "birch_log.png"), - 3: ("jungle_log_top.png", "jungle_log.png"), - }, - 162: { - 0: ("acacia_log_top.png", "acacia_log.png"), - 1: ("dark_oak_log_top.png", "dark_oak_log.png"), - }, - 11306: { - 0: ("stripped_oak_log_top.png", "stripped_oak_log.png"), - 1: ("stripped_spruce_log_top.png", "stripped_spruce_log.png"), - 2: ("stripped_birch_log_top.png", "stripped_birch_log.png"), - 3: ("stripped_jungle_log_top.png", "stripped_jungle_log.png"), - }, - 11307: { - 0: ("stripped_acacia_log_top.png", "stripped_acacia_log.png"), - 1: ("stripped_dark_oak_log_top.png", "stripped_dark_oak_log.png"), - }, - 11308: { - 0: ("oak_log.png", None), - 1: ("spruce_log.png", None), - 2: ("birch_log.png", None), - 3: ("jungle_log.png", None), - }, - 11309: { - 0: ("acacia_log.png", None), - 1: ("dark_oak_log.png", None), - }, - 11310: { - 0: ("stripped_oak_log.png", None), - 1: ("stripped_spruce_log.png", None), - 2: ("stripped_birch_log.png", None), - 3: ("stripped_jungle_log.png", None), - }, - 11311: { - 0: ("stripped_acacia_log.png", None), - 1: ("stripped_dark_oak_log.png", None), - }, - 1008: { - 0: ("warped_stem_top.png", "warped_stem.png"), - 1: ("warped_stem_top.png", "stripped_warped_stem.png"), - 2: ("crimson_stem_top.png", "crimson_stem.png"), - 3: ("crimson_stem_top.png", "stripped_crimson_stem.png"), - }, - 1009: { - 0: ("warped_stem.png", None), - 1: ("stripped_warped_stem.png", None), - 2: ("crimson_stem.png", None), - 3: ("stripped_crimson_stem.png", None), - }, - 1126: { - 0: ("mangrove_log_top.png", "mangrove_log.png"), - 1: ("stripped_mangrove_log_top.png", "stripped_mangrove_log.png"), - }, - } - - top_f, side_f = wood_tex[blockid].get(wood_type, wood_tex[blockid][0]) - if not side_f: - side_f = top_f - top = self.load_image_texture(BLOCKTEX + 'block/' + top_f) - side = self.load_image_texture(BLOCKTEX + 'block/' + side_f) - - # choose orientation and paste textures - if wood_orientation == 0: - return self.build_block(top, side) - elif wood_orientation == 4: # east-west orientation - return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90)) - elif wood_orientation == 8: # north-south orientation - return self.build_full_block(side, None, None, side.rotate(270), top) + type = data & 3 + + blockstate = {} + blockstate['axis'] = { 0 : 'y', 4: 'x', 8 : 'z'}[data & 12] + + if blockid == 17: + if type == 0: + return self.build_block_from_model('oak_log', blockstate) + if type == 1: + return self.build_block_from_model('spruce_log', blockstate) + if type == 2: + return self.build_block_from_model('birch_log', blockstate) + if type == 3: + return self.build_block_from_model('jungle_log', blockstate) + + if blockid == 162: + if type == 0: + return self.build_block_from_model('acacia_log', blockstate) + if type == 1: + return self.build_block_from_model('dark_oak_log', blockstate) + + if blockid == 11306: + if type == 0: + return self.build_block_from_model('stripped_oak_log', blockstate) + if type == 1: + return self.build_block_from_model('stripped_spruce_log', blockstate) + if type == 2: + return self.build_block_from_model('stripped_birch_log', blockstate) + if type == 3: + return self.build_block_from_model('stripped_jungle_log', blockstate) + + if blockid == 11307: + if type == 0: + return self.build_block_from_model('stripped_acacia_log', blockstate) + if type == 1: + return self.build_block_from_model('stripped_dark_oak_log', blockstate) + + if blockid == 11308: + if type == 0: + return self.build_block_from_model('oak_wood', blockstate) + if type == 1: + return self.build_block_from_model('spruce_wood', blockstate) + if type == 2: + return self.build_block_from_model('birch_wood', blockstate) + if type == 3: + return self.build_block_from_model('jungle_wood', blockstate) + + if blockid == 11309: + if type == 0: + return self.build_block_from_model('acacia_wood', blockstate) + if type == 1: + return self.build_block_from_model('dark_oak_wood', blockstate) + + if blockid == 11310: + if type == 0: + return self.build_block_from_model('stripped_oak_wood', blockstate) + if type == 1: + return self.build_block_from_model('stripped_spruce_wood', blockstate) + if type == 2: + return self.build_block_from_model('stripped_birch_wood', blockstate) + if type == 3: + return self.build_block_from_model('stripped_jungle_wood', blockstate) + + if blockid == 11311: + if type == 0: + return self.build_block_from_model('stripped_acacia_wood', blockstate) + if type == 1: + return self.build_block_from_model('stripped_dark_oak_wood', blockstate) + + if blockid == 1008: + if type == 0: + return self.build_block_from_model('warped_stem', blockstate) + if type == 1: + return self.build_block_from_model('stripped_warped_stem', blockstate) + if type == 2: + return self.build_block_from_model('crimson_stem', blockstate) + if type == 3: + return self.build_block_from_model('stripped_crimson_stem', blockstate) + + if blockid == 1009: + if type == 0: + return self.build_block_from_model('warped_hyphae', blockstate) + if type == 1: + return self.build_block_from_model('stripped_warped_hyphae', blockstate) + if type == 2: + return self.build_block_from_model('crimson_hyphae', blockstate) + if type == 3: + return self.build_block_from_model('stripped_crimson_hyphae', blockstate) + + if blockid == 1126: + if type == 0: + return self.build_block_from_model('mangrove_log', blockstate) + if type == 1: + return self.build_block_from_model('stripped_mangrove_log', blockstate) + + # # choose orientation and paste textures + # if wood_orientation == 0: + # return self.build_block(top, side) + # elif wood_orientation == 4: # east-west orientation + # return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90)) + # elif wood_orientation == 8: # north-south orientation + # return self.build_full_block(side, None, None, side.rotate(270), top) + + return self.build_block_from_model('redstone_block', blockstate) +# TODO: transparency @material(blockid=[18, 161], data=list(range(16)), transparent=True, solid=True) def leaves(self, blockid, data): # mask out the bits 4 and 8 From 7598fd4c68bf9d2e11019c43f21bd3c77b5efb30 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Tue, 5 Jul 2022 19:12:48 +0200 Subject: [PATCH 10/34] removed nodata --- overviewer_core/src/iterate.c | 37 +-- overviewer_core/src/overviewer.h | 1 - overviewer_core/textures.py | 529 +++++++++++++------------------ overviewer_core/world.py | 8 +- 4 files changed, 232 insertions(+), 343 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index b3251e92c..666e5a030 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -30,7 +30,6 @@ static PyObject* transparent_blocks = NULL; static PyObject* solid_blocks = NULL; static PyObject* fluid_blocks = NULL; static PyObject* nospawn_blocks = NULL; -static PyObject* nodata_blocks = NULL; PyObject* init_chunk_render(void) { @@ -76,9 +75,6 @@ PyObject* init_chunk_render(void) { nospawn_blocks = PyObject_GetAttrString(textures, "nospawn_blocks"); if (!nospawn_blocks) return NULL; - nodata_blocks = PyObject_GetAttrString(textures, "nodata_blocks"); - if (!nodata_blocks) - return NULL; block_properties = calloc(max_blockid, sizeof(uint8_t)); for (i = 0; i < max_blockid; i++) { @@ -94,8 +90,6 @@ PyObject* init_chunk_render(void) { block_properties[i] |= 1 << FLUID; if (PySequence_Contains(nospawn_blocks, block)) block_properties[i] |= 1 << NOSPAWN; - if (PySequence_Contains(nodata_blocks, block)) - block_properties[i] |= 1 << NODATA; Py_DECREF(block); } @@ -601,27 +595,18 @@ chunk_render(PyObject* self, PyObject* args) { continue; } - /* everything stored here will be a borrowed ref */ - - if (block_has_property(state.block, NODATA)) { - /* block shouldn't have data associated with it, set it to 0 */ - ancilData = 0; - state.block_data = 0; - state.block_pdata = 0; + /* block has associated data, use it */ + ancilData = getArrayByte3D(state.blockdatas, state.x, state.y, state.z); + state.block_data = ancilData; + /* block that need pseudo ancildata: + * grass, water, glass, chest, restone wire, + * ice, portal, iron bars, + * trapped chests, stairs */ + if (block_class_is_subset(state.block, block_class_ancil, block_class_ancil_len)) { + ancilData = generate_pseudo_data(&state, ancilData); + state.block_pdata = ancilData; } else { - /* block has associated data, use it */ - ancilData = getArrayByte3D(state.blockdatas, state.x, state.y, state.z); - state.block_data = ancilData; - /* block that need pseudo ancildata: - * grass, water, glass, chest, restone wire, - * ice, portal, iron bars, - * trapped chests, stairs */ - if (block_class_is_subset(state.block, block_class_ancil, block_class_ancil_len)) { - ancilData = generate_pseudo_data(&state, ancilData); - state.block_pdata = ancilData; - } else { - state.block_pdata = 0; - } + state.block_pdata = 0; } /* make sure our block info is in-bounds */ diff --git a/overviewer_core/src/overviewer.h b/overviewer_core/src/overviewer.h index e4c1beb7f..413cdb24c 100644 --- a/overviewer_core/src/overviewer.h +++ b/overviewer_core/src/overviewer.h @@ -131,7 +131,6 @@ typedef enum { SOLID, FLUID, NOSPAWN, - NODATA, } BlockProperty; /* globals set in init_chunk_render, here because they're used in block_has_property */ diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 6a381d8be..08243a92f 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -31,9 +31,6 @@ from . import util -BLOCKTEX = "assets/minecraft/textures/" -BLOCKMOD = "assets/minecraft/models/" - # global variables to collate information in @material decorators blockmap_generators = {} @@ -46,7 +43,6 @@ solid_blocks = set() fluid_blocks = set() nospawn_blocks = set() -nodata_blocks = set() # This is here for circular import reasons. @@ -838,7 +834,7 @@ def load_model(self, modelname): if modelname in self.models: return self.models[modelname] - fileobj = self.find_file(BLOCKMOD + modelname + '.json', verbose=logging.getLogger().isEnabledFor(logging.DEBUG)) + fileobj = self.find_file('assets/minecraft/models/' + modelname + '.json', verbose=logging.getLogger().isEnabledFor(logging.DEBUG)) self.models[modelname] = json.load(fileobj) fileobj.close() @@ -898,16 +894,38 @@ def build_block_from_model(self, modelname, blockstate={}): return img def numvalue_orientation(self, orientation): - return {'south': 0, 'west': 1, 'north': 2, 'east': 3}[orientation] + return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4,'down': 5}[orientation] def orientation_from_numvalue(self, orientation): - return {0:'south', 1:'west', 2:'north', 3:'east'}[orientation] + return {0:'south', 1:'west', 2:'north', 3:'east', 4:'up', 5:'down'}[orientation] # translates rotation to real face value + # facing is the blockproperty + # targetfacing is the direction in witch the north is rotated def map_facing_to_real(self, blockfacing, targetblockface): - if ((blockfacing in {'up','down'}) | (targetblockface in {'up','down'})): - return targetblockface - return self.orientation_from_numvalue((self.numvalue_orientation(targetblockface) + [0,3,2,1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2)*2) % 4) + if ((blockfacing in {'up','down'}) or (targetblockface in {'up','down'})): + if targetblockface == 'up': + resultface = 'up' + elif targetblockface == 'down': + resultface = 'up' # because there is no down texture + + elif blockfacing == 'down' and targetblockface == 'west': + resultface = 'west' + elif blockfacing == 'down' and targetblockface == 'east': + resultface = 'east' + elif blockfacing == 'down' and targetblockface == 'north': + resultface = 'up' # because there is no down texture + + + elif blockfacing == 'up' and targetblockface == 'north': + resultface = 'up' # because there is no down texture + elif blockfacing == 'up' and targetblockface == 'west': + resultface = 'west' + else: + raise Exception('unexpected facing direction: ' + blockfacing + ' ' + targetblockface) + else: + resultface = self.orientation_from_numvalue((self.numvalue_orientation(targetblockface) + [0,3,2,1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2)*2) % 4) + return resultface def map_axis_to_real(self, axis, textureface): match axis: @@ -923,7 +941,7 @@ def map_axis_to_real(self, axis, textureface): def axis_rotation(self, axis, face, texture): match axis: case 'x': - rotation = {'up':0,'north':0,'down':0,'south':0,'east':90,'west':90}[face] + rotation = {'up':90,'north':0,'down':0,'south':0,'east':90,'west':90}[face] return texture.rotate(rotation) case 'y': return texture @@ -941,12 +959,19 @@ def draw_face(self, direction, elem, data, blockstate, modelname): textureface = self.map_axis_to_real(blockstate['axis'], direction) texture = self.find_texture_from_model(elem['faces'][textureface]['texture'], data['textures']).copy() - if 'uv' in elem['faces'][textureface]: - print('uv defined in ' + modelname + ' as ' + str(elem['faces'][textureface]['uv'])) - texture = self.crop_to_transparancy(texture, elem['faces'][textureface]['uv']) - texture = self.adjust_rotation(textureface, texture, modelname) + # if 'uv' in elem['faces'][textureface]: + # TODO: implement uv + # print('uv defined in ' + modelname + ' as ' + str(elem['faces'][textureface]['uv'])) + # texture = self.crop_to_transparancy(texture, elem['faces'][textureface]['uv']) + # texture = self.adjust_texture_rotation(textureface, texture, modelname) + # if 'rotation' in elem: + # TODO: implement rotation + # rotation only exists as 45, 22,5 -22,5 and - 45 + # print('rotation: ' + str(elem['rotation']['angle'])) + # texture = self.transform_image_angle(texture, elem['rotation']['angle']*-1) if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) + # else: texture = self.transform_texture(direction, texture, blockstate) texture = self.adjust_lighting(direction,texture) @@ -970,16 +995,16 @@ def adjust_lighting(self, direction, texture): raise Exception() def transform_texture(self, direction, texture, blockstate): + top_rotation = 0 + if 'facing' in blockstate: + top_rotation = [180, 90, 0, 270, 180, 180][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 6] match direction: case 'down' | 'up': - top_rotation = 0 - if 'facing' in blockstate: - top_rotation = [180, 90, 0, 270][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] return self.transform_image_top(texture.rotate(top_rotation)) case 'north'| 'south': - texture = self.transform_image_side(texture) + texture = self.transform_image_side(texture.rotate(top_rotation)) case 'west' | 'east': - texture = self.transform_image_side(texture) + texture = self.transform_image_side(texture.rotate(top_rotation)) texture = texture.transpose(Image.FLIP_LEFT_RIGHT) case _: raise Exception() @@ -990,7 +1015,7 @@ def find_texture_from_model(self, face, textureset): if face.startswith('#'): return self.find_texture_from_model(textureset[face[1:]], textureset) else: - return self.load_image_texture(BLOCKTEX + re.sub('.*:','',face) + '.png') + return self.load_image_texture("assets/minecraft/textures/" + re.sub('.*:','',face) + '.png') def crop_to_transparancy(self, img, area): # top @@ -1003,20 +1028,9 @@ def crop_to_transparancy(self, img, area): ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) return img - def adjust_rotation(self, direction, texture, modelname): - match direction: - case 'down' | 'up': - return texture.rotate(90) - case 'south': - return texture.rotate(90) - case 'west': - return texture.rotate(0) - case 'north' | 'east': - return texture.rotate(0) - case _: - raise Exception() - -## In my quest to generify reading model json files I've found there is no simple way to deduce the BlockProperty (KNOWN, TRANSPARENT, SOLID, FLUID, NOSPAWN) of a block. Do you have any suggestion how I could detrmine these properties, short of just keeping a hard-coded list of these blocks? + def adjust_texture_rotation(self, direction, texture, modelname): + rotation = {'up':90,'north':0,'down':90,'south':90,'east':0,'west':0}[direction] + return texture.rotate(rotation) ## ## The other big one: @material and associated framework @@ -1026,7 +1040,7 @@ def adjust_rotation(self, direction, texture, modelname): # the material registration decorator def material(blockid=[], data=[0], **kwargs): # mapping from property name to the set to store them in - properties = {"transparent" : transparent_blocks, "solid" : solid_blocks, "fluid" : fluid_blocks, "nospawn" : nospawn_blocks, "nodata" : nodata_blocks} + properties = {"transparent" : transparent_blocks, "solid" : solid_blocks, "fluid" : fluid_blocks, "nospawn" : nospawn_blocks} # make sure blockid and data are iterable try: @@ -1071,20 +1085,28 @@ def func_wrapper(texobj, blockid, data): return func_wrapper return inner_material -# shortcut function for pure blocks, default to solid, nodata -def modelblock(blockid=[], name=None): - +def transparentmodelblock(blockid=[], name=None, **kwargs): + new_kwargs = {'transparent' : True} + new_kwargs.update(kwargs) + return modelblock(blockid=blockid, name=name, **new_kwargs) + +def solidmodelblock(blockid=[], name=None, **kwargs): + new_kwargs = {'solid' : True} + new_kwargs.update(kwargs) + return modelblock(blockid=blockid, name=name, **new_kwargs) + +def modelblock(blockid=[], name=None, **kwargs): if name is None: raise ValueError("block name was not provided") - @material(blockid=blockid) + @material(blockid=blockid, **kwargs) def inner_block(self, unused_id, unused_data): return self.build_block_from_model(name) return inner_block -# shortcut function for pure blocks, default to solid, nodata +# shortcut function for pure blocks, default to solid def block(blockid=[], top_image=None, side_image=None, **kwargs): - new_kwargs = {'solid' : True, 'nodata' : True} + new_kwargs = {'solid' : True} new_kwargs.update(kwargs) if top_image is None: @@ -1098,9 +1120,9 @@ def inner_block(self, unused_id, unused_data): return self.build_block(self.load_image_texture(top_image), self.load_image_texture(side_image)) return inner_block -# shortcut function for sprite blocks, defaults to transparent, nodata +# shortcut function for sprite blocks, defaults to transparent def sprite(blockid=[], imagename=None, **kwargs): - new_kwargs = {'transparent' : True, 'nodata' : True} + new_kwargs = {'transparent' : True} new_kwargs.update(kwargs) if imagename is None: @@ -1111,9 +1133,9 @@ def inner_sprite(self, unused_id, unused_data): return self.build_sprite(self.load_image_texture(imagename)) return inner_sprite -# shortcut function for billboard blocks, defaults to transparent, nodata +# shortcut function for billboard blocks, defaults to transparent def billboard(blockid=[], imagename=None, **kwargs): - new_kwargs = {'transparent' : True, 'nodata' : True} + new_kwargs = {'transparent' : True} new_kwargs.update(kwargs) if imagename is None: @@ -1167,7 +1189,7 @@ def dirt_blocks(self, blockid, data): if data == 2: return self.build_block_from_model('podzol') -modelblock(blockid=4, name='cobblestone') +solidmodelblock(blockid=4, name='cobblestone') # wooden planks @material(blockid=5, data=list(range(8)), solid=True) @@ -1193,9 +1215,9 @@ def wooden_planks(self, blockid, data): def saplings(self, blockid, data): # TODO: generify block/cross # usual saplings - tex = self.load_image_texture("assets/minecraft/textures/block/oak_sapling.png") - - if data & 0x3 == 1: # spruce sapling + if data & 0x3 == 0: + tex = self.load_image_texture("assets/minecraft/textures/block/oak_sapling.png") + elif data & 0x3 == 1: # spruce sapling tex = self.load_image_texture("assets/minecraft/textures/block/spruce_sapling.png") elif data & 0x3 == 2: # birch sapling tex = self.load_image_texture("assets/minecraft/textures/block/birch_sapling.png") @@ -1205,23 +1227,26 @@ def saplings(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/acacia_sapling.png") elif data & 0x3 == 5: # dark oak/roofed oak/big oak sapling tex = self.load_image_texture("assets/minecraft/textures/block/dark_oak_sapling.png") + else: + raise Exception('unknown sapling id ' + str(data)) return self.build_sprite(tex) -sprite(blockid=11385, imagename="assets/minecraft/textures/block/oak_sapling.png") -sprite(blockid=11386, imagename="assets/minecraft/textures/block/spruce_sapling.png") -sprite(blockid=11387, imagename="assets/minecraft/textures/block/birch_sapling.png") -sprite(blockid=11388, imagename="assets/minecraft/textures/block/jungle_sapling.png") -sprite(blockid=11389, imagename="assets/minecraft/textures/block/acacia_sapling.png") -sprite(blockid=11390, imagename="assets/minecraft/textures/block/dark_oak_sapling.png") +transparentmodelblock(blockid=11385, name="oak_sapling") +transparentmodelblock(blockid=11386, name="spruce_sapling") +transparentmodelblock(blockid=11387, name="birch_sapling") +transparentmodelblock(blockid=11388, name="jungle_sapling") +transparentmodelblock(blockid=11389, name="acacia_sapling") +transparentmodelblock(blockid=11390, name="dark_oak_sapling") + sprite(blockid=11413, imagename="assets/minecraft/textures/block/bamboo_stage0.png") # bedrock -modelblock(blockid=7, name='bedrock') +solidmodelblock(blockid=7, name='bedrock') # TODO: There is no transparency information in the model json files. The png files do contain transparancy. Create static list for this data. # water, glass, and ice (no inner surfaces) # uses pseudo-ancildata found in iterate.c -@material(blockid=[8, 9, 79, 95], data=list(range(512)), fluid=(8, 9), transparent=True, nospawn=True, solid=(79, 20, 95)) +@material(blockid=[8, 9, 20, 79, 95], data=list(range(512)), fluid=(8, 9), transparent=True, nospawn=True, solid=(79, 20, 95)) def no_inner_surfaces(self, blockid, data): if blockid == 8 or blockid == 9: texture = self.load_water() @@ -1273,13 +1298,13 @@ def sand_blocks(self, blockid, data): return self.build_block_from_model('red_sand') # gravel -modelblock(blockid=13, name='gravel') +solidmodelblock(blockid=13, name='gravel') # gold ore -modelblock(blockid=14, name='gold_ore') +solidmodelblock(blockid=14, name='gold_ore') # iron ore -modelblock(blockid=15, name='iron_ore') +solidmodelblock(blockid=15, name='iron_ore') # coal ore -modelblock(blockid=16, name='coal_ore') +solidmodelblock(blockid=16, name='coal_ore') @material(blockid=[17, 162, 11306, 11307, 11308, 11309, 11310, 11311, 1008, 1009, 1126], data=list(range(12)), solid=True) @@ -1378,14 +1403,6 @@ def wood(self, blockid, data): return self.build_block_from_model('mangrove_log', blockstate) if type == 1: return self.build_block_from_model('stripped_mangrove_log', blockstate) - - # # choose orientation and paste textures - # if wood_orientation == 0: - # return self.build_block(top, side) - # elif wood_orientation == 4: # east-west orientation - # return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90)) - # elif wood_orientation == 8: # north-south orientation - # return self.build_full_block(side, None, None, side.rotate(270), top) return self.build_block_from_model('redstone_block', blockstate) @@ -1415,12 +1432,11 @@ def leaves(self, blockid, data): return self.build_block(t, t) # sponge -block(blockid=19, top_image="assets/minecraft/textures/block/sponge.png") +solidmodelblock(blockid=19, name='sponge') # lapis lazuli ore -block(blockid=21, top_image="assets/minecraft/textures/block/lapis_ore.png") +solidmodelblock(blockid=21, name="lapis_ore") # lapis lazuli block -block(blockid=22, top_image="assets/minecraft/textures/block/lapis_block.png") - +solidmodelblock(blockid=22, name="lapis_block") # dispenser, dropper, furnace, blast furnace, and smoker @material(blockid=[23, 61, 158, 11362, 11364], data=list(range(14)), solid=True) @@ -1490,11 +1506,11 @@ def furnaces(self, blockid, data): def sandstone(self, blockid, data): top = self.load_image_texture("assets/minecraft/textures/block/sandstone_top.png") if data == 0: # normal - return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/sandstone.png")) + return self.build_block_from_model('sandstone') if data == 1: # hieroglyphic - return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/chiseled_sandstone.png")) + return self.build_block_from_model("chiseled_sandstone") if data == 2: # soft - return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/cut_sandstone.png")) + return self.build_block_from_model("cut_sandstone") # red sandstone @material(blockid=179, data=list(range(3)), solid=True) @@ -1509,7 +1525,7 @@ def sandstone(self, blockid, data): return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/cut_red_sandstone.png")) # note block -block(blockid=25, top_image="assets/minecraft/textures/block/note_block.png") +solidmodelblock(blockid=25, name="note_block") # Bed @material(blockid=26, data=list(range(256)), transparent=True, nospawn=True) @@ -1903,9 +1919,9 @@ def flower(self, blockid, data): sprite(blockid=1019, imagename="assets/minecraft/textures/block/crimson_roots.png") # block of gold -block(blockid=41, top_image="assets/minecraft/textures/block/gold_block.png") +solidmodelblock(blockid=41, name="gold_block") # block of iron -block(blockid=42, top_image="assets/minecraft/textures/block/iron_block.png") +solidmodelblock(blockid=42, name="iron_block") # double slabs and slabs # these wooden slabs are unobtainable without cheating, they are still @@ -2039,15 +2055,15 @@ def slabs(self, blockid, data): return self.build_slab_block(top, side, data & 8 == 8); # brick block -block(blockid=45, top_image="assets/minecraft/textures/block/bricks.png") +solidmodelblock(blockid=45, name="bricks") # TNT -block(blockid=46, top_image="assets/minecraft/textures/block/tnt_top.png", side_image="assets/minecraft/textures/block/tnt_side.png", nospawn=True) +solidmodelblock(blockid=46, name="tnt", nospawn=True) # bookshelf -block(blockid=47, top_image="assets/minecraft/textures/block/oak_planks.png", side_image="assets/minecraft/textures/block/bookshelf.png") +solidmodelblock(blockid=47, name="bookshelf") # moss stone -block(blockid=48, top_image="assets/minecraft/textures/block/mossy_cobblestone.png") +solidmodelblock(blockid=48, name="mossy_cobblestone") # obsidian -block(blockid=49, top_image="assets/minecraft/textures/block/obsidian.png") +solidmodelblock(blockid=49, name="obsidian") # torch, redstone torch (off), redstone torch(on), soul_torch @material(blockid=[50, 75, 76, 1039], data=[1, 2, 3, 4, 5], transparent=True) @@ -2283,10 +2299,10 @@ def fire(self, blockid, data): return img # monster spawner -block(blockid=52, top_image="assets/minecraft/textures/block/spawner.png", transparent=True) +transparentmodelblock(blockid=52, name="spawner") # wooden, cobblestone, red brick, stone brick, netherbrick, sandstone, spruce, birch, -# jungle, quartz, red sandstone, purper_stairs, crimson_stairs, warped_stairs, (dark) prismarine, +# jungle, quartz, red sandstone, purpur_stairs, crimson_stairs, warped_stairs, (dark) prismarine, # mossy brick and mossy cobblestone, stone smooth_quartz # polished_granite polished_andesite polished_diorite granite diorite andesite end_stone_bricks red_nether_brick stairs # smooth_red_sandstone blackstone polished_blackstone polished_blackstone_brick @@ -2754,14 +2770,13 @@ def wire(self, blockid, data): return img # diamond ore -block(blockid=56, top_image="assets/minecraft/textures/block/diamond_ore.png") +solidmodelblock(blockid=56, name="diamond_ore") # diamond block -block(blockid=57, top_image="assets/minecraft/textures/block/diamond_block.png") - +solidmodelblock(blockid=57, name="diamond_block") # Table blocks with no facing or other properties where sides are not all the same # Includes: Crafting table, fletching table, cartography table, smithing table -@material(blockid=[58, 11359, 11360, 11361], solid=True, nodata=True) +@material(blockid=[58, 11359, 11360, 11361], solid=True) def block_table(self, blockid, data): block_name = {58: "crafting_table", 11359: "fletching_table", @@ -3618,7 +3633,7 @@ def pressure_plate(self, blockid, data): return img # normal and glowing redstone ore -block(blockid=[73, 74], top_image="assets/minecraft/textures/block/redstone_ore.png") +solidmodelblock(blockid=[73, 74], name="redstone_ore") # stone and wood buttons @material(blockid=(77,143,11326,11327,11328,11329,11330,1034,11515,11516), data=list(range(16)), transparent=True) @@ -3830,7 +3845,7 @@ def snow(self, blockid, data): return img # snow block -block(blockid=80, top_image="assets/minecraft/textures/block/snow.png") +solidmodelblock(blockid=80, name="snow_block") # cactus @material(blockid=81, data=list(range(15)), transparent=True, solid=True, nospawn=True) @@ -3858,7 +3873,7 @@ def cactus(self, blockid, data): return img # clay block -block(blockid=82, top_image="assets/minecraft/textures/block/clay.png") +solidmodelblock(blockid=82, name="clay") # sugar cane @material(blockid=83, data=list(range(16)), transparent=True) @@ -3866,10 +3881,7 @@ def sugar_cane(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/sugar_cane.png") return self.build_sprite(tex) -# jukebox -@material(blockid=84, data=list(range(16)), solid=True) -def jukebox(self, blockid, data): - return self.build_block(self.load_image_texture("assets/minecraft/textures/block/jukebox_top.png"), self.load_image_texture("assets/minecraft/textures/block/note_block.png")) +solidmodelblock(blockid=84, name="jukebox") # nether and normal fences @material(blockid=[85, 188, 189, 190, 191, 192, 113, 511, 512], data=list(range(16)), transparent=True, nospawn=True) @@ -4004,56 +4016,30 @@ def draw_west(): return img -# pumpkin -@material(blockid=[86, 91,11300], data=list(range(4)), solid=True) -def pumpkin(self, blockid, data): # pumpkins, jack-o-lantern - # rotation - if self.rotation == 1: - if data == 0: data = 1 - elif data == 1: data = 2 - elif data == 2: data = 3 - elif data == 3: data = 0 - elif self.rotation == 2: - if data == 0: data = 2 - elif data == 1: data = 3 - elif data == 2: data = 0 - elif data == 3: data = 1 - elif self.rotation == 3: - if data == 0: data = 3 - elif data == 1: data = 0 - elif data == 2: data = 1 - elif data == 3: data = 2 - - # texture generation - top = self.load_image_texture("assets/minecraft/textures/block/pumpkin_top.png") - frontName = {86: "assets/minecraft/textures/block/pumpkin_side.png", - 91: "assets/minecraft/textures/block/jack_o_lantern.png", - 11300: "assets/minecraft/textures/block/carved_pumpkin.png" - }[blockid] - front = self.load_image_texture(frontName) - side = self.load_image_texture("assets/minecraft/textures/block/pumpkin_side.png") - - if data == 0: # pointing west - img = self.build_full_block(top, None, None, side, front) - - elif data == 1: # pointing north - img = self.build_full_block(top, None, None, front, side) +solidmodelblock(blockid=86, name='pumpkin') - else: # in any other direction the front can't be seen - img = self.build_full_block(top, None, None, side, side) +@material(blockid=91, data=list(range(4)), solid=True) +def jack_o_lantern(self, blockid, data): + # normalize data so it can be used by a generic method + blockstate = {} + blockstate['facing'] = {0:'south', 1:'west', 2:'north', 3:'east'}[data] + return self.build_block_from_model('jack_o_lantern', blockstate) - return img +@material(blockid=11300, data=list(range(4)), solid=True) +def carved_pumpkin(self, blockid, data): + # normalize data so it can be used by a generic method + blockstate = {} + blockstate['facing'] = {0:'south', 1:'west', 2:'north', 3:'east'}[data] + return self.build_block_from_model('carved_pumpkin', blockstate) # netherrack -block(blockid=87, top_image="assets/minecraft/textures/block/netherrack.png") - +solidmodelblock(blockid=87, name="netherrack") # soul sand -block(blockid=88, top_image="assets/minecraft/textures/block/soul_sand.png") - +solidmodelblock(blockid=88, name="soul_sand") # glowstone -block(blockid=89, top_image="assets/minecraft/textures/block/glowstone.png") +solidmodelblock(blockid=89, name="glowstone") # shroomlight -block(blockid=1011, top_image="assets/minecraft/textures/block/shroomlight.png") +solidmodelblock(blockid=1011, name="shroomlight") # portal @material(blockid=90, data=[1, 2, 4, 5, 8, 10], transparent=True) @@ -4476,34 +4462,29 @@ def trapdoor(self, blockid, data): @material(blockid=97, data=list(range(3)), solid=True) def hidden_silverfish(self, blockid, data): if data == 0: # stone - t = self.load_image_texture("assets/minecraft/textures/block/stone.png") + return self.build_block_from_model("stone") elif data == 1: # cobblestone - t = self.load_image_texture("assets/minecraft/textures/block/cobblestone.png") + return self.build_block_from_model("cobblestone") elif data == 2: # stone brick - t = self.load_image_texture("assets/minecraft/textures/block/stone_bricks.png") - - img = self.build_block(t, t) - - return img + return self.build_block_from_model("stone_bricks") + + raise Exception('unknown hidden silverfish block: ' + str(data)) # stone brick @material(blockid=98, data=list(range(4)), solid=True) def stone_brick(self, blockid, data): if data == 0: # normal - t = self.load_image_texture("assets/minecraft/textures/block/stone_bricks.png") + return self.build_block_from_model("stone_bricks") elif data == 1: # mossy - t = self.load_image_texture("assets/minecraft/textures/block/mossy_stone_bricks.png") + return self.build_block_from_model("mossy_stone_bricks") elif data == 2: # cracked - t = self.load_image_texture("assets/minecraft/textures/block/cracked_stone_bricks.png") + return self.build_block_from_model("cracked_stone_bricks") elif data == 3: # "circle" stone brick - t = self.load_image_texture("assets/minecraft/textures/block/chiseled_stone_bricks.png") - - img = self.build_full_block(t, None, None, t, t) - - return img + return self.build_block_from_model("chiseled_stone_bricks") + raise Exception('unknown stone brick block: ' + str(data)) -# huge brown/red mushrooms, and mushroom stems +# TODO: minecraft:block/template_single_face have faces set in blockstate, and relevant textures are not available in the model json @material(blockid=[99, 100, 139], data=list(range(64)), solid=True) def huge_mushroom(self, blockid, data): # Re-arrange the bits in data based on self.rotation @@ -4518,12 +4499,6 @@ def huge_mushroom(self, blockid, data): 3: [6, 5, 1, 4, 3, 2]} new_data = 0 - # Add the ith bit to new_data then shift left one at a time, - # re-ordering data's bits in the order specified in bit_map - for i in bit_map[self.rotation]: - new_data = new_data << 1 - new_data |= (data >> (i - 1)) & 1 - data = new_data # texture generation texture_map = {99: "brown_mushroom_block", @@ -4540,7 +4515,6 @@ def huge_mushroom(self, blockid, data): return self.build_full_block(side_up, None, None, side_west, side_south) - # iron bars and glass pane # TODO glass pane is not a sprite, it has a texture for the side, # at the moment is not used @@ -4611,7 +4585,7 @@ def draw_bottom_left(): return img # melon -block(blockid=103, top_image="assets/minecraft/textures/block/melon_top.png", side_image="assets/minecraft/textures/block/melon_side.png", solid=True) +solidmodelblock(blockid=103, name="melon") # pumpkin and melon stem # TODO To render it as in game needs from pseudo data and ancil data: @@ -4779,11 +4753,10 @@ def fence_gate(self, blockid, data): return img # mycelium -block(blockid=110, top_image="assets/minecraft/textures/block/mycelium_top.png", side_image="assets/minecraft/textures/block/mycelium_side.png") +solidmodelblock(blockid=110, name="mycelium") # warped_nylium & crimson_nylium -block(blockid=1006, top_image="assets/minecraft/textures/block/warped_nylium.png", side_image="assets/minecraft/textures/block/warped_nylium_side.png") -block(blockid=1007, top_image="assets/minecraft/textures/block/crimson_nylium.png", side_image="assets/minecraft/textures/block/crimson_nylium_side.png") - +solidmodelblock(blockid=1006, name="warped_nylium") +solidmodelblock(blockid=1007, name="crimson_nylium") # lilypad # At the moment of writing this lilypads has no ancil data and their @@ -4807,15 +4780,12 @@ def lilypad(self, blockid, data): @material(blockid=112, data=list(range(3)), solid=True) def nether_bricks(self, blockid, data): if data == 0: # normal - t = self.load_image_texture("assets/minecraft/textures/block/nether_bricks.png") + return self.build_block_from_model('nether_bricks') elif data == 1: # cracked - t = self.load_image_texture("assets/minecraft/textures/block/cracked_nether_bricks.png") + return self.build_block_from_model('cracked_nether_bricks') elif data == 2: # chiseled - t = self.load_image_texture("assets/minecraft/textures/block/chiseled_nether_bricks.png") - - img = self.build_full_block(t, None, None, t, t) - - return img + return self.build_block_from_model('chiseled_nether_bricks') + raise Exception('unexpected nether brick data: ' + str(data)) # nether wart @material(blockid=115, data=list(range(4)), transparent=True) @@ -4834,7 +4804,7 @@ def nether_wart(self, blockid, data): # enchantment table # TODO there's no book at the moment -@material(blockid=116, transparent=True, nodata=True) +@material(blockid=116, transparent=True) def enchantment_table(self, blockid, data): # no book at the moment top = self.load_image_texture("assets/minecraft/textures/block/enchanting_table_top.png") @@ -4883,7 +4853,7 @@ def cauldron(self, blockid, data): # end portal and end_gateway -@material(blockid=[119,209], transparent=True, nodata=True) +@material(blockid=[119,209], transparent=True) def end_portal(self, blockid, data): img = Image.new("RGBA", (24,24), self.bgcolor) # generate a black texure with white, blue and grey dots resembling stars @@ -4931,17 +4901,17 @@ def end_portal_frame(self, blockid, data): # end stone -block(blockid=121, top_image="assets/minecraft/textures/block/end_stone.png") +solidmodelblock(blockid=121, name="end_stone") # dragon egg # NOTE: this isn't a block, but I think it's better than nothing -block(blockid=122, top_image="assets/minecraft/textures/block/dragon_egg.png") +transparentmodelblock(blockid=122, name="dragon_egg") # inactive redstone lamp -block(blockid=123, top_image="assets/minecraft/textures/block/redstone_lamp.png") +solidmodelblock(blockid=123, name="redstone_lamp") # active redstone lamp -block(blockid=124, top_image="assets/minecraft/textures/block/redstone_lamp_on.png") +solidmodelblock(blockid=124, name="redstone_lamp_on") # daylight sensor. @material(blockid=[151,178], transparent=True) @@ -5008,10 +4978,10 @@ def wooden_slabs(self, blockid, data): return self.build_slab_block(top, side, data & 8 == 8); # emerald ore -block(blockid=129, top_image="assets/minecraft/textures/block/emerald_ore.png") +solidmodelblock(blockid=129, name="emerald_ore") # emerald block -block(blockid=133, top_image="assets/minecraft/textures/block/emerald_block.png") +solidmodelblock(blockid=133, name="emerald_block") # cocoa plant @material(blockid=127, data=list(range(12)), transparent=True) @@ -5094,27 +5064,14 @@ def cocoa_plant(self, blockid, data): return img -# command block -@material(blockid=[137,210,211], solid=True, nodata=True) -def command_block(self, blockid, data): - if blockid == 210: - front = self.load_image_texture("assets/minecraft/textures/block/repeating_command_block_front.png") - side = self.load_image_texture("assets/minecraft/textures/block/repeating_command_block_side.png") - back = self.load_image_texture("assets/minecraft/textures/block/repeating_command_block_back.png") - elif blockid == 211: - front = self.load_image_texture("assets/minecraft/textures/block/chain_command_block_front.png") - side = self.load_image_texture("assets/minecraft/textures/block/chain_command_block_side.png") - back = self.load_image_texture("assets/minecraft/textures/block/chain_command_block_back.png") - else: - front = self.load_image_texture("assets/minecraft/textures/block/command_block_front.png") - side = self.load_image_texture("assets/minecraft/textures/block/command_block_side.png") - back = self.load_image_texture("assets/minecraft/textures/block/command_block_back.png") - return self.build_full_block(side, side, back, front, side) +solidmodelblock(blockid=137, name='command_block') +solidmodelblock(blockid=210, name='repeating_command_block') +solidmodelblock(blockid=211, name='chain_command_block') # beacon block # at the moment of writing this, it seems the beacon block doens't use # the data values -@material(blockid=138, transparent=True, nodata = True) +@material(blockid=138, transparent=True) def beacon(self, blockid, data): # generate the three pieces of the block t = self.load_image_texture("assets/minecraft/textures/block/glass.png") @@ -5394,40 +5351,26 @@ def anvil(self, blockid, data): return img - # block of redstone -block(blockid=152, top_image="assets/minecraft/textures/block/redstone_block.png") +solidmodelblock(blockid=152, name="redstone_block") # nether quartz ore -block(blockid=153, top_image="assets/minecraft/textures/block/nether_quartz_ore.png") +solidmodelblock(blockid=153, name="nether_quartz_ore") # block of quartz @material(blockid=155, data=list(range(5)), solid=True) def quartz_block(self, blockid, data): - if data in (0,1): # normal and chiseled quartz block - if data == 0: - top = self.load_image_texture("assets/minecraft/textures/block/quartz_block_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/quartz_block_side.png") - else: - top = self.load_image_texture("assets/minecraft/textures/block/chiseled_quartz_block_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/chiseled_quartz_block.png") - return self.build_block(top, side) - - # pillar quartz block with orientation - top = self.load_image_texture("assets/minecraft/textures/block/quartz_pillar_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/quartz_pillar.png").copy() - if data == 2: # vertical - return self.build_block(top, side) - elif data == 3: # north-south oriented - if self.rotation in (0,2): - return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90)) - return self.build_full_block(side, None, None, side.rotate(90), top) - - elif data == 4: # east-west oriented - if self.rotation in (0,2): - return self.build_full_block(side, None, None, side.rotate(90), top) - return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90)) + if data == 0: + return self.build_block_from_model('quartz_block') + elif data == 1: + return self.build_block_from_model('chiseled_quartz_block') + elif data == 2: + return self.build_block_from_model('quartz_pillar', blockstate={'axis':'y'}) + elif data == 3: + return self.build_block_from_model('quartz_pillar', blockstate={'axis':'x'}) + elif data == 4: + return self.build_block_from_model('quartz_pillar', blockstate={'axis':'z'}) # hopper @material(blockid=154, data=list(range(4)), transparent=True) @@ -5454,47 +5397,27 @@ def hopper(self, blockid, data): return img # slime block -block(blockid=165, top_image="assets/minecraft/textures/block/slime_block.png") +transparentmodelblock(blockid=165, name="slime_block") # prismarine block @material(blockid=168, data=list(range(3)), solid=True) def prismarine_block(self, blockid, data): - - if data == 0: # prismarine - t = self.load_image_texture("assets/minecraft/textures/block/prismarine.png") - elif data == 1: # prismarine bricks - t = self.load_image_texture("assets/minecraft/textures/block/prismarine_bricks.png") - elif data == 2: # dark prismarine - t = self.load_image_texture("assets/minecraft/textures/block/dark_prismarine.png") - - img = self.build_block(t, t) - - return img + if data == 0: # prismarine + t = self.build_block_from_model("prismarine") + elif data == 1: # prismarine bricks + t = self.build_block_from_model("prismarine_bricks") + elif data == 2: # dark prismarine + t = self.build_block_from_model("dark_prismarine") + else: + raise Exception('unexpected prismarine data: ' + str(data)) # sea lantern -block(blockid=169, top_image="assets/minecraft/textures/block/sea_lantern.png") +solidmodelblock(blockid=169, name="sea_lantern") # hay block -@material(blockid=170, data=list(range(9)), solid=True) +@material(blockid=170, data=list(range(3)), solid=True) def hayblock(self, blockid, data): - top = self.load_image_texture("assets/minecraft/textures/block/hay_block_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/hay_block_side.png") - - if self.rotation == 1: - if data == 4: data = 8 - elif data == 8: data = 4 - elif self.rotation == 3: - if data == 4: data = 8 - elif data == 8: data = 4 - - # choose orientation and paste textures - if data == 4: # east-west orientation - return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90)) - elif data == 8: # north-south orientation - return self.build_full_block(side, None, None, side.rotate(90), top) - else: - return self.build_block(top, side) - + return self.build_block_from_model('hay_block', blockstate = {'axis': ({ 0 : 'y', 1: 'x', 2 : 'z'}[data])}) # carpet - wool block that's small? @material(blockid=171, data=list(range(17)), transparent=True) @@ -5507,42 +5430,40 @@ def carpet(self, blockid, data): return self.build_full_block((texture,15),texture,texture,texture,texture) #clay block -block(blockid=172, top_image="assets/minecraft/textures/block/terracotta.png") +solidmodelblock(blockid=172, name="terracotta") #stained hardened clay @material(blockid=159, data=list(range(16)), solid=True) def stained_clay(self, blockid, data): - texture = self.load_image_texture("assets/minecraft/textures/block/%s_terracotta.png" % color_map[data]) - - return self.build_block(texture,texture) + return self.build_block_from_model("%s_terracotta" % color_map[data]) #coal block -block(blockid=173, top_image="assets/minecraft/textures/block/coal_block.png") +solidmodelblock(blockid=173, name="coal_block") # packed ice block -block(blockid=174, top_image="assets/minecraft/textures/block/packed_ice.png") +solidmodelblock(blockid=174, name="packed_ice") #blue ice -block(blockid=11312, top_image="assets/minecraft/textures/block/blue_ice.png") +solidmodelblock(blockid=11312, name="blue_ice") #smooth stones -block(blockid=11313, top_image="assets/minecraft/textures/block/smooth_stone.png") # stone -block(blockid=11314, top_image="assets/minecraft/textures/block/sandstone_top.png") # sandstone -block(blockid=11315, top_image="assets/minecraft/textures/block/red_sandstone_top.png") # red sandstone +solidmodelblock(blockid=11313, name="smooth_stone") +solidmodelblock(blockid=11314, name="sandstone") +solidmodelblock(blockid=11315, name="red_sandstone") #coral blocks -block(blockid=11316, top_image="assets/minecraft/textures/block/brain_coral_block.png") -block(blockid=11317, top_image="assets/minecraft/textures/block/bubble_coral_block.png") -block(blockid=11318, top_image="assets/minecraft/textures/block/fire_coral_block.png") -block(blockid=11319, top_image="assets/minecraft/textures/block/horn_coral_block.png") -block(blockid=11320, top_image="assets/minecraft/textures/block/tube_coral_block.png") +solidmodelblock(blockid=11316, name="brain_coral_block") +solidmodelblock(blockid=11317, name="bubble_coral_block") +solidmodelblock(blockid=11318, name="fire_coral_block") +solidmodelblock(blockid=11319, name="horn_coral_block") +solidmodelblock(blockid=11320, name="tube_coral_block") #dead coral blocks -block(blockid=11321, top_image="assets/minecraft/textures/block/dead_brain_coral_block.png") -block(blockid=11322, top_image="assets/minecraft/textures/block/dead_bubble_coral_block.png") -block(blockid=11323, top_image="assets/minecraft/textures/block/dead_fire_coral_block.png") -block(blockid=11324, top_image="assets/minecraft/textures/block/dead_horn_coral_block.png") -block(blockid=11325, top_image="assets/minecraft/textures/block/dead_tube_coral_block.png") +solidmodelblock(blockid=11321, name="dead_brain_coral_block") +solidmodelblock(blockid=11322, name="dead_bubble_coral_block") +solidmodelblock(blockid=11323, name="dead_fire_coral_block") +solidmodelblock(blockid=11324, name="dead_horn_coral_block") +solidmodelblock(blockid=11325, name="dead_tube_coral_block") @material(blockid=175, data=list(range(16)), transparent=True) def flower(self, blockid, data): @@ -5577,61 +5498,45 @@ def chorus_flower(self, blockid, data): return self.build_block(texture,texture) # purpur block -block(blockid=201, top_image="assets/minecraft/textures/block/purpur_block.png") +solidmodelblock(blockid=201, name="purpur_block") # purpur pillar @material(blockid=202, data=list(range(3)), solid=True) def purpur_pillar(self, blockid, data): - top=self.load_image_texture("assets/minecraft/textures/block/purpur_pillar_top.png") - side=self.load_image_texture("assets/minecraft/textures/block/purpur_pillar.png") - return self.build_axis_block(top, side, data) + return self.build_block_from_model('purpur_pillar', blockstate = {'axis': ({ 0 : 'y', 1: 'x', 2 : 'z'}[data])}) # end brick -block(blockid=206, top_image="assets/minecraft/textures/block/end_stone_bricks.png") +solidmodelblock(blockid=206, name="end_stone_bricks") # frosted ice @material(blockid=212, data=list(range(4)), solid=True) def frosted_ice(self, blockid, data): - img = self.load_image_texture("assets/minecraft/textures/block/frosted_ice_%d.png" % data) - return self.build_block(img, img) + return self.build_block_from_model("frosted_ice_%d" % data) # magma block -block(blockid=213, top_image="assets/minecraft/textures/block/magma.png") - +solidmodelblock(blockid=213, name="magma_block") # nether wart block -block(blockid=214, top_image="assets/minecraft/textures/block/nether_wart_block.png") +solidmodelblock(blockid=214, name="nether_wart_block") # warped wart block -block(blockid=1010, top_image="assets/minecraft/textures/block/warped_wart_block.png") - +solidmodelblock(blockid=1010, name="warped_wart_block") # red nether brick -block(blockid=215, top_image="assets/minecraft/textures/block/red_nether_bricks.png") +solidmodelblock(blockid=215, name="red_nether_bricks") @material(blockid=216, data=list(range(12)), solid=True) def boneblock(self, blockid, data): - # extract orientation - boneblock_orientation = data & 12 - if self.rotation == 1: - if boneblock_orientation == 4: boneblock_orientation = 8 - elif boneblock_orientation == 8: boneblock_orientation = 4 - elif self.rotation == 3: - if boneblock_orientation == 4: boneblock_orientation = 8 - elif boneblock_orientation == 8: boneblock_orientation = 4 - - top = self.load_image_texture("assets/minecraft/textures/block/bone_block_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/bone_block_side.png") - - # choose orientation and paste textures - if boneblock_orientation == 0: - return self.build_block(top, side) - elif boneblock_orientation == 4: # east-west orientation - return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90)) - elif boneblock_orientation == 8: # north-south orientation - return self.build_full_block(side, None, None, side.rotate(270), top) - + return self.build_block_from_model('bone_block', blockstate = {'axis': ({ 0 : 'y', 4: 'x', 8 : 'z'}[data & 12])}) # observer @material(blockid=218, data=[0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13], solid=True, nospawn=True) def observer(self, blockid, data): + + facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data & 0b0111] + if data & 0b1000: + return self.build_block_from_model('observer', {'facing':facing}) + else: + return self.build_block_from_model('observer_on', {'facing':facing}) + + # Do rotation if self.rotation in [1, 2, 3] and (data & 0b111) in [2, 3, 4, 5]: rotation_map = {1: {2: 5, 3: 4, 4: 2, 5: 3}, diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 0fd3f796e..67ea6c354 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -1200,7 +1200,7 @@ def _get_block(self, palette_entry): data = {'east': 1, 'west': 2, 'south': 3, 'north': 4}[facing] elif face == 'floor': data = {'east': 6, 'west': 6, 'south': 5, 'north': 5}[facing] - elif key == 'minecraft:nether_wart': + elif key in ['minecraft:nether_wart', 'minecraft:frosted_ice']: data = int(palette_entry['Properties']['age']) elif (key.endswith('shulker_box') or key.endswith('piston') or key in ['minecraft:observer', 'minecraft:dropper', 'minecraft:dispenser', @@ -1223,11 +1223,11 @@ def _get_block(self, palette_entry): elif key == 'minecraft:quartz_pillar': axis = palette_entry['Properties']['axis'] if axis == 'x': - data = 3 + data = 1 if axis == 'z': - data = 4 + data = 2 elif key in ['minecraft:basalt', 'minecraft:polished_basalt', 'minecraft:chain', 'minecraft:purpur_pillar', - 'minecraft:deepslate']: + 'minecraft:deepslate', 'minecraft:hay_block']: axis = palette_entry['Properties']['axis'] data = {'y': 0, 'x': 1, 'z': 2}[axis] elif key in ['minecraft:redstone_torch','minecraft:redstone_wall_torch','minecraft:wall_torch', From de3fcb6a7316dba38f57a9992f239b01d1d06794 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Wed, 6 Jul 2022 14:18:32 +0200 Subject: [PATCH 11/34] observer --- overviewer_core/textures.py | 69 ++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 08243a92f..2eb5c34e9 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -14,6 +14,7 @@ # with the Overviewer. If not, see . from collections import OrderedDict +from locale import normalize import re import sys import imp @@ -849,12 +850,25 @@ def load_model(self, modelname): self.models[modelname]['elements'] = parent['elements'] del self.models[modelname]['parent'] + self.models[modelname] = self.normalize_model(self.models[modelname], modelname); return self.models[modelname] + # fix known inconsistencies in model info + def normalize_model(self, model, modelname): + match modelname: + # observer top texture is inconsistent in rotation + case 'block/observer': + model['elements'][0]['faces']['up']['texturerotation'] = 180 + model['elements'][0]['faces']['down']['texturerotation'] = 180 + return model + def build_block_from_model(self, modelname, blockstate={}): - colmodel = self.load_model('block/' + modelname) + modelname = 'block/' + modelname + + colmodel = self.load_model(modelname) - # print(json.dumps(data, indent=4)) + # if modelname in {'block/loom'}: + # print(json.dumps(self.models[modelname], indent=4)) img = Image.new("RGBA", (24,24), self.bgcolor) # for each elements @@ -894,35 +908,38 @@ def build_block_from_model(self, modelname, blockstate={}): return img def numvalue_orientation(self, orientation): - return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4,'down': 5}[orientation] + return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4,'down': 6}[orientation] def orientation_from_numvalue(self, orientation): - return {0:'south', 1:'west', 2:'north', 3:'east', 4:'up', 5:'down'}[orientation] + return {0:'south', 1:'west', 2:'north', 3:'east', 4:'up', 6:'down'}[orientation] # translates rotation to real face value # facing is the blockproperty # targetfacing is the direction in witch the north is rotated def map_facing_to_real(self, blockfacing, targetblockface): - if ((blockfacing in {'up','down'}) or (targetblockface in {'up','down'})): + if blockfacing == 'up': if targetblockface == 'up': - resultface = 'up' - elif targetblockface == 'down': - resultface = 'up' # because there is no down texture - - elif blockfacing == 'down' and targetblockface == 'west': + resultface = 'north' + elif targetblockface == 'north': resultface = 'west' - elif blockfacing == 'down' and targetblockface == 'east': - resultface = 'east' - elif blockfacing == 'down' and targetblockface == 'north': - resultface = 'up' # because there is no down texture - - - elif blockfacing == 'up' and targetblockface == 'north': - resultface = 'up' # because there is no down texture - elif blockfacing == 'up' and targetblockface == 'west': + elif targetblockface == 'west': + resultface = 'down' + else: + raise Exception('unexpected facing direction: ' + blockfacing + ' ' + targetblockface) + elif blockfacing == 'down': + if targetblockface == 'west': + resultface = 'down' + elif targetblockface == 'north': resultface = 'west' + elif targetblockface == 'up': + resultface = 'south' else: raise Exception('unexpected facing direction: ' + blockfacing + ' ' + targetblockface) + elif targetblockface == 'up': + resultface = 'up' + elif targetblockface == 'down': + # print('facing direction: ' + blockfacing + ' target: ' + targetblockface + ' ') + resultface = 'down' else: resultface = self.orientation_from_numvalue((self.numvalue_orientation(targetblockface) + [0,3,2,1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2)*2) % 4) return resultface @@ -972,7 +989,7 @@ def draw_face(self, direction, elem, data, blockstate, modelname): if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) # else: - texture = self.transform_texture(direction, texture, blockstate) + texture = self.transform_texture(direction, texture, blockstate, elem['faces'][textureface]) texture = self.adjust_lighting(direction,texture) return texture @@ -994,16 +1011,22 @@ def adjust_lighting(self, direction, texture): case _: raise Exception() - def transform_texture(self, direction, texture, blockstate): + def transform_texture(self, direction, texture, blockstate, faceinfo): top_rotation = 0 - if 'facing' in blockstate: - top_rotation = [180, 90, 0, 270, 180, 180][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 6] match direction: case 'down' | 'up': + if 'facing' in blockstate: + top_rotation = [ 180, 90, 0, 270][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] + if 'texturerotation' in faceinfo: + top_rotation += faceinfo['texturerotation'] return self.transform_image_top(texture.rotate(top_rotation)) case 'north'| 'south': + if 'facing' in blockstate and blockstate['facing'] in {'up','down'}: + top_rotation = [90,90][({'up':0,'down':1}[blockstate['facing']])] texture = self.transform_image_side(texture.rotate(top_rotation)) case 'west' | 'east': + if 'facing' in blockstate and blockstate['facing'] in {'up','down'}: + top_rotation = [180,0][({'up':0,'down':1}[blockstate['facing']])] texture = self.transform_image_side(texture.rotate(top_rotation)) texture = texture.transpose(Image.FLIP_LEFT_RIGHT) case _: From af51000448d2e3a51822ce332c4059540c8c3649 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Wed, 6 Jul 2022 15:10:02 +0200 Subject: [PATCH 12/34] structure blocks --- overviewer_core/textures.py | 42 ++++++------------------------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 2eb5c34e9..bcf892df0 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -5552,43 +5552,12 @@ def boneblock(self, blockid, data): # observer @material(blockid=218, data=[0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13], solid=True, nospawn=True) def observer(self, blockid, data): - facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data & 0b0111] if data & 0b1000: return self.build_block_from_model('observer', {'facing':facing}) else: return self.build_block_from_model('observer_on', {'facing':facing}) - - # Do rotation - if self.rotation in [1, 2, 3] and (data & 0b111) in [2, 3, 4, 5]: - rotation_map = {1: {2: 5, 3: 4, 4: 2, 5: 3}, - 2: {2: 3, 3: 2, 4: 5, 5: 4}, - 3: {2: 4, 3: 5, 4: 3, 5: 2}} - data = (data & 0b1000) | rotation_map[self.rotation][data & 0b111] - - front = self.load_image_texture("assets/minecraft/textures/block/observer_front.png") - side = self.load_image_texture("assets/minecraft/textures/block/observer_side.png") - top = self.load_image_texture("assets/minecraft/textures/block/observer_top.png") - file_name_back = "observer_back_on" if data & 0b1000 else "observer_back" - back = self.load_image_texture("assets/minecraft/textures/block/%s.png" % file_name_back) - - if data & 0b0111 == 0: # Down - img = self.build_full_block(back, None, None, side.rotate(90), top) - elif data & 0b0111 == 1: # Up - img = self.build_full_block(front.rotate(180), None, None, side.rotate(90), top.rotate(180)) - elif data & 0b0111 == 2: # East - img = self.build_full_block(top.rotate(180), None, None, side, back) - elif data & 0b0111 == 3: # West - img = self.build_full_block(top, None, None, side, front) - elif data & 0b0111 == 4: # North - img = self.build_full_block(top.rotate(270), None, None, front, side) - elif data & 0b0111 == 5: # South - img = self.build_full_block(top.rotate(90), None, None, back, side) - - return img - - # shulker box @material(blockid=list(range(219, 235)) + [257], data=list(range(6)), solid=True, nospawn=True) def shulker_box(self, blockid, data): @@ -5638,14 +5607,15 @@ def shulker_box(self, blockid, data): @material(blockid=255, data=list(range(4)), solid=True) def structure_block(self, blockid, data): if data == 0: - img = self.load_image_texture("assets/minecraft/textures/block/structure_block_save.png") + return self.build_block_from_model("structure_block_save") elif data == 1: - img = self.load_image_texture("assets/minecraft/textures/block/structure_block_load.png") + return self.build_block_from_model("structure_block_load") elif data == 2: - img = self.load_image_texture("assets/minecraft/textures/block/structure_block_corner.png") + return self.build_block_from_model("structure_block_corner") elif data == 3: - img = self.load_image_texture("assets/minecraft/textures/block/structure_block_data.png") - return self.build_block(img, img) + return self.build_block_from_model("structure_block_data") + else: + raise Exception('unexpected structure block: ' + str(data)) # Jigsaw block From c1e499218ce1adc1a44951b900ce067d50491b30 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Wed, 6 Jul 2022 20:01:52 +0200 Subject: [PATCH 13/34] glazed --- overviewer_core/textures.py | 144 ++++++++++++++---------------------- overviewer_core/world.py | 6 +- 2 files changed, 61 insertions(+), 89 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index bcf892df0..41e1f5d4d 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -845,7 +845,9 @@ def load_model(self, modelname): self.models[modelname]['textures'].update(parent['textures']) if 'elements' in parent: if 'elements' in self.models[modelname]: - self.models[modelname]['elements'].update(parent['elements']) + # print(modelname + ' : ' + str(type(self.models[modelname]))) + # self.models[modelname]['elements'].update(parent['elements']) + self.models[modelname]['elements'] += parent['elements'] else: self.models[modelname]['elements'] = parent['elements'] del self.models[modelname]['parent'] @@ -857,7 +859,7 @@ def load_model(self, modelname): def normalize_model(self, model, modelname): match modelname: # observer top texture is inconsistent in rotation - case 'block/observer': + case 'block/loom': model['elements'][0]['faces']['up']['texturerotation'] = 180 model['elements'][0]['faces']['down']['texturerotation'] = 180 return model @@ -867,33 +869,36 @@ def build_block_from_model(self, modelname, blockstate={}): colmodel = self.load_model(modelname) - # if modelname in {'block/loom'}: - # print(json.dumps(self.models[modelname], indent=4)) + # if modelname in {'block/white_glazed_terracotta'}: + # print(json.dumps(self.models[modelname], indent=4)) img = Image.new("RGBA", (24,24), self.bgcolor) # for each elements for elem in colmodel['elements']: - if 'west' in elem['faces']: - texture = self.draw_face('west', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (12,6), texture) - elif 'east' in elem['faces']: - texture = self.draw_face('east', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0,0), texture) - - if 'north' in elem['faces']: - texture = self.draw_face('north', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0,6), texture) - elif 'south' in elem['faces']: - texture = self.draw_face('south', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (12,0), texture) - - if 'up' in elem['faces']: - texture = self.draw_face('up', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0,0), texture) - elif 'down' in elem['faces']: - texture = self.draw_face('down', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0,12), texture) - + try: + if 'west' in elem['faces']: + texture = self.draw_face('west', elem, colmodel, blockstate, modelname) + alpha_over(img, texture, (12,6), texture) + elif 'east' in elem['faces']: + texture = self.draw_face('east', elem, colmodel, blockstate, modelname) + alpha_over(img, texture, (0,0), texture) + + if 'north' in elem['faces']: + texture = self.draw_face('north', elem, colmodel, blockstate, modelname) + alpha_over(img, texture, (0,6), texture) + elif 'south' in elem['faces']: + texture = self.draw_face('south', elem, colmodel, blockstate, modelname) + alpha_over(img, texture, (12,0), texture) + + if 'up' in elem['faces']: + texture = self.draw_face('up', elem, colmodel, blockstate, modelname) + alpha_over(img, texture, (0,0), texture) + elif 'down' in elem['faces']: + texture = self.draw_face('down', elem, colmodel, blockstate, modelname) + alpha_over(img, texture, (0,12), texture) + except KeyError: + # element has an invalid texture; skipping entire element + continue # draw each face # Manually touch up 6 pixels that leave a gap because of how the @@ -958,12 +963,12 @@ def map_axis_to_real(self, axis, textureface): def axis_rotation(self, axis, face, texture): match axis: case 'x': - rotation = {'up':90,'north':0,'down':0,'south':0,'east':90,'west':90}[face] + rotation = {'up':270,'north':0,'down':0,'south':0,'east':270,'west':270}[face] return texture.rotate(rotation) case 'y': return texture case 'z': - rotation = {'up':0,'west':0,'down':0,'east':0,'north':270,'south':270}[face] + rotation = {'up':0,'west':0,'down':0,'east':0,'north':90,'south':90}[face] return texture.rotate(rotation) case _: raise Exception() @@ -1012,22 +1017,30 @@ def adjust_lighting(self, direction, texture): raise Exception() def transform_texture(self, direction, texture, blockstate, faceinfo): - top_rotation = 0 + rotation = 0 match direction: case 'down' | 'up': if 'facing' in blockstate: - top_rotation = [ 180, 90, 0, 270][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] + if self.numvalue_orientation(blockstate['facing']) < 4: + rotation += [ 0, 270, 180, 90][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] + else: + rotation += [180,0][({'up':0,'down':1}[blockstate['facing']])] if 'texturerotation' in faceinfo: - top_rotation += faceinfo['texturerotation'] - return self.transform_image_top(texture.rotate(top_rotation)) - case 'north'| 'south': + rotation += faceinfo['texturerotation'] + return self.transform_image_top(texture.rotate(rotation)) + case 'north' | 'south': + if 'rotation' in faceinfo: + rotation = {0:180, 90:90, 180:0, 270:270}[faceinfo['rotation']] if 'facing' in blockstate and blockstate['facing'] in {'up','down'}: - top_rotation = [90,90][({'up':0,'down':1}[blockstate['facing']])] - texture = self.transform_image_side(texture.rotate(top_rotation)) + rotation += [90,90][({'up':0,'down':1}[blockstate['facing']])] + texture = self.transform_image_side(texture.rotate(rotation)) case 'west' | 'east': + if 'rotation' in faceinfo: + rotation = {0:180, 90:90, 180:0, 270:270}[faceinfo['rotation']] if 'facing' in blockstate and blockstate['facing'] in {'up','down'}: - top_rotation = [180,0][({'up':0,'down':1}[blockstate['facing']])] - texture = self.transform_image_side(texture.rotate(top_rotation)) + rotation += [180,0][({'up':0,'down':1}[blockstate['facing']])] + texture = texture.transpose(Image.FLIP_LEFT_RIGHT) + texture = self.transform_image_side(texture.rotate(rotation)) texture = texture.transpose(Image.FLIP_LEFT_RIGHT) case _: raise Exception() @@ -5617,37 +5630,12 @@ def structure_block(self, blockid, data): else: raise Exception('unexpected structure block: ' + str(data)) - # Jigsaw block +# doesnt actually render @material(blockid=256, data=list(range(6)), solid=True) def jigsaw_block(self, blockid, data): - # Do rotation - if self.rotation in [1, 2, 3] and data in [2, 3, 4, 5]: - rotation_map = {1: {2: 5, 3: 4, 4: 2, 5: 3}, - 2: {2: 3, 3: 2, 4: 5, 5: 4}, - 3: {2: 4, 3: 5, 4: 3, 5: 2}} - data = rotation_map[self.rotation][data] - - top = self.load_image_texture("assets/minecraft/textures/block/jigsaw_top.png") - bottom = self.load_image_texture("assets/minecraft/textures/block/jigsaw_bottom.png") - side = self.load_image_texture("assets/minecraft/textures/block/jigsaw_side.png") - - if data == 0: # Down - img = self.build_full_block(bottom.rotate(self.rotation * 90), None, None, - side.rotate(180), side.rotate(180)) - elif data == 1: # Up - img = self.build_full_block(top.rotate(self.rotation * 90), None, None, side, side) - elif data == 2: # North - img = self.build_full_block(side, None, None, side.rotate(90), bottom.rotate(180)) - elif data == 3: # South - img = self.build_full_block(side.rotate(180), None, None, side.rotate(270), top.rotate(270)) - elif data == 4: # West - img = self.build_full_block(side.rotate(90), None, None, top.rotate(180), side.rotate(270)) - elif data == 5: # East - img = self.build_full_block(side.rotate(270), None, None, bottom.rotate(180), - side.rotate(90)) - - return img + facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data%6] + return self.build_block_from_model('jigsaw', {'facing':facing}) # beetroots(207), berry bushes (11505) @@ -5673,38 +5661,18 @@ def crops(self, blockid, data): # Concrete @material(blockid=251, data=list(range(16)), solid=True) def concrete(self, blockid, data): - texture = self.load_image_texture("assets/minecraft/textures/block/%s_concrete.png" % color_map[data]) - return self.build_block(texture, texture) + return self.build_block_from_model("%s_concrete" % color_map[data]) # Concrete Powder @material(blockid=252, data=list(range(16)), solid=True) def concrete(self, blockid, data): - texture = self.load_image_texture("assets/minecraft/textures/block/%s_concrete_powder.png" % color_map[data]) - return self.build_block(texture, texture) - + return self.build_block_from_model("%s_concrete_powder" % color_map[data]) # Glazed Terracotta @material(blockid=list(range(235, 251)), data=list(range(4)), solid=True) def glazed_terracotta(self, blockid, data): - # Do rotation - data = (self.rotation + data) % 4 - - texture = self.load_image_texture("assets/minecraft/textures/block/%s_glazed_terracotta.png" % - color_map[blockid - 235]).copy() - texture_side4 = texture.transpose(Image.FLIP_LEFT_RIGHT) - - if data == 0: # South - return self.build_full_block(texture, None, None, texture, texture_side4.rotate(270)) - elif data == 1: # West - return self.build_full_block(texture.rotate(270), None, None, texture.rotate(90), - texture_side4.rotate(180)) - elif data == 2: # North - return self.build_full_block(texture.rotate(180), None, None, texture.rotate(180), - texture_side4.rotate(90)) - elif data == 3: # East - return self.build_full_block(texture.rotate(90), None, None, texture.rotate(270), - texture_side4) - + facing = {0: 'south', 1: 'west', 2: 'north', 3: 'east'}[data] + return self.build_block_from_model("%s_glazed_terracotta" % color_map[blockid - 235], {'facing':facing}) # dried kelp block @material(blockid=11331, data=[0], solid=True) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 67ea6c354..ae7e716bd 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -1202,9 +1202,13 @@ def _get_block(self, palette_entry): data = {'east': 6, 'west': 6, 'south': 5, 'north': 5}[facing] elif key in ['minecraft:nether_wart', 'minecraft:frosted_ice']: data = int(palette_entry['Properties']['age']) + elif key in ['minecraft:jigsaw']: + data = {'down_east': 0, 'down_east': 0, 'down_north': 0, 'down_south': 0, 'down_west': 0, + 'up_east': 1, 'up_north': 1, 'up_south': 1, 'up_west': 1, 'north_up': 2, 'south_up': 3, + 'west_up': 4, 'east_up': 5}[palette_entry['Properties']['facing']] elif (key.endswith('shulker_box') or key.endswith('piston') or key in ['minecraft:observer', 'minecraft:dropper', 'minecraft:dispenser', - 'minecraft:piston_head', 'minecraft:jigsaw', 'minecraft:end_rod']): + 'minecraft:piston_head', 'minecraft:end_rod']): p = palette_entry['Properties'] data = {'down': 0, 'up': 1, 'north': 2, 'south': 3, 'west': 4, 'east': 5}[p['facing']] if ((key.endswith('piston') and p.get('extended', 'false') == 'true') or From 2ee681cf36486c5770c9b7b4d4573756d1aba6f7 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Thu, 7 Jul 2022 14:14:08 +0200 Subject: [PATCH 14/34] load simple blocks by model name instead of texture --- overviewer_core/textures.py | 466 +++++++++++++----------------------- overviewer_core/world.py | 5 + 2 files changed, 168 insertions(+), 303 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 41e1f5d4d..d41c30def 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -15,6 +15,7 @@ from collections import OrderedDict from locale import normalize +import copy import re import sys import imp @@ -766,26 +767,6 @@ def build_full_block(self, top, side1, side2, side3, side4, bottom=None): return img - def build_axis_block(self, top, side, data): - """ - Build an block with Axis property. - data = {'y': 0, 'x': 1, 'z': 2}[axis] - """ - def draw_x(): - return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90)) - - def draw_y(): - return self.build_full_block(side, None, None, side.rotate(270), top) - - draw_funcs = [draw_x, draw_y] - - if data == 0: # up - return self.build_block(top, side) - elif data == 1: # x - return draw_funcs[(self.rotation + 0) % len(draw_funcs)]() - elif data == 2: # y - return draw_funcs[(self.rotation + 1) % len(draw_funcs)]() - def build_sprite(self, side): """From a side texture, create a sprite-like texture such as those used for spiderwebs or flowers.""" @@ -852,25 +833,40 @@ def load_model(self, modelname): self.models[modelname]['elements'] = parent['elements'] del self.models[modelname]['parent'] - self.models[modelname] = self.normalize_model(self.models[modelname], modelname); + self.models[modelname] = self.normalize_model(modelname); return self.models[modelname] # fix known inconsistencies in model info - def normalize_model(self, model, modelname): + def normalize_model(self, modelname): match modelname: # observer top texture is inconsistent in rotation case 'block/loom': - model['elements'][0]['faces']['up']['texturerotation'] = 180 - model['elements'][0]['faces']['down']['texturerotation'] = 180 - return model + self.models[modelname] = copy.deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['up']['texturerotation'] = 180 + self.models[modelname]['elements'][0]['faces']['down']['texturerotation'] = 180 + case 'block/barrel' | 'block/barrel_open': + self.models[modelname] = copy.deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['north']['texture'] = '#up' + self.models[modelname]['elements'][0]['faces']['south']['texture'] = '#down' + self.models[modelname]['elements'][0]['faces']['down']['texture'] = '#north' + self.models[modelname]['elements'][0]['faces']['up']['texture'] = '#south' + self.models[modelname]['elements'][0]['faces']['east']['texturerotation'] = 90 + self.models[modelname]['elements'][0]['faces']['west']['texturerotation'] = 90 + case 'block/dropper_vertical' | 'block/dispenser_vertical': + self.models[modelname] = copy.deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['north']['texture'] = '#up' + self.models[modelname]['elements'][0]['faces']['up']['texture'] = '#north' + + return self.models[modelname] def build_block_from_model(self, modelname, blockstate={}): modelname = 'block/' + modelname colmodel = self.load_model(modelname) - # if modelname in {'block/white_glazed_terracotta'}: - # print(json.dumps(self.models[modelname], indent=4)) + # if modelname in {'block/barrel_open'}: + # print(json.dumps(self.models[modelname], indent=4)) + img = Image.new("RGBA", (24,24), self.bgcolor) # for each elements @@ -943,7 +939,6 @@ def map_facing_to_real(self, blockfacing, targetblockface): elif targetblockface == 'up': resultface = 'up' elif targetblockface == 'down': - # print('facing direction: ' + blockfacing + ' target: ' + targetblockface + ' ') resultface = 'down' else: resultface = self.orientation_from_numvalue((self.numvalue_orientation(targetblockface) + [0,3,2,1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2)*2) % 4) @@ -1018,6 +1013,8 @@ def adjust_lighting(self, direction, texture): def transform_texture(self, direction, texture, blockstate, faceinfo): rotation = 0 + if 'texturerotation' in faceinfo: + rotation += faceinfo['texturerotation'] match direction: case 'down' | 'up': if 'facing' in blockstate: @@ -1025,8 +1022,6 @@ def transform_texture(self, direction, texture, blockstate, faceinfo): rotation += [ 0, 270, 180, 90][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] else: rotation += [180,0][({'up':0,'down':1}[blockstate['facing']])] - if 'texturerotation' in faceinfo: - rotation += faceinfo['texturerotation'] return self.transform_image_top(texture.rotate(rotation)) case 'north' | 'south': if 'rotation' in faceinfo: @@ -1036,7 +1031,7 @@ def transform_texture(self, direction, texture, blockstate, faceinfo): texture = self.transform_image_side(texture.rotate(rotation)) case 'west' | 'east': if 'rotation' in faceinfo: - rotation = {0:180, 90:90, 180:0, 270:270}[faceinfo['rotation']] + rotation = {0:180, 90:270, 180:0, 270:90}[faceinfo['rotation']] if 'facing' in blockstate and blockstate['facing'] in {'up','down'}: rotation += [180,0][({'up':0,'down':1}[blockstate['facing']])] texture = texture.transpose(Image.FLIP_LEFT_RIGHT) @@ -1140,22 +1135,6 @@ def inner_block(self, unused_id, unused_data): return self.build_block_from_model(name) return inner_block -# shortcut function for pure blocks, default to solid -def block(blockid=[], top_image=None, side_image=None, **kwargs): - new_kwargs = {'solid' : True} - new_kwargs.update(kwargs) - - if top_image is None: - raise ValueError("top_image was not provided") - - if side_image is None: - side_image = top_image - - @material(blockid=blockid, **new_kwargs) - def inner_block(self, unused_id, unused_data): - return self.build_block(self.load_image_texture(top_image), self.load_image_texture(side_image)) - return inner_block - # shortcut function for sprite blocks, defaults to transparent def sprite(blockid=[], imagename=None, **kwargs): new_kwargs = {'transparent' : True} @@ -1209,7 +1188,6 @@ def grass(self, blockid, data): if data & 0x10: return self.build_block_from_model('grass_block_snow') else: - # TODO: generify biome texture overlay side_img = self.load_image_texture("assets/minecraft/textures/block/grass_block_side.png") img = self.build_block(self.load_image_texture("assets/minecraft/textures/block/grass_block_top.png"), side_img) alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture) @@ -1319,7 +1297,6 @@ def no_inner_surfaces(self, blockid, data): img = self.build_full_block(top,None,None,side3,side4) return img -# TODO: generify rendering fluids @material(blockid=[10, 11], data=list(range(16)), fluid=True, transparent=False, nospawn=True) def lava(self, blockid, data): lavatex = self.load_lava() @@ -1448,25 +1425,25 @@ def leaves(self, blockid, data): # mask out the bits 4 and 8 # they are used for player placed and check-for-decay blocks data = data & 0x7 - t = self.load_image_texture("assets/minecraft/textures/block/oak_leaves.png") - if (blockid, data) == (18, 1): # pine! - t = self.load_image_texture("assets/minecraft/textures/block/spruce_leaves.png") - elif (blockid, data) == (18, 2): # birth tree - t = self.load_image_texture("assets/minecraft/textures/block/birch_leaves.png") - elif (blockid, data) == (18, 3): # jungle tree - t = self.load_image_texture("assets/minecraft/textures/block/jungle_leaves.png") - elif (blockid, data) == (161, 4): # acacia tree - t = self.load_image_texture("assets/minecraft/textures/block/acacia_leaves.png") + if (blockid, data) == (18, 0): + return self.build_block_from_model("oak_leaves") + elif (blockid, data) == (18, 1): + return self.build_block_from_model("spruce_leaves") + elif (blockid, data) == (18, 2): + return self.build_block_from_model("birch_leaves") + elif (blockid, data) == (18, 3): + return self.build_block_from_model("jungle_leaves") + elif (blockid, data) == (161, 4): + return self.build_block_from_model("acacia_leaves") elif (blockid, data) == (161, 5): - t = self.load_image_texture("assets/minecraft/textures/block/dark_oak_leaves.png") + return self.build_block_from_model("dark_oak_leaves") elif (blockid, data) == (18, 6): - t = self.load_image_texture("assets/minecraft/textures/block/flowering_azalea_leaves.png") + return self.build_block_from_model("flowering_azalea_leaves") elif (blockid, data) == (18, 7): - t = self.load_image_texture("assets/minecraft/textures/block/azalea_leaves.png") - elif (blockid, data) == (18, 8): - t = self.load_image_texture("assets/minecraft/textures/block/mangrove_leaves.png") - return self.build_block(t, t) - + return self.build_block_from_model("azalea_leaves") + else: + return self.build_block_from_model("mangrove_leaves") + # sponge solidmodelblock(blockid=19, name='sponge') # lapis lazuli ore @@ -1474,68 +1451,38 @@ def leaves(self, blockid, data): # lapis lazuli block solidmodelblock(blockid=22, name="lapis_block") -# dispenser, dropper, furnace, blast furnace, and smoker -@material(blockid=[23, 61, 158, 11362, 11364], data=list(range(14)), solid=True) +@material(blockid=[23, 158], data=list(range(6)), solid=True) +def dropper(self, blockid, data): + facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data] + + if blockid == 158: + if data in {0,1}: + return self.build_block_from_model('dropper_vertical', {'facing':facing}) + return self.build_block_from_model('dropper', {'facing':facing}) + if blockid == 23: + if data in {0,1}: + return self.build_block_from_model('dispenser_vertical', {'facing':facing}) + return self.build_block_from_model('dispenser', {'facing':facing}) + +# furnace, blast furnace, and smoker +@material(blockid=[ 61, 11362, 11364], data=list(range(14)), solid=True) def furnaces(self, blockid, data): - # first, do the rotation if needed - # Masked as bit 4 indicates whether the block is lit/triggered or not - if self.rotation in [1, 2, 3] and data & 0b111 in [2, 3, 4, 5]: - rotation_map = {1: {2: 5, 3: 4, 4: 2, 5: 3}, - 2: {2: 3, 3: 2, 4: 5, 5: 4}, - 3: {2: 4, 3: 5, 4: 3, 5: 2}} - data = data & 0b1000 | rotation_map[self.rotation][data & 0b111] - - # Rotation angles for top texture using data & 0b111 as an index - top_rotation_map = [0, 0, 180, 0, 270, 90, 0, 0] - - # Dispenser - texture_map = {23: {'top': 'furnace_top', 'side': 'furnace_side', - 'front': 'dispenser_front', 'top_vert': 'dispenser_front_vertical'}, - # Furnace - 61: {'top': 'furnace_top', 'side': 'furnace_side', - 'front': 'furnace_front', 'front_on': 'furnace_front_on'}, - # Dropper - 158: {'top': 'furnace_top', 'side': 'furnace_side', - 'front': 'dropper_front', 'top_vert': 'dropper_front_vertical'}, - # Blast furance - 11362: {'top': 'blast_furnace_top', 'side': 'blast_furnace_side', - 'front': 'blast_furnace_front', 'front_on': 'blast_furnace_front_on'}, - # Smoker - 11364: {'top': 'smoker_top', 'side': 'smoker_side', - 'front': 'smoker_front', 'front_on': 'smoker_front_on'}} - - if data & 0b111 in [0, 1] and 'top_vert' in texture_map[blockid]: - # Block has a special top texture when it faces up/down - # This also affects which texture is used for the sides/front - top_name = 'top_vert' if data & 0b111 == 1 else 'top' - side_name = 'top' - front_name = 'top' - else: - top_name = 'top' - side_name = 'side' - # Use block's lit/on front texture if it is defined & bit 4 is set - # Note: Some front_on texture images have multiple frames, - # but load_image_texture() crops this appropriately - # as long as the image width is 16px - if data & 0b1000 == 8 and 'front_on' in texture_map[blockid]: - front_name = 'front_on' - else: - front_name = 'front' - - top = self.load_image_texture("assets/minecraft/textures/block/%s.png" % - texture_map[blockid][top_name]).copy() - top = top.rotate(top_rotation_map[data & 0b111]) - side = self.load_image_texture("assets/minecraft/textures/block/%s.png" % - texture_map[blockid][side_name]) - front = self.load_image_texture("assets/minecraft/textures/block/%s.png" % - texture_map[blockid][front_name]) - - if data & 0b111 == 3: # pointing west - return self.build_full_block(top, None, None, side, front) - elif data & 0b111 == 4: # pointing north - return self.build_full_block(top, None, None, front, side) - else: # in any other direction the front can't be seen - return self.build_full_block(top, None, None, side, side) + lit = data & 0b1000 == 8 + oriention = data & 0b111 + + facing = {0: '', 1: '', 2: 'north', 3: 'south', 4: 'west', 5: 'east', 6:'',7:''}[oriention] + if blockid == 61: + if lit: + return self.build_block_from_model('furnace_on', {'facing':facing}) + return self.build_block_from_model('furnace', {'facing':facing}) + if blockid == 11362: + if lit: + return self.build_block_from_model('blast_furnace_on', {'facing':facing}) + return self.build_block_from_model('blast_furnace', {'facing':facing}) + if blockid == 11364: + if lit: + return self.build_block_from_model('smoker_on', {'facing':facing}) + return self.build_block_from_model('smoker', {'facing':facing}) # sandstone @material(blockid=24, data=list(range(3)), solid=True) @@ -1551,14 +1498,12 @@ def sandstone(self, blockid, data): # red sandstone @material(blockid=179, data=list(range(3)), solid=True) def sandstone(self, blockid, data): - top = self.load_image_texture("assets/minecraft/textures/block/red_sandstone_top.png") if data == 0: # normal - side = self.load_image_texture("assets/minecraft/textures/block/red_sandstone.png") - return self.build_full_block(top, None, None, side, side, self.load_image_texture("assets/minecraft/textures/block/red_sandstone_bottom.png") ) + return self.build_block_from_model('red_sandstone') if data == 1: # hieroglyphic - return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/chiseled_red_sandstone.png")) + return self.build_block_from_model('chiseled_red_sandstone') if data == 2: # soft - return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/cut_red_sandstone.png")) + return self.build_block_from_model('cut_red_sandstone') # note block solidmodelblock(blockid=25, name="note_block") @@ -1925,9 +1870,7 @@ def tall_grass(self, blockid, data): @material(blockid=35, data=list(range(16)), solid=True) def wool(self, blockid, data): - texture = self.load_image_texture("assets/minecraft/textures/block/%s_wool.png" % color_map[data]) - - return self.build_block(texture, texture) + return self.build_block_from_model("%s_wool" % color_map[data]) # dandelion sprite(blockid=37, imagename="assets/minecraft/textures/block/dandelion.png") @@ -5675,106 +5618,45 @@ def glazed_terracotta(self, blockid, data): return self.build_block_from_model("%s_glazed_terracotta" % color_map[blockid - 235], {'facing':facing}) # dried kelp block -@material(blockid=11331, data=[0], solid=True) -def sandstone(self, blockid, data): - top = self.load_image_texture("assets/minecraft/textures/block/dried_kelp_top.png") - return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/dried_kelp_side.png")) +solidmodelblock(blockid=11331, name="dried_kelp_block") # scaffolding -block(blockid=11414, top_image="assets/minecraft/textures/block/scaffolding_top.png", side_image="assets/minecraft/textures/block/scaffolding_side.png", solid=False, transparent=True) +@material(blockid=[11414], data=list(range(2)), solid=False, transparent=True) +def scaffolding(self, blockid, data): + top = self.load_image_texture("assets/minecraft/textures/block/scaffolding_top.png") + side = self.load_image_texture("assets/minecraft/textures/block/scaffolding_side.png") + img = self.build_block(top,side) + return img # beehive and bee_nest @material(blockid=[11501, 11502], data=list(range(8)), solid=True) def beehivenest(self, blockid, data): - if blockid == 11501: #beehive - t_top = self.load_image("assets/minecraft/textures/block/beehive_end.png") - t_side = self.load_image("assets/minecraft/textures/block/beehive_side.png") - t_front = self.load_image("assets/minecraft/textures/block/beehive_front.png") - t_front_honey = self.load_image("assets/minecraft/textures/block/beehive_front_honey.png") - elif blockid == 11502: #bee_nest - t_top = self.load_image("assets/minecraft/textures/block/bee_nest_top.png") - t_side = self.load_image("assets/minecraft/textures/block/bee_nest_side.png") - t_front = self.load_image("assets/minecraft/textures/block/bee_nest_front.png") - t_front_honey = self.load_image("assets/minecraft/textures/block/bee_nest_front_honey.png") - - if data >= 4: - front = t_front_honey - else: - front = t_front - - if self.rotation == 0: # rendering north upper-left - if data == 0 or data == 4: # south - return self.build_full_block(t_top, t_side, t_side, t_side, front) - elif data == 1 or data == 5: # west - return self.build_full_block(t_top, t_side, t_side, front, t_side) - elif data == 2 or data == 6: # north - return self.build_full_block(t_top, t_side, front, t_side, t_side) - elif data == 3 or data == 7: # east - return self.build_full_block(t_top, front, t_side, t_side, t_side) - - elif self.rotation == 1: # north upper-right - if data == 0 or data == 4: # south - return self.build_full_block(t_top, t_side, t_side, front, t_side) - elif data == 1 or data == 5: # west - return self.build_full_block(t_top, t_side, front, t_side, t_side) - elif data == 2 or data == 6: # north - return self.build_full_block(t_top, front, t_side, t_side, t_side) - elif data == 3 or data == 7: # east - return self.build_full_block(t_top, t_side, t_side, t_side, front) - - elif self.rotation == 2: # north lower-right - if data == 0 or data == 4: # south - return self.build_full_block(t_top, t_side, front, t_side, t_side) - elif data == 1 or data == 5: # west - return self.build_full_block(t_top, front, t_side, t_side, t_side) - elif data == 2 or data == 6: # north - return self.build_full_block(t_top, t_side, t_side, t_side, front) - elif data == 3 or data == 7: # east - return self.build_full_block(t_top, t_side, t_side, front, t_side) - - elif self.rotation == 3: # north lower-left - if data == 0 or data == 4: # south - return self.build_full_block(t_top, front, t_side, t_side, t_side) - elif data == 1 or data == 5: # west - return self.build_full_block(t_top, t_side, t_side, t_side, front) - elif data == 2 or data == 6: # north - return self.build_full_block(t_top, t_side, t_side, front, t_side) - elif data == 3 or data == 7: # east - return self.build_full_block(t_top, t_side, front, t_side, t_side) + facing = {0: 'south', 1: 'west', 2: 'north', 3: 'east'}[data % 4] + if blockid == 11501: + if data >= 4: + return self.build_block_from_model('beehive_honey', {'facing':facing}) + return self.build_block_from_model('beehive', {'facing':facing}) + if blockid == 11502: + if data >= 4: + return self.build_block_from_model('bee_nest_honey', {'facing':facing}) + return self.build_block_from_model('bee_nest', {'facing':facing}) + raise Exception('what') # honeycomb_block -block(blockid=11503, top_image="assets/minecraft/textures/block/honeycomb_block.png") +solidmodelblock(blockid=11503, name="honeycomb_block") # honey_block -block(blockid=11504, top_image="assets/minecraft/textures/block/honey_block_top.png", side_image="assets/minecraft/textures/block/honey_block_side.png") - +transparentmodelblock(blockid=11504, name="honey_block") # Barrel @material(blockid=11418, data=list(range(12)), solid=True) def barrel(self, blockid, data): - t_bottom = self.load_image("assets/minecraft/textures/block/barrel_bottom.png") - t_side = self.load_image("assets/minecraft/textures/block/barrel_side.png") - if data & 0x01: - t_top = self.load_image("assets/minecraft/textures/block/barrel_top_open.png") - else: - t_top = self.load_image("assets/minecraft/textures/block/barrel_top.png") - data = data >> 1 - - if data == 0: # up - return self.build_full_block(t_top, None, None, t_side, t_side) - elif data == 1: # down - t_side = t_side.rotate(180) - return self.build_full_block(t_bottom, None, None, t_side, t_side) - elif data == 2: # south - return self.build_full_block(t_side.rotate(180), None, None, t_side.rotate(270), t_top) - elif data == 3: # east - return self.build_full_block(t_side.rotate(270), None, None, t_bottom, t_side.rotate(90)) - elif data == 4: # north - return self.build_full_block(t_side, None, None, t_side.rotate(90), t_bottom) - else: # west - return self.build_full_block(t_side.rotate(90), None, None, t_top, t_side.rotate(270)) + facing = { 0: 'up', 1: 'down', 2: 'south', 3: 'east', 4: 'north', 5: 'west'}[data >> 1] + if data & 0x01: + return self.build_block_from_model('barrel_open', {'facing':facing}) + return self.build_block_from_model('barrel', {'facing':facing}) # Campfire (11506) and soul campfire (1003) @material(blockid=[11506, 1003], data=list(range(8)), solid=True, transparent=True, nospawn=True) @@ -6004,25 +5886,20 @@ def create_tile(img_src, coord_crop, coord_paste, rot): return img - # Ancient Debris -block(blockid=[1000], top_image="assets/minecraft/textures/block/ancient_debris_top.png", - side_image="assets/minecraft/textures/block/ancient_debris_side.png") - +solidmodelblock(blockid=[1000], name="ancient_debris") # Basalt @material(blockid=[1001, 1002], data=list(range(3)), solid=True) def basalt(self, blockid, data): - block_name = "polished_basalt" if blockid == 1002 else "basalt" - top = self.load_image_texture("assets/minecraft/textures/block/" + block_name + "_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/" + block_name + "_side.png") - return self.build_axis_block(top, side, data) - - + axis = { 0 : 'y', 1: 'x', 2 : 'z'}[data] + if blockid == 1001: # basalt + return self.build_block_from_model('basalt', {'axis':axis}) + if blockid == 1002: # polished_basalt + return self.build_block_from_model('polished_basalt', {'axis':axis}) + # Blackstone block -block(blockid=[1004], top_image="assets/minecraft/textures/block/blackstone_top.png", - side_image="assets/minecraft/textures/block/blackstone.png") - +solidmodelblock(blockid=[1004], name="blackstone") # Chain @material(blockid=11419, data=list(range(3)), solid=True, transparent=True, nospawn=True) @@ -6060,87 +5937,75 @@ def draw_z(): return img - # Respawn anchor @material(blockid=1037, data=list(range(5)), solid=True) def respawn_anchor(self, blockid, data): - top = self.load_image_texture("assets/minecraft/textures/block/respawn_anchor_top_off.png" if data == - 0 else "assets/minecraft/textures/block/respawn_anchor_top.png") - side = self.load_image_texture( - "assets/minecraft/textures/block/respawn_anchor_side%s.png" % (data)) - - return self.build_block(top, side) - + return self.build_block_from_model("respawn_anchor_%s" % data) # Netherite -block(blockid=[1005], top_image="assets/minecraft/textures/block/netherite_block.png") +solidmodelblock(blockid=[1005], name="netherite_block") # soul soil -block(blockid=1020, top_image="assets/minecraft/textures/block/soul_soil.png") +solidmodelblock(blockid=1020, name="soul_soil") # nether gold ore -block(blockid=1021, top_image="assets/minecraft/textures/block/nether_gold_ore.png") +solidmodelblock(blockid=1021, name="nether_gold_ore") # Solid Nether stone blocks -block(blockid=1022, top_image="assets/minecraft/textures/block/polished_blackstone.png") -block(blockid=1023, top_image="assets/minecraft/textures/block/chiseled_polished_blackstone.png") -block(blockid=1024, top_image="assets/minecraft/textures/block/gilded_blackstone.png") -block(blockid=1025, top_image="assets/minecraft/textures/block/cracked_polished_blackstone_bricks.png") -block(blockid=1026, top_image="assets/minecraft/textures/block/polished_blackstone_bricks.png") +solidmodelblock(blockid=1022, name="polished_blackstone") +solidmodelblock(blockid=1023, name="chiseled_polished_blackstone") +solidmodelblock(blockid=1024, name="gilded_blackstone") +solidmodelblock(blockid=1025, name="cracked_polished_blackstone_bricks") +solidmodelblock(blockid=1026, name="polished_blackstone_bricks") -block(blockid=1035, top_image="assets/minecraft/textures/block/crying_obsidian.png") -block(blockid=1036, top_image="assets/minecraft/textures/block/lodestone_top.png", side_image="assets/minecraft/textures/block/lodestone_side.png") -block(blockid=1041, top_image="assets/minecraft/textures/block/quartz_bricks.png") +solidmodelblock(blockid=1035, name="crying_obsidian") +solidmodelblock(blockid=1036, name="lodestone") +solidmodelblock(blockid=1041, name="quartz_bricks") -block(blockid=1042, top_image="assets/minecraft/textures/block/amethyst_block.png") -block(blockid=1043, top_image="assets/minecraft/textures/block/raw_iron_block.png") -block(blockid=1044, top_image="assets/minecraft/textures/block/raw_gold_block.png") -block(blockid=1045, top_image="assets/minecraft/textures/block/budding_amethyst.png") +solidmodelblock(blockid=1042, name="amethyst_block") +solidmodelblock(blockid=1043, name="raw_iron_block") +solidmodelblock(blockid=1044, name="raw_gold_block") +solidmodelblock(blockid=1045, name="budding_amethyst") # You have entered the COPPER ZONE -block(blockid=[1046, 1050], top_image="assets/minecraft/textures/block/copper_block.png") -block(blockid=[1047, 1051], top_image="assets/minecraft/textures/block/exposed_copper.png") -block(blockid=[1048, 1052], top_image="assets/minecraft/textures/block/weathered_copper.png") -block(blockid=[1049, 1053], top_image="assets/minecraft/textures/block/oxidized_copper.png") +solidmodelblock(blockid=[1046, 1050], name="copper_block") +solidmodelblock(blockid=[1047, 1051], name="exposed_copper") +solidmodelblock(blockid=[1048, 1052], name="weathered_copper") +solidmodelblock(blockid=[1049, 1053], name="oxidized_copper") # Cut variant -block(blockid=[1054, 1058], top_image="assets/minecraft/textures/block/cut_copper.png") -block(blockid=[1055, 1059], top_image="assets/minecraft/textures/block/exposed_cut_copper.png") -block(blockid=[1056, 1060], top_image="assets/minecraft/textures/block/weathered_cut_copper.png") -block(blockid=[1057, 1061], top_image="assets/minecraft/textures/block/oxidized_cut_copper.png") +solidmodelblock(blockid=[1054, 1058], name="cut_copper") +solidmodelblock(blockid=[1055, 1059], name="exposed_cut_copper") +solidmodelblock(blockid=[1056, 1060], name="weathered_cut_copper") +solidmodelblock(blockid=[1057, 1061], name="oxidized_cut_copper") -block(blockid=1062, top_image="assets/minecraft/textures/block/raw_copper_block.png") -block(blockid=1063, top_image="assets/minecraft/textures/block/copper_ore.png") +solidmodelblock(blockid=1062, name="raw_copper_block") +solidmodelblock(blockid=1063, name="copper_ore") # You are now leaving the COPPER ZONE -block(blockid=1080, top_image="assets/minecraft/textures/block/moss_block.png") -block(blockid=1081, top_image="assets/minecraft/textures/block/calcite.png") -block(blockid=1082, top_image="assets/minecraft/textures/block/rooted_dirt.png") - +solidmodelblock(blockid=1080, name="moss_block") +solidmodelblock(blockid=1081, name="calcite") +solidmodelblock(blockid=1082, name="rooted_dirt") # deepslate @material(blockid=1083, data=list(range(3)), solid=True) def deepslate(self, blockid, data): - top=self.load_image_texture("assets/minecraft/textures/block/deepslate_top.png") - side=self.load_image_texture("assets/minecraft/textures/block/deepslate.png") - return self.build_axis_block(top, side, data) - - -block(blockid=1084, top_image="assets/minecraft/textures/block/cobbled_deepslate.png") -block(blockid=1085, top_image="assets/minecraft/textures/block/polished_deepslate.png") -block(blockid=1086, top_image="assets/minecraft/textures/block/deepslate_coal_ore.png") -block(blockid=1087, top_image="assets/minecraft/textures/block/deepslate_iron_ore.png") -block(blockid=1088, top_image="assets/minecraft/textures/block/deepslate_copper_ore.png") -block(blockid=1089, top_image="assets/minecraft/textures/block/deepslate_gold_ore.png") -block(blockid=1090, top_image="assets/minecraft/textures/block/deepslate_emerald_ore.png") -block(blockid=1091, top_image="assets/minecraft/textures/block/deepslate_lapis_ore.png") -block(blockid=1092, top_image="assets/minecraft/textures/block/deepslate_diamond_ore.png") -block(blockid=1093, top_image="assets/minecraft/textures/block/deepslate_redstone_ore.png") -block(blockid=1094, top_image="assets/minecraft/textures/block/deepslate_bricks.png") -block(blockid=1095, top_image="assets/minecraft/textures/block/cracked_deepslate_bricks.png") -block(blockid=1096, top_image="assets/minecraft/textures/block/deepslate_tiles.png") -block(blockid=1097, top_image="assets/minecraft/textures/block/cracked_deepslate_tiles.png") -block(blockid=1098, top_image="assets/minecraft/textures/block/chiseled_deepslate.png") - -block(blockid=1107, top_image="assets/minecraft/textures/block/dripstone_block.png") -block(blockid=1108, top_image="assets/minecraft/textures/block/smooth_basalt.png") -block(blockid=1109, top_image="assets/minecraft/textures/block/tuff.png") + return self.build_block_from_model('deepslate', {'axis': { 0 : 'y', 1: 'x', 2 : 'z'}[data]}) + +solidmodelblock(blockid=1084, name="cobbled_deepslate") +solidmodelblock(blockid=1085, name="polished_deepslate") +solidmodelblock(blockid=1086, name="deepslate_coal_ore") +solidmodelblock(blockid=1087, name="deepslate_iron_ore") +solidmodelblock(blockid=1088, name="deepslate_copper_ore") +solidmodelblock(blockid=1089, name="deepslate_gold_ore") +solidmodelblock(blockid=1090, name="deepslate_emerald_ore") +solidmodelblock(blockid=1091, name="deepslate_lapis_ore") +solidmodelblock(blockid=1092, name="deepslate_diamond_ore") +solidmodelblock(blockid=1093, name="deepslate_redstone_ore") +solidmodelblock(blockid=1094, name="deepslate_bricks") +solidmodelblock(blockid=1095, name="cracked_deepslate_bricks") +solidmodelblock(blockid=1096, name="deepslate_tiles") +solidmodelblock(blockid=1097, name="cracked_deepslate_tiles") +solidmodelblock(blockid=1098, name="chiseled_deepslate") +solidmodelblock(blockid=1107, name="dripstone_block") +solidmodelblock(blockid=1108, name="smooth_basalt") +solidmodelblock(blockid=1109, name="tuff") @material(blockid=1110, data=list(range(16)), transparent=True) @@ -6158,9 +6023,7 @@ def pointed_dripstone(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/pointed_dripstone_%s_tip.png" % (up_down)) return self.build_sprite(tex) - -block(blockid=1111, top_image="assets/minecraft/textures/block/powder_snow.png") - +solidmodelblock(blockid=1111, name="powder_snow") @material(blockid=1112, data=0, transparent=True) def hangings_roots(self, blockid, data): @@ -6443,11 +6306,8 @@ def spore_blossom(self, blockid, data): alpha_over(img, base_top, (0, 0), base_top) return img - -block(blockid=1121, top_image="assets/minecraft/textures/block/mud.png") -block(blockid=1122, top_image="assets/minecraft/textures/block/packed_mud.png") -block(blockid=1123, top_image="assets/minecraft/textures/block/mud_bricks.png") -block(blockid=1125, top_image="assets/minecraft/textures/block/mangrove_roots_top.png", - side_image="assets/minecraft/textures/block/mangrove_roots_side.png") -block(blockid=1127, top_image="assets/minecraft/textures/block/muddy_mangrove_roots_top.png", - side_image="assets/minecraft/textures/block/muddy_mangrove_roots_side.png") +solidmodelblock(blockid=1121, name="mud") +solidmodelblock(blockid=1122, name="packed_mud") +solidmodelblock(blockid=1123, name="mud_bricks") +solidmodelblock(blockid=1125, name="mangrove_roots") +solidmodelblock(blockid=1127, name="muddy_mangrove_roots") diff --git a/overviewer_core/world.py b/overviewer_core/world.py index ae7e716bd..b2ec28b33 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -1153,6 +1153,11 @@ def _get_block(self, palette_entry): elif key == 'minecraft:daylight_detector': if palette_entry['Properties']['inverted'] == 'true': block = 178 + elif key == 'minecraft:scaffolding': + if palette_entry['Properties']['bottom'] == 'true': + data = 1 + else: + data = 0 elif key == 'minecraft:redstone_wire': data = palette_entry['Properties']['power'] elif key == 'minecraft:grass_block': From 5a172e3b0aa0a6c26043e6cc9019972427713d8e Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Fri, 8 Jul 2022 13:57:35 +0200 Subject: [PATCH 15/34] referenced more blocks by enum --- overviewer_core/src/iterate.c | 10 +++++----- overviewer_core/src/primitives/base.c | 2 +- overviewer_core/src/primitives/cave.c | 4 ++-- overviewer_core/textures.py | 19 ++++++++++-------- overviewer_core/world.py | 28 ++++++++++++--------------- 5 files changed, 31 insertions(+), 32 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index 666e5a030..c8f5c186b 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -263,7 +263,7 @@ generate_pseudo_data(RenderState* state, uint16_t ancilData) { * Note that stained glass encodes 16 colors using 4 bits. this pushes us over the 8-bits of an uint8_t, * forcing us to use an uint16_t to hold 16 bits of pseudo ancil data * */ - if ((get_data(state, BLOCKS, x, y + 1, z) == 20) || (get_data(state, BLOCKS, x, y + 1, z) == 95)) { + if ((get_data(state, BLOCKS, x, y + 1, z) == block_glass) || (get_data(state, BLOCKS, x, y + 1, z) == block_stained_glass)) { data = 0; } else { data = 16; @@ -278,15 +278,15 @@ generate_pseudo_data(RenderState* state, uint16_t ancilData) { uint8_t above_level_data = 0, same_level_data = 0, below_level_data = 0, possibly_connected = 0, final_data = 0; /* check for air in y+1, no air = no connection with upper level */ - if (get_data(state, BLOCKS, x, y + 1, z) == 0) { + if (get_data(state, BLOCKS, x, y + 1, z) == block_air) { above_level_data = check_adjacent_blocks(state, x, y + 1, z, state->block); } /* else above_level_data = 0 */ /* check connection with same level (other redstone and trapped chests */ - same_level_data = check_adjacent_blocks(state, x, y, z, 55) | check_adjacent_blocks(state, x, y, z, 146); + same_level_data = check_adjacent_blocks(state, x, y, z, block_redstone_wire) | check_adjacent_blocks(state, x, y, z, block_trapped_chest); /* check the posibility of connection with y-1 level, check for air */ - possibly_connected = check_adjacent_blocks(state, x, y, z, 0); + possibly_connected = check_adjacent_blocks(state, x, y, z, block_air ); /* check connection with y-1 level */ below_level_data = check_adjacent_blocks(state, x, y - 1, z, state->block); @@ -622,7 +622,7 @@ chunk_render(PyObject* self, PyObject* args) { /* if we found a proper texture, render it! */ if (t != NULL && t != Py_None) { PyObject *src, *mask, *mask_light; - int32_t do_rand = (state.block == block_tallgrass /*|| state.block == block_red_flower || state.block == block_double_plant*/); + int32_t do_rand = (state.block == block_tallgrass); int32_t randx = 0, randy = 0; src = PyTuple_GetItem(t, 0); mask = PyTuple_GetItem(t, 0); diff --git a/overviewer_core/src/primitives/base.c b/overviewer_core/src/primitives/base.c index bd37ff0b6..31d1bda65 100644 --- a/overviewer_core/src/primitives/base.c +++ b/overviewer_core/src/primitives/base.c @@ -103,7 +103,7 @@ base_draw(void* data, RenderState* state, PyObject* src, PyObject* mask, PyObjec * biome-compliant ones! The tinting is now all done here. */ if (/* grass, but not snowgrass */ - (state->block == block_grass && get_data(state, BLOCKS, state->x, state->y + 1, state->z) != 78) || + (state->block == block_grass && get_data(state, BLOCKS, state->x, state->y + 1, state->z) != block_snow_layer) || block_class_is_subset(state->block, (mc_block_t[]){block_vine, block_waterlily, block_flowing_water, block_water, block_leaves, block_leaves2}, 6) || /* tallgrass, but not dead shrubs */ diff --git a/overviewer_core/src/primitives/cave.c b/overviewer_core/src/primitives/cave.c index 66d976efc..8d6a815e3 100644 --- a/overviewer_core/src/primitives/cave.c +++ b/overviewer_core/src/primitives/cave.c @@ -83,14 +83,14 @@ cave_hidden(void* data, RenderState* state, int32_t x, int32_t y, int32_t z) { blockID = getArrayShort3D(state->blocks, x, y, z); blockUpID = get_data(state, BLOCKS, x, y + 1, z); - if (blockID == 9 || blockID == 8 || blockUpID == 9 || blockUpID == 8) { + if (blockID == block_water || blockID == block_flowing_water || blockUpID == block_water || blockUpID == block_flowing_water) { for (dy = y + 1; dy < (SECTIONS_PER_CHUNK - state->chunky) * 16; dy++) { /* go up and check for skylight */ if (get_data(state, SKYLIGHT, x, dy, z) != 0) { return true; } blockUpID = get_data(state, BLOCKS, x, dy, z); - if (blockUpID != 8 && blockUpID != 9) { + if (blockUpID != block_flowing_water && blockUpID != block_water) { /* we are out of the water! and there's no skylight * , i.e. is a cave lake or something similar */ break; diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index d41c30def..976661dc4 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -14,8 +14,8 @@ # with the Overviewer. If not, see . from collections import OrderedDict -from locale import normalize -import copy +from copy import deepcopy +from pathlib import Path import re import sys import imp @@ -841,11 +841,11 @@ def normalize_model(self, modelname): match modelname: # observer top texture is inconsistent in rotation case 'block/loom': - self.models[modelname] = copy.deepcopy(self.models[modelname]) + self.models[modelname] = deepcopy(self.models[modelname]) self.models[modelname]['elements'][0]['faces']['up']['texturerotation'] = 180 self.models[modelname]['elements'][0]['faces']['down']['texturerotation'] = 180 case 'block/barrel' | 'block/barrel_open': - self.models[modelname] = copy.deepcopy(self.models[modelname]) + self.models[modelname] = deepcopy(self.models[modelname]) self.models[modelname]['elements'][0]['faces']['north']['texture'] = '#up' self.models[modelname]['elements'][0]['faces']['south']['texture'] = '#down' self.models[modelname]['elements'][0]['faces']['down']['texture'] = '#north' @@ -853,7 +853,7 @@ def normalize_model(self, modelname): self.models[modelname]['elements'][0]['faces']['east']['texturerotation'] = 90 self.models[modelname]['elements'][0]['faces']['west']['texturerotation'] = 90 case 'block/dropper_vertical' | 'block/dispenser_vertical': - self.models[modelname] = copy.deepcopy(self.models[modelname]) + self.models[modelname] = deepcopy(self.models[modelname]) self.models[modelname]['elements'][0]['faces']['north']['texture'] = '#up' self.models[modelname]['elements'][0]['faces']['up']['texture'] = '#north' @@ -869,6 +869,9 @@ def build_block_from_model(self, modelname, blockstate={}): img = Image.new("RGBA", (24,24), self.bgcolor) + if 'elements' not in colmodel: + return None + # for each elements for elem in colmodel['elements']: try: @@ -5382,11 +5385,11 @@ def hopper(self, blockid, data): @material(blockid=168, data=list(range(3)), solid=True) def prismarine_block(self, blockid, data): if data == 0: # prismarine - t = self.build_block_from_model("prismarine") + return self.build_block_from_model("prismarine") elif data == 1: # prismarine bricks - t = self.build_block_from_model("prismarine_bricks") + return self.build_block_from_model("prismarine_bricks") elif data == 2: # dark prismarine - t = self.build_block_from_model("dark_prismarine") + return self.build_block_from_model("dark_prismarine") else: raise Exception('unexpected prismarine data: ' + str(data)) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index b2ec28b33..2ce5d715f 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -18,12 +18,9 @@ import os.path import logging import time -import random import re -import locale import numpy -import math from . import nbt from . import cache @@ -37,10 +34,11 @@ class ChunkDoesntExist(Exception): pass - class UnsupportedVersion(Exception): pass +class UnknownBlockException(Exception): + pass def log_other_exceptions(func): """A decorator that prints out any errors that are not @@ -1129,6 +1127,8 @@ def _get_block(self, palette_entry): 'purple', 'blue', 'brown', 'green', 'red', 'black'] key = palette_entry['Name'] + if key not in self._blockmap: + raise UnknownBlockException(key) (block, data) = self._blockmap[key] if key in ['minecraft:redstone_ore', 'minecraft:redstone_lamp']: if palette_entry['Properties']['lit'] == 'true': @@ -1209,8 +1209,8 @@ def _get_block(self, palette_entry): data = int(palette_entry['Properties']['age']) elif key in ['minecraft:jigsaw']: data = {'down_east': 0, 'down_east': 0, 'down_north': 0, 'down_south': 0, 'down_west': 0, - 'up_east': 1, 'up_north': 1, 'up_south': 1, 'up_west': 1, 'north_up': 2, 'south_up': 3, - 'west_up': 4, 'east_up': 5}[palette_entry['Properties']['facing']] + 'up_east': 1, 'up_north': 1, 'up_south': 1, 'up_west': 1, 'north_up': 2, 'south_up': 3, + 'west_up': 4, 'east_up': 5}[palette_entry['Properties']['orientation']] elif (key.endswith('shulker_box') or key.endswith('piston') or key in ['minecraft:observer', 'minecraft:dropper', 'minecraft:dispenser', 'minecraft:piston_head', 'minecraft:end_rod']): @@ -1514,7 +1514,7 @@ def _packed_longarray_to_shorts_v116(self, long_array, n, num_palette): return result - def _get_blockdata_v118(self, section, unrecognized_block_types, longarray_unpacker): + def _get_blockdata_v118(self, section, longarray_unpacker): block_states = section['block_states'] palette = block_states.get('palette') block_states_data = block_states.get('data') @@ -1531,7 +1531,7 @@ def _get_blockdata_v118(self, section, unrecognized_block_types, longarray_unpac key = palette[i] try: translated_blocks[i], translated_data[i] = self._get_block(key) - except KeyError: + except UnknownBlockException as e: pass # We already have initialised arrays with 0 (= air) # Turn the BlockStates array into a 16x16x16 numpy matrix of shorts. @@ -1547,7 +1547,7 @@ def _get_blockdata_v118(self, section, unrecognized_block_types, longarray_unpac return (blocks, data) - def _get_blockdata_v113(self, section, unrecognized_block_types, longarray_unpacker): + def _get_blockdata_v113(self, section, longarray_unpacker): # Translate each entry in the palette to a 1.2-era (block, data) int pair. num_palette_entries = len(section['Palette']) translated_blocks = numpy.zeros((num_palette_entries,), dtype=numpy.uint16) # block IDs @@ -1556,7 +1556,7 @@ def _get_blockdata_v113(self, section, unrecognized_block_types, longarray_unpac key = section['Palette'][i] try: translated_blocks[i], translated_data[i] = self._get_block(key) - except KeyError: + except UnknownBlockException as e: pass # We already have initialised arrays with 0 (= air) # Turn the BlockStates array into a 16x16x16 numpy matrix of shorts. @@ -1719,7 +1719,6 @@ def get_chunk(self, x, z): chunk_data['Biomes'] = biomes chunk_data['NewBiomes'] = (len(biomes.shape) == 3) - unrecognized_block_types = {} for section in chunk_data['Sections']: # Turn the skylight array into a 16x16x16 matrix. The array comes @@ -1755,9 +1754,9 @@ def get_chunk(self, x, z): section['BlockLight'] = blocklight_expanded if 'block_states' in section: - (blocks, data) = self._get_blockdata_v118(section, unrecognized_block_types, longarray_unpacker) + (blocks, data) = self._get_blockdata_v118(section, longarray_unpacker) elif 'Palette' in section: - (blocks, data) = self._get_blockdata_v113(section, unrecognized_block_types, longarray_unpacker) + (blocks, data) = self._get_blockdata_v113(section, longarray_unpacker) elif 'Data' in section: (blocks, data) = self._get_blockdata_v112(section) else: # Special case introduced with 1.14 @@ -1773,9 +1772,6 @@ def get_chunk(self, x, z): logging.debug("Full traceback:", exc_info=1) raise nbt.CorruptChunkError() - for k in unrecognized_block_types: - logging.debug("Found %d blocks of unknown type %s" % (unrecognized_block_types[k], k)) - return chunk_data From ea35d577f43df7cbf2356c5c27e752021367e9fe Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Fri, 8 Jul 2022 18:01:29 +0200 Subject: [PATCH 16/34] passed list of loaded models to worldpy --- overviewer_core/src/iterate.c | 7 ++ overviewer_core/textures.py | 123 ++++++++++++++++++++++++---------- overviewer_core/world.py | 21 +++++- 3 files changed, 114 insertions(+), 37 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index c8f5c186b..7d2ccb0d2 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -26,6 +26,7 @@ uint32_t max_data = 0; uint8_t* block_properties = NULL; static PyObject* known_blocks = NULL; +static PyObject* model_blocks = NULL; static PyObject* transparent_blocks = NULL; static PyObject* solid_blocks = NULL; static PyObject* fluid_blocks = NULL; @@ -63,6 +64,9 @@ PyObject* init_chunk_render(void) { known_blocks = PyObject_GetAttrString(textures, "known_blocks"); if (!known_blocks) return NULL; + model_blocks = PyObject_GetAttrString(textures, "block_models"); + if (!model_blocks) + return NULL; transparent_blocks = PyObject_GetAttrString(textures, "transparent_blocks"); if (!transparent_blocks) return NULL; @@ -137,6 +141,9 @@ bool load_chunk(RenderState* state, int32_t x, int32_t z, uint8_t required) { x += state->chunkx; z += state->chunkz; + + PyObject_CallMethod(state->regionset, "add_to_blockmap","O", model_blocks); + chunk = PyObject_CallMethod(state->regionset, "get_chunk", "ii", x, z); if (chunk == NULL) { // An exception is already set. RegionSet.get_chunk sets diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 976661dc4..4f20875f8 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -35,6 +35,7 @@ # global variables to collate information in @material decorators blockmap_generators = {} +block_models = {} known_blocks = set() used_datas = set() @@ -133,11 +134,20 @@ def generate(self): # generate biome grass mask self.biome_grass_texture = self.build_block(self.load_image_texture("assets/minecraft/textures/block/grass_block_top.png"), self.load_image_texture("assets/minecraft/textures/block/grass_block_side_overlay.png")) + global max_blockid, block_models + + models = self.find_models() + max_blockid = max_blockid+1 + for model in models: + solidmodelblock(blockid=max_blockid, name=model) + block_models['minecraft:'+model] = (max_blockid, 0) + + # print(str(block_models)) + # generate the blocks global blockmap_generators - global known_blocks, used_datas self.blockmap = [None] * max_blockid * max_data - + for (blockid, data), texgen in list(blockmap_generators.items()): tex = texgen(self, blockid, data) self.blockmap[blockid * max_data + data] = self.generate_texture_tuple(tex) @@ -147,15 +157,55 @@ def generate(self): self.biome_grass_texture = self.biome_grass_texture.resize(self.texture_dimensions, Image.ANTIALIAS) # rescale the rest - for i, tex in enumerate(blockmap): + for i, tex in enumerate(self.blockmap): if tex is None: continue block = tex[0] scaled_block = block.resize(self.texture_dimensions, Image.ANTIALIAS) - blockmap[i] = self.generate_texture_tuple(scaled_block) + self.blockmap[i] = self.generate_texture_tuple(scaled_block) self.generated = True + #TODO: load models from resource packs, for now only client jars are used + #TODO: load blockstate before models + def find_models(self, verbose=False): + filename = 'assets/minecraft/models/' + versiondir = self.versiondir(verbose) + available_versions = self.available_versions(versiondir, verbose) + + if not available_versions: + if verbose: logging.info("Did not find any non-snapshot minecraft jars >=1.8.0") + while(available_versions): + most_recent_version = available_versions.pop(0) + if verbose: logging.info("Trying {0}. Searching it for the file...".format(".".join(str(x) for x in most_recent_version))) + + jarname = ".".join(str(x) for x in most_recent_version) + jarpath = os.path.join(versiondir, jarname, jarname + ".jar") + + jar = {} + + if jarpath in self.jars: + jar = self.jars[jarpath] + elif os.path.isfile(jarpath): + try: + jar = zipfile.ZipFile(jarpath) + except (KeyError, IOError) as e: + pass + except (zipfile.BadZipFile) as e: + logging.warning("Your jar {0} is corrupted, I'll be skipping it, but you " + "should probably look into that.".format(jarpath)) + else: + if verbose: logging.info("Did not find file {0} in jar {1}".format(filename, jarpath)) + continue + + models = [] + for file in jar.namelist(): + if file.startswith('assets/minecraft/models/block'): + model = Path(file).stem + models.append(model) + + return models + ## ## Helpers for opening textures ## @@ -264,6 +314,37 @@ def find_file(self, filename, mode="rb", verbose=False): # Find an installed minecraft client jar and look in it for the texture # file we need. + versiondir = self.versiondir(verbose) + available_versions = self.available_versions(versiondir, verbose) + + if not available_versions: + if verbose: logging.info("Did not find any non-snapshot minecraft jars >=1.8.0") + while(available_versions): + most_recent_version = available_versions.pop(0) + if verbose: logging.info("Trying {0}. Searching it for the file...".format(".".join(str(x) for x in most_recent_version))) + + jarname = ".".join(str(x) for x in most_recent_version) + jarpath = os.path.join(versiondir, jarname, jarname + ".jar") + + if os.path.isfile(jarpath): + try: + jar = zipfile.ZipFile(jarpath) + jar.getinfo(filename) + if verbose: logging.info("Found %s in '%s'", filename, jarpath) + self.jars[jarpath] = jar + return jar.open(filename) + except (KeyError, IOError) as e: + pass + except (zipfile.BadZipFile) as e: + logging.warning("Your jar {0} is corrupted, I'll be skipping it, but you " + "should probably look into that.".format(jarpath)) + + if verbose: logging.info("Did not find file {0} in jar {1}".format(filename, jarpath)) + + + raise TextureException("Could not find the textures while searching for '{0}'. Try specifying the 'texturepath' option in your config file.\nSet it to the path to a Minecraft Resource pack.\nAlternately, install the Minecraft client (which includes textures)\nAlso see \n(Remember, this version of Overviewer requires a 1.19-compatible resource pack)\n(Also note that I won't automatically use snapshots; you'll have to use the texturepath option to use a snapshot jar)".format(filename)) + + def versiondir(self, verbose): versiondir = "" if "APPDATA" in os.environ and sys.platform.startswith("win"): versiondir = os.path.join(os.environ['APPDATA'], ".minecraft", "versions") @@ -274,7 +355,9 @@ def find_file(self, filename, mode="rb", verbose=False): # For Mac: versiondir = os.path.join(os.environ['HOME'], "Library", "Application Support", "minecraft", "versions") + return versiondir + def available_versions(self, versiondir, verbose): try: if verbose: logging.info("Looking in the following directory: \"%s\"" % versiondir) versions = os.listdir(versiondir) @@ -306,32 +389,8 @@ def find_file(self, filename, mode="rb", verbose=False): available_versions.append(versionparts) available_versions.sort(reverse=True) - if not available_versions: - if verbose: logging.info("Did not find any non-snapshot minecraft jars >=1.8.0") - while(available_versions): - most_recent_version = available_versions.pop(0) - if verbose: logging.info("Trying {0}. Searching it for the file...".format(".".join(str(x) for x in most_recent_version))) - jarname = ".".join(str(x) for x in most_recent_version) - jarpath = os.path.join(versiondir, jarname, jarname + ".jar") - - if os.path.isfile(jarpath): - try: - jar = zipfile.ZipFile(jarpath) - jar.getinfo(filename) - if verbose: logging.info("Found %s in '%s'", filename, jarpath) - self.jars[jarpath] = jar - return jar.open(filename) - except (KeyError, IOError) as e: - pass - except (zipfile.BadZipFile) as e: - logging.warning("Your jar {0} is corrupted, I'll be skipping it, but you " - "should probably look into that.".format(jarpath)) - - if verbose: logging.info("Did not find file {0} in jar {1}".format(filename, jarpath)) - - - raise TextureException("Could not find the textures while searching for '{0}'. Try specifying the 'texturepath' option in your config file.\nSet it to the path to a Minecraft Resource pack.\nAlternately, install the Minecraft client (which includes textures)\nAlso see \n(Remember, this version of Overviewer requires a 1.19-compatible resource pack)\n(Also note that I won't automatically use snapshots; you'll have to use the texturepath option to use a snapshot jar)".format(filename)) + return available_versions def load_image_texture(self, filename): # Textures may be animated or in a different resolution than 16x16. @@ -376,8 +435,6 @@ def load_image(self, filename): self.texture_cache[filename] = img return img - - def load_water(self): """Special-case function for loading water.""" watertexture = getattr(self, "watertexture", None) @@ -525,7 +582,6 @@ def transform_image_slope(img): return newimg - @staticmethod def transform_image_angle(img, angle): """Takes an image an shears it in arbitrary angle with the axis of @@ -566,7 +622,6 @@ def transform_image_angle(img, angle): return newimg - def build_block(self, top, side): """From a top texture and a side texture, build a block image. top and side should be 16x16 image objects. Returns a 24x24 image @@ -899,7 +954,6 @@ def build_block_from_model(self, modelname, blockstate={}): # element has an invalid texture; skipping entire element continue # draw each face - # Manually touch up 6 pixels that leave a gap because of how the # shearing works out. This makes the blocks perfectly tessellate-able for x,y in [(13,23), (17,21), (21,19)]: @@ -5577,7 +5631,6 @@ def structure_block(self, blockid, data): raise Exception('unexpected structure block: ' + str(data)) # Jigsaw block -# doesnt actually render @material(blockid=256, data=list(range(6)), solid=True) def jigsaw_block(self, blockid, data): facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data%6] diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 2ce5d715f..c3cfef1e9 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -40,6 +40,8 @@ class UnsupportedVersion(Exception): class UnknownBlockException(Exception): pass +modelblocks = {} + def log_other_exceptions(func): """A decorator that prints out any errors that are not ChunkDoesntExist errors. This should decorate any functions or @@ -1126,10 +1128,19 @@ def _get_block(self, palette_entry): colors = ['white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime', 'pink', 'gray', 'light_gray', 'cyan', 'purple', 'blue', 'brown', 'green', 'red', 'black'] + global modelblocks + key = palette_entry['Name'] - if key not in self._blockmap: + if key in self._blockmap: + (block, data) = self._blockmap[key] + elif key in modelblocks: + (block, data) = modelblocks[key] + print('found ' + str(block) + ' : ' + str(key)) + else: + print(str(type(modelblocks))) + print('unknown key ' + key ) raise UnknownBlockException(key) - (block, data) = self._blockmap[key] + if key in ['minecraft:redstone_ore', 'minecraft:redstone_lamp']: if palette_entry['Properties']['lit'] == 'true': block += 1 @@ -1602,6 +1613,10 @@ def _get_blockdata_v112(self, section): return (blocks, data_expanded) + def add_to_blockmap(self, blockmap): + global modelblocks + modelblocks = blockmap + #@log_other_exceptions def get_chunk(self, x, z): """Returns a dictionary object representing the "Level" NBT Compound @@ -1902,6 +1917,8 @@ def iterate_newer_chunks(self,filemtime): return self._r.iterate_newer_chunks(filemtime) def get_chunk_mtime(self, x, z): return self._r.get_chunk_mtime(x,z) + def add_to_blockmap(self, blockmap): + return self._r.add_to_blockmap(blockmap) # see RegionSet.rotate. These values are chosen so that they can be # passed directly to rot90; this means that they're the number of From 42aaf72ea43ab54cedc738f149ea6686dd651b81 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Sat, 9 Jul 2022 22:35:34 +0200 Subject: [PATCH 17/34] removes all simple blocks from textures.py --- overviewer_core/src/block_class.c | 5 +- overviewer_core/src/iterate.c | 1 - overviewer_core/src/mc_id.h | 102 +--- .../src/primitives/overlay-mineral.c | 13 +- overviewer_core/textures.py | 577 +++++------------- overviewer_core/world.py | 198 +----- 6 files changed, 184 insertions(+), 712 deletions(-) diff --git a/overviewer_core/src/block_class.c b/overviewer_core/src/block_class.c index 27299160c..65f93ce4b 100644 --- a/overviewer_core/src/block_class.c +++ b/overviewer_core/src/block_class.c @@ -162,6 +162,7 @@ const mc_block_t block_class_door[] = { block_acacia_door, block_dark_oak_door, block_crimson_door, + block_mangrove_door, block_warped_door}; const size_t block_class_door_len = COUNT_OF(block_class_door); @@ -174,6 +175,7 @@ const mc_block_t block_class_ancil[] = { block_acacia_door, block_dark_oak_door, block_crimson_door, + block_mangrove_door, block_oak_stairs, block_brick_stairs, block_stone_brick_stairs, @@ -252,7 +254,8 @@ const mc_block_t block_class_ancil[] = { block_cobbled_deepslate_wall, block_polished_deepslate_wall, block_deepslate_brick_wall, - block_deepslate_tile_wall}; + block_deepslate_tile_wall, + block_mud_brick_wall}; const size_t block_class_ancil_len = COUNT_OF(block_class_ancil); const mc_block_t block_class_alt_height[] = { diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index 7d2ccb0d2..b509eceb1 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -141,7 +141,6 @@ bool load_chunk(RenderState* state, int32_t x, int32_t z, uint8_t required) { x += state->chunkx; z += state->chunkz; - PyObject_CallMethod(state->regionset, "add_to_blockmap","O", model_blocks); chunk = PyObject_CallMethod(state->regionset, "get_chunk", "ii", x, z); diff --git a/overviewer_core/src/mc_id.h b/overviewer_core/src/mc_id.h index dd3126fc6..1442f2139 100644 --- a/overviewer_core/src/mc_id.h +++ b/overviewer_core/src/mc_id.h @@ -3,21 +3,18 @@ #include +// enum to keep track of blocks that have special rendering effects + enum mc_block_id { block_air = 0, - block_stone = 1, block_grass = 2, - block_dirt = 3, block_cobblestone = 4, - block_planks = 5, block_sapling = 6, block_bedrock = 7, block_flowing_water = 8, block_water = 9, block_flowing_lava = 10, block_lava = 11, - block_sand = 12, - block_gravel = 13, block_gold_ore = 14, block_iron_ore = 15, block_coal_ore = 16, @@ -28,8 +25,6 @@ enum mc_block_id { block_lapis_ore = 21, block_lapis_block = 22, block_dispenser = 23, - block_sandstone = 24, - block_noteblock = 25, block_bed = 26, block_golden_rail = 27, block_detector_rail = 28, @@ -39,7 +34,6 @@ enum mc_block_id { block_deadbush = 32, block_piston = 33, block_piston_head = 34, - block_wool = 35, block_yellow_flower = 37, block_red_flower = 38, block_brown_mushroom = 39, @@ -48,11 +42,8 @@ enum mc_block_id { block_iron_block = 42, block_double_stone_slab = 43, block_stone_slab = 44, - block_brick_block = 45, block_tnt = 46, - block_bookshelf = 47, block_mossy_cobblestone = 48, - block_obsidian = 49, block_torch = 50, block_fire = 51, block_mob_spawner = 52, @@ -61,7 +52,6 @@ enum mc_block_id { block_redstone_wire = 55, block_diamond_ore = 56, block_diamond_block = 57, - block_crafting_table = 58, block_wheat = 59, block_farmland = 60, block_furnace = 61, @@ -77,22 +67,16 @@ enum mc_block_id { block_iron_door = 71, block_wooden_pressure_plate = 72, block_redstone_ore = 73, - block_lit_redstone_ore = 74, block_unlit_redstone_torch = 75, block_redstone_torch = 76, block_stone_button = 77, block_snow_layer = 78, block_ice = 79, - block_snow = 80, block_cactus = 81, - block_clay = 82, block_reeds = 83, - block_jukebox = 84, block_fence = 85, - block_pumpkin = 86, block_netherrack = 87, block_soul_sand = 88, - block_glowstone = 89, block_portal = 90, block_lit_pumpkin = 91, block_cake = 92, @@ -101,21 +85,18 @@ enum mc_block_id { block_stained_glass = 95, block_trapdoor = 96, block_monster_egg = 97, - block_stonebrick = 98, + block_infested_stone_bricks = 98, block_brown_mushroom_block = 99, block_red_mushroom_block = 100, block_iron_bars = 101, block_glass_pane = 102, - block_melon_block = 103, block_pumpkin_stem = 104, block_melon_stem = 105, block_vine = 106, block_fence_gate = 107, block_brick_stairs = 108, block_stone_brick_stairs = 109, - block_mycelium = 110, block_waterlily = 111, - block_nether_brick = 112, block_nether_brick_fence = 113, block_nether_brick_stairs = 114, block_nether_wart = 115, @@ -124,10 +105,8 @@ enum mc_block_id { block_cauldron = 118, block_end_portal = 119, block_end_portal_frame = 120, - block_end_stone = 121, block_dragon_egg = 122, block_redstone_lamp = 123, - block_lit_redstone_lamp = 124, block_double_wooden_slab = 125, block_wooden_slab = 126, block_cocoa = 127, @@ -136,11 +115,9 @@ enum mc_block_id { block_ender_chest = 130, block_tripwire_hook = 131, block_tripwire_wire = 132, - block_emerald_block = 133, block_spruce_stairs = 134, block_birch_stairs = 135, block_jungle_stairs = 136, - block_command_block = 137, block_beacon = 138, block_mushroom_stem = 139, block_flower_pot = 140, @@ -155,14 +132,11 @@ enum mc_block_id { block_unpowered_comparator = 149, block_powered_comparator = 150, block_daylight_detector = 151, - block_redstone_block = 152, block_quartz_ore = 153, block_hopper = 154, - block_quartz_block = 155, block_quartz_stairs = 156, block_activator_rail = 157, block_dropper = 158, - block_stained_hardened_clay = 159, block_stained_glass_pane = 160, block_leaves2 = 161, block_log2 = 162, @@ -173,18 +147,13 @@ enum mc_block_id { block_slime = 165, block_barrier = 166, block_iron_trapdoor = 167, - block_prismarine = 168, block_sea_lantern = 169, block_hay_block = 170, block_carpet = 171, - block_hardened_clay = 172, - block_coal_block = 173, - block_packed_ice = 174, block_double_plant = 175, block_standing_banner = 176, block_wall_banner = 177, block_daylight_detector_inverted = 178, - block_red_sandstone = 179, block_red_sandstone_stairs = 180, block_smooth_red_sandstone_stairs = 11415, block_double_stone_slab2 = 181, @@ -196,6 +165,8 @@ enum mc_block_id { block_acacia_fence_gate = 187, block_crimson_fence_gate = 513, block_warped_fence_gate = 514, + block_mangrove_fence_gate = 455, + block_mangrove_fence = 456, block_spruce_fence = 188, block_birch_fence = 189, block_jungle_fence = 190, @@ -207,13 +178,13 @@ enum mc_block_id { block_birch_door = 194, block_jungle_door = 195, block_acacia_door = 196, + block_mangrove_door = 457, block_crimson_door = 499, block_warped_door = 500, block_dark_oak_door = 197, block_end_rod = 198, block_chorus_plant = 199, block_chorus_flower = 200, - block_purpur_block = 201, block_purpur_pillar = 202, block_purpur_stairs = 203, block_purpur_double_slab = 204, @@ -222,12 +193,7 @@ enum mc_block_id { block_beetroots = 207, block_dirt_path = 208, block_end_gateway = 209, - block_repeating_command_block = 210, - block_chain_command_block = 211, block_frosted_ice = 212, - block_magma = 213, - block_nether_wart_block = 214, - block_red_nether_brick = 215, block_bone_block = 216, block_structure_void = 217, block_observer = 218, @@ -263,22 +229,18 @@ enum mc_block_id { block_green_glazed_terracotta = 248, block_red_glazed_terracotta = 249, block_black_glazed_terracotta = 250, - block_concrete = 251, - block_concrete_powder = 252, block_structure_block = 255, block_jigsaw = 256, block_shulker_box = 257, + + block_mangrove_trapdoor = 451, + block_mangrove_wall_sign = 454, // 1.16 stuff block_ancient_debris = 1000, block_basalt = 1001, block_polished_basalt = 1002, block_soul_campfire = 1003, block_blackstone = 1004, - block_netherite_block = 1005, - block_warped_nylium = 1006, - block_crimson_nylium = 1007, - block_warped_wart_block = 1010, - block_shroomlight = 1011, block_twisting_vines = 1012, block_twisting_vines_plant = 1013, block_weeping_vines = 1014, @@ -289,13 +251,6 @@ enum mc_block_id { block_crimson_roots = 1019, block_soul_soil = 1020, block_nether_gold_ore = 1021, - // Solid Nether stone blocks - block_polished_blackstone = 1022, - block_chiseled_polished_blackstone = 1023, - block_gilded_blackstone = 1024, - block_cracked_polished_blackstone_bricks = 1025, - block_polished_blackstone_bricks = 1026, - block_quartz_bricks = 1041, // Nether stone stairs block_blackstone_stairs = 1030, block_polished_blackstone_stairs = 1031, @@ -304,8 +259,6 @@ enum mc_block_id { block_polished_blackstone_pressure_plate = 1033, block_polished_blackstone_button = 1034, // advanced nether blocks - block_crying_obsidian = 1035, - block_lodestone = 1036, block_respawn_anchor = 1037, // soul lightning block_soul_lantern = 1038, @@ -313,29 +266,17 @@ enum mc_block_id { block_soul_fire = 1040, // 1.17 - block_amethyst = 1042, - block_raw_iron = 1043, - block_raw_gold = 1044, block_budding_amethyst = 1045, - block_copper = 1046, - block_exposed_copper = 1047, - block_weathered_copper = 1048, - block_oxidized_copper = 1049, block_waxed_copper = 1050, block_waxed_exposed_copper = 1051, block_waxed_weathered_copper = 1052, block_waxed_oxidized_copper = 1053, - block_cut_copper = 1054, - block_exposed_cut_copper = 1055, - block_weathered_cut_copper = 1056, - block_oxidized_cut_copper = 1057, block_waxed_cut_copper = 1058, block_waxed_exposed_cut_copper = 1059, block_waxed_weathered_cut_copper = 1060, block_waxed_oxidized_cut_copper = 1061, - block_raw_copper = 1062, block_copper_ore = 1063, block_cut_copper_stairs = 1064, @@ -358,13 +299,7 @@ enum mc_block_id { block_waxed_weathered_cut_copper_slab = 1078, block_waxed_oxidized_cut_copper_slab = 1079, - block_moss = 1080, - block_calcite = 1081, - block_rooted_dirt = 1082, - block_deepslate = 1083, - block_cobbled_deepslate = 1084, - block_polished_deepslate = 1085, block_deepslate_coal_ore = 1086, block_deepslate_iron_ore = 1087, block_deepslate_copper_ore = 1088, @@ -373,11 +308,6 @@ enum mc_block_id { block_deepslate_lapis_ore = 1091, block_deepslate_diamond_ore = 1092, block_deepslate_redstone_ore = 1093, - block_deepslate_bricks = 1094, - block_cracked_deepslate_bricks = 1095, - block_deepslate_tiles = 1096, - block_cracked_deepslate_tiles = 1097, - block_chiseled_deepslate = 1098, block_cobbled_deepslate_stairs = 1099, block_polished_deepslate_stairs = 1100, @@ -389,12 +319,8 @@ enum mc_block_id { block_deepslate_brick_slab = 1105, block_deepslate_tile_slab = 1106, - block_dripstone = 1107, - block_smooth_basalt = 1108, - block_tuff = 1109, block_pointed_dripstone = 1110, - block_powder_snow = 1111, block_hanging_roots = 1112, block_small_amethyst_bud = 1113, block_medium_amethyst_bud = 1114, @@ -405,13 +331,9 @@ enum mc_block_id { block_glow_lichen = 1119, block_spore_blossom = 1120, - block_mud = 1121, - block_packed_mud = 1122, - block_mud_bricks = 1123, block_mud_brick_slab = 1124, block_mangrove_roots = 1125, block_mangrove_log = 1126, - block_muddy_mangrove_roots = 1127, // adding a gap in the numbering of walls to keep them all // in one numbering block starting at 1792 @@ -438,6 +360,8 @@ enum mc_block_id { block_polished_deepslate_wall = 1810, block_deepslate_brick_wall = 1811, block_deepslate_tile_wall = 1812, + block_mud_brick_wall = 1813, + // end of walls block_prismarine_stairs = 11337, @@ -465,9 +389,6 @@ enum mc_block_id { block_mossy_stone_brick_slab = 11356, block_smooth_quartz_slab = 11357, block_smooth_stone_slab = 11358, - block_fletching_table = 11359, - block_cartography_table = 11360, - block_smithing_table = 11361, block_blast_furnace = 11362, // block_blast_furnace lit 11363 block_smoker = 11364, @@ -519,7 +440,6 @@ enum mc_block_id { // 1.15 blocks below block_beehive = 11501, block_bee_nest = 11502, - block_honeycomb_block = 11503, block_honey_block = 11504, block_sweet_berry_bush = 11505, block_campfire = 11506, diff --git a/overviewer_core/src/primitives/overlay-mineral.c b/overviewer_core/src/primitives/overlay-mineral.c index f8bba9006..66043acee 100644 --- a/overviewer_core/src/primitives/overlay-mineral.c +++ b/overviewer_core/src/primitives/overlay-mineral.c @@ -33,16 +33,27 @@ struct MineralColor { /* put more valuable ores first -- they take precedence */ static struct MineralColor default_minerals[] = { {block_mossy_cobblestone, 31, 153, 9}, + {block_deepslate_emerald_ore, 0, 255, 0}, {block_diamond_ore, 32, 230, 220}, + {block_deepslate_diamond_ore, 32, 230, 220}, {block_lapis_ore, 0, 23, 176}, + {block_deepslate_lapis_ore, 0, 23, 176}, {block_gold_ore, 255, 234, 0}, + {block_deepslate_gold_ore, 255, 234, 0}, + + {block_emerald_ore, 0, 255, 0}, {block_iron_ore, 204, 204, 204}, + {block_deepslate_iron_ore, 204, 204, 204}, {block_redstone_ore, 186, 0, 0}, - {block_lit_redstone_ore, 186, 0, 0}, + {block_deepslate_redstone_ore, 186, 0, 0}, {block_coal_ore, 54, 54, 54}, + {block_deepslate_coal_ore, 54, 54, 54}, + + {block_copper_ore, 254, 154, 54}, + {block_deepslate_copper_ore, 254, 154, 54}, /* end of list marker */ {0, 0, 0, 0}}; diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 4f20875f8..d0979a85f 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -41,6 +41,7 @@ used_datas = set() max_blockid = 0 max_data = 0 +next_unclaimed_id = 1 transparent_blocks = set() solid_blocks = set() @@ -134,16 +135,6 @@ def generate(self): # generate biome grass mask self.biome_grass_texture = self.build_block(self.load_image_texture("assets/minecraft/textures/block/grass_block_top.png"), self.load_image_texture("assets/minecraft/textures/block/grass_block_side_overlay.png")) - global max_blockid, block_models - - models = self.find_models() - max_blockid = max_blockid+1 - for model in models: - solidmodelblock(blockid=max_blockid, name=model) - block_models['minecraft:'+model] = (max_blockid, 0) - - # print(str(block_models)) - # generate the blocks global blockmap_generators self.blockmap = [None] * max_blockid * max_data @@ -865,6 +856,10 @@ def generate_texture_tuple(self, img): return None return (img, self.generate_opaque_mask(img)) + # + # This part if for reading the models/*.json assets. + # + models = {} def load_model(self, modelname): @@ -881,8 +876,6 @@ def load_model(self, modelname): self.models[modelname]['textures'].update(parent['textures']) if 'elements' in parent: if 'elements' in self.models[modelname]: - # print(modelname + ' : ' + str(type(self.models[modelname]))) - # self.models[modelname]['elements'].update(parent['elements']) self.models[modelname]['elements'] += parent['elements'] else: self.models[modelname]['elements'] = parent['elements'] @@ -894,7 +887,7 @@ def load_model(self, modelname): # fix known inconsistencies in model info def normalize_model(self, modelname): match modelname: - # observer top texture is inconsistent in rotation + # remap textures of blocks with the rotation property to match the mapping of the observer textures case 'block/loom': self.models[modelname] = deepcopy(self.models[modelname]) self.models[modelname]['elements'][0]['faces']['up']['texturerotation'] = 180 @@ -919,14 +912,11 @@ def build_block_from_model(self, modelname, blockstate={}): colmodel = self.load_model(modelname) - # if modelname in {'block/barrel_open'}: - # print(json.dumps(self.models[modelname], indent=4)) - - img = Image.new("RGBA", (24,24), self.bgcolor) - if 'elements' not in colmodel: return None + img = Image.new("RGBA", (24,24), self.bgcolor) + # for each elements for elem in colmodel['elements']: try: @@ -953,7 +943,7 @@ def build_block_from_model(self, modelname, blockstate={}): except KeyError: # element has an invalid texture; skipping entire element continue - # draw each face + # Manually touch up 6 pixels that leave a gap because of how the # shearing works out. This makes the blocks perfectly tessellate-able for x,y in [(13,23), (17,21), (21,19)]: @@ -975,6 +965,7 @@ def orientation_from_numvalue(self, orientation): # facing is the blockproperty # targetfacing is the direction in witch the north is rotated def map_facing_to_real(self, blockfacing, targetblockface): + resultface = blockfacing if blockfacing == 'up': if targetblockface == 'up': resultface = 'north' @@ -982,8 +973,6 @@ def map_facing_to_real(self, blockfacing, targetblockface): resultface = 'west' elif targetblockface == 'west': resultface = 'down' - else: - raise Exception('unexpected facing direction: ' + blockfacing + ' ' + targetblockface) elif blockfacing == 'down': if targetblockface == 'west': resultface = 'down' @@ -991,8 +980,6 @@ def map_facing_to_real(self, blockfacing, targetblockface): resultface = 'west' elif targetblockface == 'up': resultface = 'south' - else: - raise Exception('unexpected facing direction: ' + blockfacing + ' ' + targetblockface) elif targetblockface == 'up': resultface = 'up' elif targetblockface == 'down': @@ -1005,25 +992,21 @@ def map_axis_to_real(self, axis, textureface): match axis: case 'x': return {'up':'north','north':'down','down':'south','south':'up','east':'east','west':'west'}[textureface] - case 'y': - return textureface case 'z': return {'up':'west','west':'down','down':'east','east':'up','north':'north','south':'south'}[textureface] - case _: - raise Exception() + case 'y' | _: + return textureface def axis_rotation(self, axis, face, texture): match axis: case 'x': rotation = {'up':270,'north':0,'down':0,'south':0,'east':270,'west':270}[face] return texture.rotate(rotation) - case 'y': - return texture case 'z': rotation = {'up':0,'west':0,'down':0,'east':0,'north':90,'south':90}[face] return texture.rotate(rotation) - case _: - raise Exception() + case 'y' | _: + return texture def draw_face(self, direction, elem, data, blockstate, modelname): textureface = direction @@ -1033,19 +1016,9 @@ def draw_face(self, direction, elem, data, blockstate, modelname): textureface = self.map_axis_to_real(blockstate['axis'], direction) texture = self.find_texture_from_model(elem['faces'][textureface]['texture'], data['textures']).copy() - # if 'uv' in elem['faces'][textureface]: - # TODO: implement uv - # print('uv defined in ' + modelname + ' as ' + str(elem['faces'][textureface]['uv'])) - # texture = self.crop_to_transparancy(texture, elem['faces'][textureface]['uv']) - # texture = self.adjust_texture_rotation(textureface, texture, modelname) - # if 'rotation' in elem: - # TODO: implement rotation - # rotation only exists as 45, 22,5 -22,5 and - 45 - # print('rotation: ' + str(elem['rotation']['angle'])) - # texture = self.transform_image_angle(texture, elem['rotation']['angle']*-1) if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) - # else: + texture = self.transform_texture(direction, texture, blockstate, elem['faces'][textureface]) texture = self.adjust_lighting(direction,texture) @@ -1053,8 +1026,6 @@ def draw_face(self, direction, elem, data, blockstate, modelname): def adjust_lighting(self, direction, texture): match direction: - case 'down' | 'up': - return texture case 'south' | 'west': sidealpha = texture.split()[3] texture = ImageEnhance.Brightness(texture).enhance(0.8) @@ -1065,8 +1036,8 @@ def adjust_lighting(self, direction, texture): texture = ImageEnhance.Brightness(texture).enhance(0.9) texture.putalpha(sidealpha) return texture - case _: - raise Exception() + case 'down' | 'up' | _: + return texture def transform_texture(self, direction, texture, blockstate, faceinfo): rotation = 0 @@ -1094,8 +1065,6 @@ def transform_texture(self, direction, texture, blockstate, faceinfo): texture = texture.transpose(Image.FLIP_LEFT_RIGHT) texture = self.transform_image_side(texture.rotate(rotation)) texture = texture.transpose(Image.FLIP_LEFT_RIGHT) - case _: - raise Exception() return texture @@ -1105,6 +1074,7 @@ def find_texture_from_model(self, face, textureset): else: return self.load_image_texture("assets/minecraft/textures/" + re.sub('.*:','',face) + '.png') + ## TODO: deal with uv, from, to def crop_to_transparancy(self, img, area): # top ImageDraw.Draw(img).rectangle((area[2],0,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -1116,10 +1086,6 @@ def crop_to_transparancy(self, img, area): ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) return img - def adjust_texture_rotation(self, direction, texture, modelname): - rotation = {'up':90,'north':0,'down':90,'south':90,'east':0,'west':0}[direction] - return texture.rotate(rotation) - ## ## The other big one: @material and associated framework ## @@ -1218,28 +1184,25 @@ def inner_billboard(self, unused_id, unused_data): return self.build_billboard(self.load_image_texture(imagename)) return inner_billboard +def unbound_models(): + global max_blockid, block_models, next_unclaimed_id + + models = Textures.find_models(Textures()) + for model in models: + # find next unclaimed id to keep id values as low as possible + while (next_unclaimed_id, 0) in blockmap_generators: + next_unclaimed_id = next_unclaimed_id + 1 + # 1792 to 2047 is a reserved range for wall blocks + if next_unclaimed_id < 2048 and next_unclaimed_id > 1791: + next_unclaimed_id = 2048 + id = next_unclaimed_id + solidmodelblock(blockid=id, name=model) + block_models['minecraft:'+model] = (id, 0) + ## -## and finally: actual texture definitions +## the texture definitions for all blocks that have special rendering conditions ## -# stone -@material(blockid=1, data=list(range(7)), solid=True) -def stone(self, blockid, data): - if data == 0: # regular old-school stone - return self.build_block_from_model('stone') - elif data == 1: # granite - return self.build_block_from_model('granite') - elif data == 2: # polished granite - return self.build_block_from_model('polished_granite') - elif data == 3: # diorite - return self.build_block_from_model('diorite') - elif data == 4: # polished diorite - return self.build_block_from_model('polished_diorite') - elif data == 5: # andesite - return self.build_block_from_model('andesite') - elif data == 6: # polished andesite - return self.build_block_from_model('polished_andesite') - @material(blockid=2, data=list(range(11))+[0x10,], solid=True) def grass(self, blockid, data): if data & 0x10: @@ -1250,45 +1213,12 @@ def grass(self, blockid, data): alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture) return img -# dirt -@material(blockid=3, data=list(range(3)), solid=True) -def dirt_blocks(self, blockid, data): - if data == 0: - return self.build_block_from_model('dirt') - if data == 1: - return self.build_block_from_model('coarse_dirt') - if data == 2: - return self.build_block_from_model('podzol') - -solidmodelblock(blockid=4, name='cobblestone') - -# wooden planks -@material(blockid=5, data=list(range(8)), solid=True) -def wooden_planks(self, blockid, data): - if data == 0: # normal - return self.build_block_from_model('oak_planks') - if data == 1: # pine - return self.build_block_from_model('spruce_planks') - if data == 2: # birch - return self.build_block_from_model('birch_planks') - if data == 3: # jungle wood - return self.build_block_from_model('jungle_planks') - if data == 4: # acacia - return self.build_block_from_model('acacia_planks') - if data == 5: # dark oak - return self.build_block_from_model('dark_oak_planks') - if data == 6: # crimson - return self.build_block_from_model('crimson_planks') - if data == 7: # warped - return self.build_block_from_model('warped_planks') - @material(blockid=6, data=list(range(16)), transparent=True) def saplings(self, blockid, data): - # TODO: generify block/cross # usual saplings - if data & 0x3 == 0: - tex = self.load_image_texture("assets/minecraft/textures/block/oak_sapling.png") - elif data & 0x3 == 1: # spruce sapling + tex = self.load_image_texture("assets/minecraft/textures/block/oak_sapling.png") + + if data & 0x3 == 1: # spruce sapling tex = self.load_image_texture("assets/minecraft/textures/block/spruce_sapling.png") elif data & 0x3 == 2: # birch sapling tex = self.load_image_texture("assets/minecraft/textures/block/birch_sapling.png") @@ -1298,23 +1228,20 @@ def saplings(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/acacia_sapling.png") elif data & 0x3 == 5: # dark oak/roofed oak/big oak sapling tex = self.load_image_texture("assets/minecraft/textures/block/dark_oak_sapling.png") - else: - raise Exception('unknown sapling id ' + str(data)) return self.build_sprite(tex) -transparentmodelblock(blockid=11385, name="oak_sapling") -transparentmodelblock(blockid=11386, name="spruce_sapling") -transparentmodelblock(blockid=11387, name="birch_sapling") -transparentmodelblock(blockid=11388, name="jungle_sapling") -transparentmodelblock(blockid=11389, name="acacia_sapling") -transparentmodelblock(blockid=11390, name="dark_oak_sapling") +sprite(blockid=11385, imagename="assets/minecraft/textures/block/oak_sapling.png") +sprite(blockid=11386, imagename="assets/minecraft/textures/block/spruce_sapling.png") +sprite(blockid=11387, imagename="assets/minecraft/textures/block/birch_sapling.png") +sprite(blockid=11388, imagename="assets/minecraft/textures/block/jungle_sapling.png") +sprite(blockid=11389, imagename="assets/minecraft/textures/block/acacia_sapling.png") +sprite(blockid=11390, imagename="assets/minecraft/textures/block/dark_oak_sapling.png") sprite(blockid=11413, imagename="assets/minecraft/textures/block/bamboo_stage0.png") # bedrock solidmodelblock(blockid=7, name='bedrock') -# TODO: There is no transparency information in the model json files. The png files do contain transparancy. Create static list for this data. # water, glass, and ice (no inner surfaces) # uses pseudo-ancildata found in iterate.c @material(blockid=[8, 9, 20, 79, 95], data=list(range(512)), fluid=(8, 9), transparent=True, nospawn=True, solid=(79, 20, 95)) @@ -1359,16 +1286,7 @@ def lava(self, blockid, data): lavatex = self.load_lava() return self.build_block(lavatex, lavatex) -# sand -@material(blockid=12, data=list(range(2)), solid=True) -def sand_blocks(self, blockid, data): - if data == 0: # normal - return self.build_block_from_model('sand') - else: # red - return self.build_block_from_model('red_sand') - -# gravel -solidmodelblock(blockid=13, name='gravel') +# Mineral overlay blocks # gold ore solidmodelblock(blockid=14, name='gold_ore') # iron ore @@ -1474,9 +1392,8 @@ def wood(self, blockid, data): if type == 1: return self.build_block_from_model('stripped_mangrove_log', blockstate) - return self.build_block_from_model('redstone_block', blockstate) + return self.build_block_from_model('oak_log', blockstate) -# TODO: transparency @material(blockid=[18, 161], data=list(range(16)), transparent=True, solid=True) def leaves(self, blockid, data): # mask out the bits 4 and 8 @@ -1501,8 +1418,14 @@ def leaves(self, blockid, data): else: return self.build_block_from_model("mangrove_leaves") -# sponge -solidmodelblock(blockid=19, name='sponge') +@material(blockid=19, data=list(range(2)), solid=True) +def sponge(self, blockid, data): + if data == 0: + return self.build_block_from_model('sponge') + if data == 1: + return self.build_block_from_model('wet_sponge') + +# mineral overlay # lapis lazuli ore solidmodelblock(blockid=21, name="lapis_ore") # lapis lazuli block @@ -1541,30 +1464,6 @@ def furnaces(self, blockid, data): return self.build_block_from_model('smoker_on', {'facing':facing}) return self.build_block_from_model('smoker', {'facing':facing}) -# sandstone -@material(blockid=24, data=list(range(3)), solid=True) -def sandstone(self, blockid, data): - top = self.load_image_texture("assets/minecraft/textures/block/sandstone_top.png") - if data == 0: # normal - return self.build_block_from_model('sandstone') - if data == 1: # hieroglyphic - return self.build_block_from_model("chiseled_sandstone") - if data == 2: # soft - return self.build_block_from_model("cut_sandstone") - -# red sandstone -@material(blockid=179, data=list(range(3)), solid=True) -def sandstone(self, blockid, data): - if data == 0: # normal - return self.build_block_from_model('red_sandstone') - if data == 1: # hieroglyphic - return self.build_block_from_model('chiseled_red_sandstone') - if data == 2: # soft - return self.build_block_from_model('cut_red_sandstone') - -# note block -solidmodelblock(blockid=25, name="note_block") - # Bed @material(blockid=26, data=list(range(256)), transparent=True, nospawn=True) def bed(self, blockid, data): @@ -1925,10 +1824,6 @@ def tall_grass(self, blockid, data): # dead bush billboard(blockid=32, imagename="assets/minecraft/textures/block/dead_bush.png") -@material(blockid=35, data=list(range(16)), solid=True) -def wool(self, blockid, data): - return self.build_block_from_model("%s_wool" % color_map[data]) - # dandelion sprite(blockid=37, imagename="assets/minecraft/textures/block/dandelion.png") @@ -1954,6 +1849,7 @@ def flower(self, blockid, data): # crimson roots sprite(blockid=1019, imagename="assets/minecraft/textures/block/crimson_roots.png") +# mineral overlay # block of gold solidmodelblock(blockid=41, name="gold_block") # block of iron @@ -2090,16 +1986,11 @@ def slabs(self, blockid, data): return self.build_slab_block(top, side, data & 8 == 8); -# brick block -solidmodelblock(blockid=45, name="bricks") # TNT solidmodelblock(blockid=46, name="tnt", nospawn=True) -# bookshelf -solidmodelblock(blockid=47, name="bookshelf") +# mineral overlay # moss stone solidmodelblock(blockid=48, name="mossy_cobblestone") -# obsidian -solidmodelblock(blockid=49, name="obsidian") # torch, redstone torch (off), redstone torch(on), soul_torch @material(blockid=[50, 75, 76, 1039], data=[1, 2, 3, 4, 5], transparent=True) @@ -2320,19 +2211,9 @@ def composter(self, blockid, data): @material(blockid=[51, 1040], transparent=True) def fire(self, blockid, data): if blockid == 51: - textureNS = self.load_image_texture("assets/minecraft/textures/block/fire_0.png") - textureEW = self.load_image_texture("assets/minecraft/textures/block/fire_1.png") - elif blockid == 1040: - textureNS = self.load_image_texture("assets/minecraft/textures/block/soul_fire_0.png") - textureEW = self.load_image_texture("assets/minecraft/textures/block/soul_fire_1.png") - side1 = self.transform_image_side(textureNS) - side2 = self.transform_image_side(textureEW).transpose(Image.FLIP_LEFT_RIGHT) - img = Image.new("RGBA", (24,24), self.bgcolor) - alpha_over(img, side1, (12,0), side1) - alpha_over(img, side2, (0,0), side2) - alpha_over(img, side1, (0,6), side1) - alpha_over(img, side2, (12,6), side2) - return img + return self.build_block_from_model('fire_floor0') + else: + return self.build_block_from_model('soul_fire_floor0') # monster spawner transparentmodelblock(blockid=52, name="spawner") @@ -2805,44 +2686,12 @@ def wire(self, blockid, data): return img +# mineral overlay # diamond ore solidmodelblock(blockid=56, name="diamond_ore") # diamond block solidmodelblock(blockid=57, name="diamond_block") -# Table blocks with no facing or other properties where sides are not all the same -# Includes: Crafting table, fletching table, cartography table, smithing table -@material(blockid=[58, 11359, 11360, 11361], solid=True) -def block_table(self, blockid, data): - block_name = {58: "crafting_table", - 11359: "fletching_table", - 11360: "cartography_table", - 11361: "smithing_table"}[blockid] - - # Top texture doesn't vary with self.rotation, but texture rotation does - top_tex = block_name + "_top" - top_rot = [0, 270, 180, 90][self.rotation] - - # List of side textures from side 1 to 4 for each blockid - side_tex_map = {58: ["front", "side", "front", "side"], - 11359: ["front", "side", "side", "front"], - 11360: ["side3", "side3", "side2", "side1"], - 11361: ["front", "side", "side", "front"]}[blockid] - # Determine which side textures to use - side3_id = [2, 3, 1, 0][self.rotation] - side4_id = [3, 1, 0, 2][self.rotation] - side3_tex = block_name + "_" + side_tex_map[side3_id] - side4_tex = block_name + "_" + side_tex_map[side4_id] - - tex_path = "assets/minecraft/textures/block" - top = self.load_image_texture("{}/{}.png".format(tex_path, top_tex)).copy() - side3 = self.load_image_texture("{}/{}.png".format(tex_path, side3_tex)) - side4 = self.load_image_texture("{}/{}.png".format(tex_path, side4_tex)).copy() - top = top.rotate(top_rot) - side4 = side4.transpose(Image.FLIP_LEFT_RIGHT) - - return self.build_full_block(top, None, None, side3, side4, None) - @material(blockid=11366, data=list(range(8)), transparent=True, solid=True, nospawn=True) def lectern(self, blockid, data): @@ -3216,7 +3065,7 @@ def signpost(self, blockid, data): # wooden and iron door # uses pseudo-ancildata found in iterate.c -@material(blockid=[64,71,193,194,195,196,197, 499, 500], data=list(range(32)), transparent=True) +@material(blockid=[64,71,193,194,195,196,197,457, 499, 500], data=list(range(32)), transparent=True) def door(self, blockid, data): #Masked to not clobber block top/bottom & swung info if self.rotation == 1: @@ -3250,6 +3099,8 @@ def door(self, blockid, data): raw_door = self.load_image_texture("assets/minecraft/textures/block/acacia_door_top.png") elif blockid == 197: # dark_oak door raw_door = self.load_image_texture("assets/minecraft/textures/block/dark_oak_door_top.png") + elif blockid == 457: # mangrove door + raw_door = self.load_image_texture("assets/minecraft/textures/block/mangrove_door_top.png") elif blockid == 499: # crimson door raw_door = self.load_image_texture("assets/minecraft/textures/block/crimson_door_top.png") elif blockid == 500: # warped door @@ -3269,6 +3120,8 @@ def door(self, blockid, data): raw_door = self.load_image_texture("assets/minecraft/textures/block/acacia_door_bottom.png") elif blockid == 197: # dark_oak door raw_door = self.load_image_texture("assets/minecraft/textures/block/dark_oak_door_bottom.png") + elif blockid == 457: # mangrove door + raw_door = self.load_image_texture("assets/minecraft/textures/block/mangrove_door_bottom.png") elif blockid == 499: # crimson door raw_door = self.load_image_texture("assets/minecraft/textures/block/crimson_door_bottom.png") elif blockid == 500: # warped door @@ -3416,7 +3269,7 @@ def ladder(self, blockid, data): # wall signs -@material(blockid=[68,11407,11408,11409,11410,11411,11412,12507,12508], data=[2, 3, 4, 5], transparent=True) +@material(blockid=[68,454,11407,11408,11409,11410,11411,11412,12507,12508], data=[2, 3, 4, 5], transparent=True) def wall_sign(self, blockid, data): # wall sign # first rotations @@ -3438,6 +3291,7 @@ def wall_sign(self, blockid, data): # wall sign sign_texture = { 68: "oak_planks.png", + 454: "mangrove_planks.png", 11407: "oak_planks.png", 11408: "spruce_planks.png", 11409: "birch_planks.png", @@ -3628,7 +3482,7 @@ def levers(self, blockid, data): return img # wooden and stone pressure plates, and weighted pressure plates -@material(blockid=[70, 72,147,148,11301,11302,11303,11304,11305, 1033,11517,11518], data=[0,1], transparent=True) +@material(blockid=[70, 72,147,148,1127,11301,11302,11303,11304,11305, 1033,11517,11518], data=[0,1], transparent=True) def pressure_plate(self, blockid, data): texture_name = {70:"assets/minecraft/textures/block/stone.png", # stone 72:"assets/minecraft/textures/block/oak_planks.png", # oak @@ -3641,7 +3495,8 @@ def pressure_plate(self, blockid, data): 11518:"assets/minecraft/textures/block/warped_planks.png", # warped 147:"assets/minecraft/textures/block/gold_block.png", # light golden 148:"assets/minecraft/textures/block/iron_block.png", # heavy iron - 1033:"assets/minecraft/textures/block/polished_blackstone.png" + 1033:"assets/minecraft/textures/block/polished_blackstone.png", + 1127:"assets/minecraft/textures/block/mangrove_planks.png" }[blockid] t = self.load_image_texture(texture_name).copy() @@ -3668,11 +3523,12 @@ def pressure_plate(self, blockid, data): return img +# mineral overlay # normal and glowing redstone ore -solidmodelblock(blockid=[73, 74], name="redstone_ore") +solidmodelblock(blockid=[73], name="redstone_ore") # stone and wood buttons -@material(blockid=(77,143,11326,11327,11328,11329,11330,1034,11515,11516), data=list(range(16)), transparent=True) +@material(blockid=(77,143,1128,11326,11327,11328,11329,11330,1034,11515,11516), data=list(range(16)), transparent=True) def buttons(self, blockid, data): # 0x8 is set if the button is pressed mask this info and render @@ -3701,6 +3557,7 @@ def buttons(self, blockid, data): texturepath = {77:"assets/minecraft/textures/block/stone.png", 143:"assets/minecraft/textures/block/oak_planks.png", + 1128:"assets/minecraft/textures/block/mangrove_planks.png", 11326:"assets/minecraft/textures/block/spruce_planks.png", 11327:"assets/minecraft/textures/block/birch_planks.png", 11328:"assets/minecraft/textures/block/jungle_planks.png", @@ -3880,9 +3737,6 @@ def snow(self, blockid, data): return img -# snow block -solidmodelblock(blockid=80, name="snow_block") - # cactus @material(blockid=81, data=list(range(15)), transparent=True, solid=True, nospawn=True) def cactus(self, blockid, data): @@ -3908,19 +3762,14 @@ def cactus(self, blockid, data): return img -# clay block -solidmodelblock(blockid=82, name="clay") - # sugar cane @material(blockid=83, data=list(range(16)), transparent=True) def sugar_cane(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/sugar_cane.png") return self.build_sprite(tex) -solidmodelblock(blockid=84, name="jukebox") - # nether and normal fences -@material(blockid=[85, 188, 189, 190, 191, 192, 113, 511, 512], data=list(range(16)), transparent=True, nospawn=True) +@material(blockid=[85, 188, 189, 190, 191, 192, 113, 456, 511, 512], data=list(range(16)), transparent=True, nospawn=True) def fence(self, blockid, data): # create needed images for Big stick fence if blockid == 85: # normal fence @@ -3947,6 +3796,10 @@ def fence(self, blockid, data): fence_top = self.load_image_texture("assets/minecraft/textures/block/acacia_planks.png").copy() fence_side = self.load_image_texture("assets/minecraft/textures/block/acacia_planks.png").copy() fence_small_side = self.load_image_texture("assets/minecraft/textures/block/acacia_planks.png").copy() + elif blockid == 456: # mangrove_fence + fence_top = self.load_image_texture("assets/minecraft/textures/block/mangrove_planks.png").copy() + fence_side = self.load_image_texture("assets/minecraft/textures/block/mangrove_planks.png").copy() + fence_small_side = self.load_image_texture("assets/minecraft/textures/block/mangrove_planks.png").copy() elif blockid == 511: # crimson_fence fence_top = self.load_image_texture("assets/minecraft/textures/block/crimson_planks.png").copy() fence_side = self.load_image_texture("assets/minecraft/textures/block/crimson_planks.png").copy() @@ -4052,8 +3905,6 @@ def draw_west(): return img -solidmodelblock(blockid=86, name='pumpkin') - @material(blockid=91, data=list(range(4)), solid=True) def jack_o_lantern(self, blockid, data): # normalize data so it can be used by a generic method @@ -4068,14 +3919,11 @@ def carved_pumpkin(self, blockid, data): blockstate['facing'] = {0:'south', 1:'west', 2:'north', 3:'east'}[data] return self.build_block_from_model('carved_pumpkin', blockstate) +# nether roof # netherrack solidmodelblock(blockid=87, name="netherrack") # soul sand solidmodelblock(blockid=88, name="soul_sand") -# glowstone -solidmodelblock(blockid=89, name="glowstone") -# shroomlight -solidmodelblock(blockid=1011, name="shroomlight") # portal @material(blockid=90, data=[1, 2, 4, 5, 8, 10], transparent=True) @@ -4437,7 +4285,7 @@ def build_torch(active): # trapdoor # the trapdoor is looks like a sprite when opened, that's not good -@material(blockid=[96,167,11332,11333,11334,11335,11336,12501,12502], data=list(range(16)), transparent=True, nospawn=True) +@material(blockid=[96,167,451,11332,11333,11334,11335,11336,12501,12502], data=list(range(16)), transparent=True, nospawn=True) def trapdoor(self, blockid, data): # rotation @@ -4461,6 +4309,7 @@ def trapdoor(self, blockid, data): # texture generation texturepath = {96:"assets/minecraft/textures/block/oak_trapdoor.png", 167:"assets/minecraft/textures/block/iron_trapdoor.png", + 451:"assets/minecraft/textures/block/mangrove_trapdoor.png", 11332:"assets/minecraft/textures/block/spruce_trapdoor.png", 11333:"assets/minecraft/textures/block/birch_trapdoor.png", 11334:"assets/minecraft/textures/block/jungle_trapdoor.png", @@ -4495,32 +4344,27 @@ def trapdoor(self, blockid, data): return img # block with hidden silverfish (stone, cobblestone and stone brick) -@material(blockid=97, data=list(range(3)), solid=True) +@material(blockid=[4, 97, 98], data=list(range(3)), solid=True) def hidden_silverfish(self, blockid, data): - if data == 0: # stone - return self.build_block_from_model("stone") - elif data == 1: # cobblestone + if blockid == 4: return self.build_block_from_model("cobblestone") - elif data == 2: # stone brick - return self.build_block_from_model("stone_bricks") - - raise Exception('unknown hidden silverfish block: ' + str(data)) - -# stone brick -@material(blockid=98, data=list(range(4)), solid=True) -def stone_brick(self, blockid, data): - if data == 0: # normal - return self.build_block_from_model("stone_bricks") - elif data == 1: # mossy - return self.build_block_from_model("mossy_stone_bricks") - elif data == 2: # cracked - return self.build_block_from_model("cracked_stone_bricks") - elif data == 3: # "circle" stone brick - return self.build_block_from_model("chiseled_stone_bricks") - - raise Exception('unknown stone brick block: ' + str(data)) - -# TODO: minecraft:block/template_single_face have faces set in blockstate, and relevant textures are not available in the model json + if blockid == 97: + if data == 0: + return self.build_block_from_model("stone") + if data == 1: + return self.build_block_from_model("cobblestone") + else: + return self.build_block_from_model("stone_bricks") + if blockid == 98: + if data == 0: # normal + return self.build_block_from_model("stone_bricks") + elif data == 1: # mossy + return self.build_block_from_model("mossy_stone_bricks") + elif data == 2: # cracked + return self.build_block_from_model("cracked_stone_bricks") + elif data == 3: # "circle" stone brick + return self.build_block_from_model("chiseled_stone_bricks") + @material(blockid=[99, 100, 139], data=list(range(64)), solid=True) def huge_mushroom(self, blockid, data): # Re-arrange the bits in data based on self.rotation @@ -4620,9 +4464,6 @@ def draw_bottom_left(): return img -# melon -solidmodelblock(blockid=103, name="melon") - # pumpkin and melon stem # TODO To render it as in game needs from pseudo data and ancil data: # once fully grown the stem bends to the melon/pumpkin block, @@ -4687,7 +4528,7 @@ def vines(self, blockid, data): # fence gates -@material(blockid=[107, 183, 184, 185, 186, 187, 513, 514], data=list(range(8)), transparent=True, nospawn=True) +@material(blockid=[107, 183, 184, 185, 186, 187, 455, 513, 514], data=list(range(8)), transparent=True, nospawn=True) def fence_gate(self, blockid, data): # rotation @@ -4726,6 +4567,8 @@ def fence_gate(self, blockid, data): gate_side = self.load_image_texture("assets/minecraft/textures/block/dark_oak_planks.png").copy() elif blockid == 187: # Acacia gate_side = self.load_image_texture("assets/minecraft/textures/block/acacia_planks.png").copy() + elif blockid == 455: # Mangrove + gate_side = self.load_image_texture("assets/minecraft/textures/block/mangrove_planks.png").copy() elif blockid == 513: # Crimson gate_side = self.load_image_texture("assets/minecraft/textures/block/crimson_planks.png").copy() elif blockid == 514: # Warped @@ -4788,12 +4631,6 @@ def fence_gate(self, blockid, data): return img -# mycelium -solidmodelblock(blockid=110, name="mycelium") -# warped_nylium & crimson_nylium -solidmodelblock(blockid=1006, name="warped_nylium") -solidmodelblock(blockid=1007, name="crimson_nylium") - # lilypad # At the moment of writing this lilypads has no ancil data and their # orientation depends on their position on the map. So it uses pseudo @@ -4812,17 +4649,6 @@ def lilypad(self, blockid, data): return self.build_full_block(None, None, None, None, None, t) -# nether bricks -@material(blockid=112, data=list(range(3)), solid=True) -def nether_bricks(self, blockid, data): - if data == 0: # normal - return self.build_block_from_model('nether_bricks') - elif data == 1: # cracked - return self.build_block_from_model('cracked_nether_bricks') - elif data == 2: # chiseled - return self.build_block_from_model('chiseled_nether_bricks') - raise Exception('unexpected nether brick data: ' + str(data)) - # nether wart @material(blockid=115, data=list(range(4)), transparent=True) def nether_wart(self, blockid, data): @@ -4936,19 +4762,16 @@ def end_portal_frame(self, blockid, data): return img -# end stone -solidmodelblock(blockid=121, name="end_stone") - # dragon egg # NOTE: this isn't a block, but I think it's better than nothing transparentmodelblock(blockid=122, name="dragon_egg") -# inactive redstone lamp -solidmodelblock(blockid=123, name="redstone_lamp") - -# active redstone lamp -solidmodelblock(blockid=124, name="redstone_lamp_on") - +@material(blockid=[123], data=list(range(2)), solid=True) +def redstone_lamp(self, blockid, data): + if data == 0: # off + return self.build_block_from_model('redstone_lamp') + return self.build_block_from_model('redstone_lamp_on') + # daylight sensor. @material(blockid=[151,178], transparent=True) def daylight_sensor(self, blockid, data): @@ -5013,12 +4836,10 @@ def wooden_slabs(self, blockid, data): return self.build_slab_block(top, side, data & 8 == 8); +# mineral overlay # emerald ore solidmodelblock(blockid=129, name="emerald_ore") -# emerald block -solidmodelblock(blockid=133, name="emerald_block") - # cocoa plant @material(blockid=127, data=list(range(12)), transparent=True) def cocoa_plant(self, blockid, data): @@ -5100,10 +4921,6 @@ def cocoa_plant(self, blockid, data): return img -solidmodelblock(blockid=137, name='command_block') -solidmodelblock(blockid=210, name='repeating_command_block') -solidmodelblock(blockid=211, name='chain_command_block') - # beacon block # at the moment of writing this, it seems the beacon block doens't use # the data values @@ -5129,7 +4946,7 @@ def beacon(self, blockid, data): # cobblestone and mossy cobblestone walls, chorus plants, mossy stone brick walls # one additional bit of data value added for mossy and cobblestone -@material(blockid=[199]+list(range(1792, 1812 + 1)), data=list(range(32)), transparent=True, nospawn=True) +@material(blockid=[199]+list(range(1792, 1813 + 1)), data=list(range(32)), transparent=True, nospawn=True) def cobblestone_wall(self, blockid, data): walls_id_to_tex = { 199: "assets/minecraft/textures/block/chorus_plant.png", # chorus plants @@ -5154,6 +4971,7 @@ def cobblestone_wall(self, blockid, data): 1810: "assets/minecraft/textures/block/polished_deepslate.png", 1811: "assets/minecraft/textures/block/deepslate_bricks.png", 1812: "assets/minecraft/textures/block/deepslate_tiles.png", + 1813: "assets/minecraft/textures/block/mud_bricks.png", } t = self.load_image_texture(walls_id_to_tex[blockid]).copy() @@ -5387,26 +5205,14 @@ def anvil(self, blockid, data): return img -# block of redstone -solidmodelblock(blockid=152, name="redstone_block") - +# mineral overlay # nether quartz ore solidmodelblock(blockid=153, name="nether_quartz_ore") # block of quartz -@material(blockid=155, data=list(range(5)), solid=True) -def quartz_block(self, blockid, data): - - if data == 0: - return self.build_block_from_model('quartz_block') - elif data == 1: - return self.build_block_from_model('chiseled_quartz_block') - elif data == 2: - return self.build_block_from_model('quartz_pillar', blockstate={'axis':'y'}) - elif data == 3: - return self.build_block_from_model('quartz_pillar', blockstate={'axis':'x'}) - elif data == 4: - return self.build_block_from_model('quartz_pillar', blockstate={'axis':'z'}) +@material(blockid=155, data=list(range(3)), solid=True) +def quartz_pillar(self, blockid, data): + return self.build_block_from_model('quartz_pillar', blockstate = {'axis': ({ 0 : 'y', 1: 'x', 2 : 'z'}[data])}) # hopper @material(blockid=154, data=list(range(4)), transparent=True) @@ -5435,18 +5241,6 @@ def hopper(self, blockid, data): # slime block transparentmodelblock(blockid=165, name="slime_block") -# prismarine block -@material(blockid=168, data=list(range(3)), solid=True) -def prismarine_block(self, blockid, data): - if data == 0: # prismarine - return self.build_block_from_model("prismarine") - elif data == 1: # prismarine bricks - return self.build_block_from_model("prismarine_bricks") - elif data == 2: # dark prismarine - return self.build_block_from_model("dark_prismarine") - else: - raise Exception('unexpected prismarine data: ' + str(data)) - # sea lantern solidmodelblock(blockid=169, name="sea_lantern") @@ -5465,41 +5259,6 @@ def carpet(self, blockid, data): return self.build_full_block((texture,15),texture,texture,texture,texture) -#clay block -solidmodelblock(blockid=172, name="terracotta") - -#stained hardened clay -@material(blockid=159, data=list(range(16)), solid=True) -def stained_clay(self, blockid, data): - return self.build_block_from_model("%s_terracotta" % color_map[data]) - -#coal block -solidmodelblock(blockid=173, name="coal_block") - -# packed ice block -solidmodelblock(blockid=174, name="packed_ice") - -#blue ice -solidmodelblock(blockid=11312, name="blue_ice") - -#smooth stones -solidmodelblock(blockid=11313, name="smooth_stone") -solidmodelblock(blockid=11314, name="sandstone") -solidmodelblock(blockid=11315, name="red_sandstone") - -#coral blocks -solidmodelblock(blockid=11316, name="brain_coral_block") -solidmodelblock(blockid=11317, name="bubble_coral_block") -solidmodelblock(blockid=11318, name="fire_coral_block") -solidmodelblock(blockid=11319, name="horn_coral_block") -solidmodelblock(blockid=11320, name="tube_coral_block") - -#dead coral blocks -solidmodelblock(blockid=11321, name="dead_brain_coral_block") -solidmodelblock(blockid=11322, name="dead_bubble_coral_block") -solidmodelblock(blockid=11323, name="dead_fire_coral_block") -solidmodelblock(blockid=11324, name="dead_horn_coral_block") -solidmodelblock(blockid=11325, name="dead_tube_coral_block") @material(blockid=175, data=list(range(16)), transparent=True) def flower(self, blockid, data): @@ -5533,31 +5292,16 @@ def chorus_flower(self, blockid, data): return self.build_block(texture,texture) -# purpur block -solidmodelblock(blockid=201, name="purpur_block") - # purpur pillar @material(blockid=202, data=list(range(3)), solid=True) def purpur_pillar(self, blockid, data): return self.build_block_from_model('purpur_pillar', blockstate = {'axis': ({ 0 : 'y', 1: 'x', 2 : 'z'}[data])}) -# end brick -solidmodelblock(blockid=206, name="end_stone_bricks") - # frosted ice @material(blockid=212, data=list(range(4)), solid=True) def frosted_ice(self, blockid, data): return self.build_block_from_model("frosted_ice_%d" % data) -# magma block -solidmodelblock(blockid=213, name="magma_block") -# nether wart block -solidmodelblock(blockid=214, name="nether_wart_block") -# warped wart block -solidmodelblock(blockid=1010, name="warped_wart_block") -# red nether brick -solidmodelblock(blockid=215, name="red_nether_bricks") - @material(blockid=216, data=list(range(12)), solid=True) def boneblock(self, blockid, data): return self.build_block_from_model('bone_block', blockstate = {'axis': ({ 0 : 'y', 4: 'x', 8 : 'z'}[data & 12])}) @@ -5633,7 +5377,7 @@ def structure_block(self, blockid, data): # Jigsaw block @material(blockid=256, data=list(range(6)), solid=True) def jigsaw_block(self, blockid, data): - facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data%6] + facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data] return self.build_block_from_model('jigsaw', {'facing':facing}) @@ -5657,25 +5401,12 @@ def crops(self, blockid, data): alpha_over(img, crop3, (6,3), crop3) return img -# Concrete -@material(blockid=251, data=list(range(16)), solid=True) -def concrete(self, blockid, data): - return self.build_block_from_model("%s_concrete" % color_map[data]) - -# Concrete Powder -@material(blockid=252, data=list(range(16)), solid=True) -def concrete(self, blockid, data): - return self.build_block_from_model("%s_concrete_powder" % color_map[data]) - # Glazed Terracotta @material(blockid=list(range(235, 251)), data=list(range(4)), solid=True) def glazed_terracotta(self, blockid, data): facing = {0: 'south', 1: 'west', 2: 'north', 3: 'east'}[data] return self.build_block_from_model("%s_glazed_terracotta" % color_map[blockid - 235], {'facing':facing}) -# dried kelp block -solidmodelblock(blockid=11331, name="dried_kelp_block") - # scaffolding @material(blockid=[11414], data=list(range(2)), solid=False, transparent=True) def scaffolding(self, blockid, data): @@ -5692,14 +5423,10 @@ def beehivenest(self, blockid, data): if data >= 4: return self.build_block_from_model('beehive_honey', {'facing':facing}) return self.build_block_from_model('beehive', {'facing':facing}) - if blockid == 11502: + else: # blockid == 11502: if data >= 4: return self.build_block_from_model('bee_nest_honey', {'facing':facing}) return self.build_block_from_model('bee_nest', {'facing':facing}) - raise Exception('what') - -# honeycomb_block -solidmodelblock(blockid=11503, name="honeycomb_block") # honey_block transparentmodelblock(blockid=11504, name="honey_block") @@ -5942,6 +5669,7 @@ def create_tile(img_src, coord_crop, coord_paste, rot): return img +# nether roof # Ancient Debris solidmodelblock(blockid=[1000], name="ancient_debris") @@ -5954,6 +5682,7 @@ def basalt(self, blockid, data): if blockid == 1002: # polished_basalt return self.build_block_from_model('polished_basalt', {'axis':axis}) +# nether roof # Blackstone block solidmodelblock(blockid=[1004], name="blackstone") @@ -5998,54 +5727,33 @@ def draw_z(): def respawn_anchor(self, blockid, data): return self.build_block_from_model("respawn_anchor_%s" % data) -# Netherite -solidmodelblock(blockid=[1005], name="netherite_block") +# nether roof # soul soil solidmodelblock(blockid=1020, name="soul_soil") # nether gold ore solidmodelblock(blockid=1021, name="nether_gold_ore") -# Solid Nether stone blocks -solidmodelblock(blockid=1022, name="polished_blackstone") -solidmodelblock(blockid=1023, name="chiseled_polished_blackstone") -solidmodelblock(blockid=1024, name="gilded_blackstone") -solidmodelblock(blockid=1025, name="cracked_polished_blackstone_bricks") -solidmodelblock(blockid=1026, name="polished_blackstone_bricks") - -solidmodelblock(blockid=1035, name="crying_obsidian") -solidmodelblock(blockid=1036, name="lodestone") -solidmodelblock(blockid=1041, name="quartz_bricks") - -solidmodelblock(blockid=1042, name="amethyst_block") -solidmodelblock(blockid=1043, name="raw_iron_block") -solidmodelblock(blockid=1044, name="raw_gold_block") + solidmodelblock(blockid=1045, name="budding_amethyst") -# You have entered the COPPER ZONE -solidmodelblock(blockid=[1046, 1050], name="copper_block") -solidmodelblock(blockid=[1047, 1051], name="exposed_copper") -solidmodelblock(blockid=[1048, 1052], name="weathered_copper") -solidmodelblock(blockid=[1049, 1053], name="oxidized_copper") +# waxed copper +solidmodelblock(blockid=[1050], name="copper_block") +solidmodelblock(blockid=[1051], name="exposed_copper") +solidmodelblock(blockid=[1052], name="weathered_copper") +solidmodelblock(blockid=[1053], name="oxidized_copper") # Cut variant -solidmodelblock(blockid=[1054, 1058], name="cut_copper") -solidmodelblock(blockid=[1055, 1059], name="exposed_cut_copper") -solidmodelblock(blockid=[1056, 1060], name="weathered_cut_copper") -solidmodelblock(blockid=[1057, 1061], name="oxidized_cut_copper") +solidmodelblock(blockid=[1058], name="cut_copper") +solidmodelblock(blockid=[1059], name="exposed_cut_copper") +solidmodelblock(blockid=[1060], name="weathered_cut_copper") +solidmodelblock(blockid=[1061], name="oxidized_cut_copper") -solidmodelblock(blockid=1062, name="raw_copper_block") solidmodelblock(blockid=1063, name="copper_ore") -# You are now leaving the COPPER ZONE - -solidmodelblock(blockid=1080, name="moss_block") -solidmodelblock(blockid=1081, name="calcite") -solidmodelblock(blockid=1082, name="rooted_dirt") # deepslate @material(blockid=1083, data=list(range(3)), solid=True) def deepslate(self, blockid, data): return self.build_block_from_model('deepslate', {'axis': { 0 : 'y', 1: 'x', 2 : 'z'}[data]}) -solidmodelblock(blockid=1084, name="cobbled_deepslate") -solidmodelblock(blockid=1085, name="polished_deepslate") +# mineral overlay solidmodelblock(blockid=1086, name="deepslate_coal_ore") solidmodelblock(blockid=1087, name="deepslate_iron_ore") solidmodelblock(blockid=1088, name="deepslate_copper_ore") @@ -6054,15 +5762,6 @@ def deepslate(self, blockid, data): solidmodelblock(blockid=1091, name="deepslate_lapis_ore") solidmodelblock(blockid=1092, name="deepslate_diamond_ore") solidmodelblock(blockid=1093, name="deepslate_redstone_ore") -solidmodelblock(blockid=1094, name="deepslate_bricks") -solidmodelblock(blockid=1095, name="cracked_deepslate_bricks") -solidmodelblock(blockid=1096, name="deepslate_tiles") -solidmodelblock(blockid=1097, name="cracked_deepslate_tiles") -solidmodelblock(blockid=1098, name="chiseled_deepslate") -solidmodelblock(blockid=1107, name="dripstone_block") -solidmodelblock(blockid=1108, name="smooth_basalt") -solidmodelblock(blockid=1109, name="tuff") - @material(blockid=1110, data=list(range(16)), transparent=True) def pointed_dripstone(self, blockid, data): @@ -6079,8 +5778,6 @@ def pointed_dripstone(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/pointed_dripstone_%s_tip.png" % (up_down)) return self.build_sprite(tex) -solidmodelblock(blockid=1111, name="powder_snow") - @material(blockid=1112, data=0, transparent=True) def hangings_roots(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/hanging_roots.png") @@ -6362,8 +6059,8 @@ def spore_blossom(self, blockid, data): alpha_over(img, base_top, (0, 0), base_top) return img -solidmodelblock(blockid=1121, name="mud") -solidmodelblock(blockid=1122, name="packed_mud") -solidmodelblock(blockid=1123, name="mud_bricks") -solidmodelblock(blockid=1125, name="mangrove_roots") -solidmodelblock(blockid=1127, name="muddy_mangrove_roots") +transparentmodelblock(blockid=1125, name="mangrove_roots") + +# Render all blocks not explicitly declared before +# Must run last to prevent being hidden by blocks with fixed IDs +unbound_models() \ No newline at end of file diff --git a/overviewer_core/world.py b/overviewer_core/world.py index c3cfef1e9..ed16045ae 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -302,34 +302,12 @@ def __init__(self, regiondir, rel): 'minecraft:air': (0, 0), 'minecraft:cave_air': (0, 0), 'minecraft:void_air': (0, 0), - 'minecraft:stone': (1, 0), - 'minecraft:granite': (1, 1), - 'minecraft:polished_granite': (1, 2), - 'minecraft:diorite': (1, 3), - 'minecraft:polished_diorite': (1, 4), - 'minecraft:andesite': (1, 5), - 'minecraft:polished_andesite': (1, 6), 'minecraft:grass_block': (2, 0), - 'minecraft:dirt': (3, 0), - 'minecraft:coarse_dirt': (3, 1), - 'minecraft:podzol': (3, 2), - 'minecraft:cobblestone': (4, 0), 'minecraft:infested_cobblestone': (4, 0), - 'minecraft:oak_planks': (5, 0), - 'minecraft:spruce_planks': (5, 1), - 'minecraft:birch_planks': (5, 2), - 'minecraft:jungle_planks': (5, 3), - 'minecraft:acacia_planks': (5, 4), - 'minecraft:dark_oak_planks': (5, 5), - 'minecraft:crimson_planks': (5, 6), - 'minecraft:warped_planks': (5, 7), 'minecraft:sapling': (6, 0), 'minecraft:bedrock': (7, 0), 'minecraft:water': (8, 0), 'minecraft:lava': (11, 0), - 'minecraft:sand': (12, 0), - 'minecraft:red_sand': (12, 1), - 'minecraft:gravel': (13, 0), 'minecraft:gold_ore': (14, 0), 'minecraft:iron_ore': (15, 0), 'minecraft:coal_ore': (16, 0), @@ -352,10 +330,6 @@ def __init__(self, regiondir, rel): 'minecraft:lapis_ore': (21, 0), 'minecraft:lapis_block': (22, 0), 'minecraft:dispenser': (23, 0), - 'minecraft:sandstone': (24, 0), - 'minecraft:chiseled_sandstone': (24, 1), - 'minecraft:cut_sandstone': (24, 2), - 'minecraft:note_block': (25, 0), 'minecraft:powered_rail': (27, 0), 'minecraft:detector_rail': (28, 0), 'minecraft:sticky_piston': (29, 0), @@ -365,22 +339,6 @@ def __init__(self, regiondir, rel): 'minecraft:fern': (31, 2), 'minecraft:piston': (33, 0), 'minecraft:piston_head': (34, 0), - 'minecraft:white_wool': (35, 0), - 'minecraft:orange_wool': (35, 1), - 'minecraft:magenta_wool': (35, 2), - 'minecraft:light_blue_wool': (35, 3), - 'minecraft:yellow_wool': (35, 4), - 'minecraft:lime_wool': (35, 5), - 'minecraft:pink_wool': (35, 6), - 'minecraft:gray_wool': (35, 7), - 'minecraft:light_gray_wool': (35, 8), - 'minecraft:cyan_wool': (35, 9), - 'minecraft:purple_wool': (35, 10), - 'minecraft:blue_wool': (35, 11), - 'minecraft:brown_wool': (35, 12), - 'minecraft:green_wool': (35, 13), - 'minecraft:red_wool': (35, 14), - 'minecraft:black_wool': (35, 15), # Flowers 'minecraft:poppy': (38, 0), 'minecraft:blue_orchid': (38, 1), @@ -408,11 +366,8 @@ def __init__(self, regiondir, rel): 'minecraft:stone_brick_slab': (44, 5), 'minecraft:nether_brick_slab': (44, 6), 'minecraft:quartz_slab': (44, 7), - 'minecraft:bricks': (45, 0), 'minecraft:tnt': (46, 0), - 'minecraft:bookshelf': (47, 0), 'minecraft:mossy_cobblestone': (48, 0), - 'minecraft:obsidian': (49, 0), 'minecraft:wall_torch': (50, 0), 'minecraft:torch': (50, 5), 'minecraft:fire': (51, 0), @@ -424,7 +379,6 @@ def __init__(self, regiondir, rel): 'minecraft:redstone_wire': (55, 0), 'minecraft:diamond_ore': (56, 0), 'minecraft:diamond_block': (57, 0), - 'minecraft:crafting_table': (58, 0), 'minecraft:wheat': (59, 0), 'minecraft:farmland': (60, 0), 'minecraft:furnace': (61, 0), @@ -443,6 +397,7 @@ def __init__(self, regiondir, rel): 'minecraft:cobblestone_stairs': (67, 0), 'minecraft:wall_sign': (68, 0), 'minecraft:oak_wall_sign': (11407, 0), + 'minecraft:mangrove_wall_sign': (454, 0), 'minecraft:spruce_wall_sign': (11408, 0), 'minecraft:birch_wall_sign': (11409, 0), 'minecraft:jungle_wall_sign': (11410, 0), @@ -460,35 +415,25 @@ def __init__(self, regiondir, rel): 'minecraft:stone_button': (77, 0), 'minecraft:snow': (78, 0), 'minecraft:ice': (79, 0), - 'minecraft:snow_block': (80, 0), 'minecraft:cactus': (81, 0), - 'minecraft:clay': (82, 0), 'minecraft:sugar_cane': (83, 0), - 'minecraft:jukebox': (84, 0), 'minecraft:oak_fence': (85, 0), - 'minecraft:pumpkin': (86, 0), 'minecraft:netherrack': (87, 0), 'minecraft:soul_sand': (88, 0), - 'minecraft:glowstone': (89, 0), 'minecraft:nether_portal': (90, 0), 'minecraft:jack_o_lantern': (91, 0), 'minecraft:cake': (92, 0), 'minecraft:repeater': (93,0), 'minecraft:oak_trapdoor': (96, 0), 'minecraft:infested_stone': (97, 0), - 'minecraft:stone_bricks': (98, 0), 'minecraft:infested_stone_bricks': (98, 0), - 'minecraft:mossy_stone_bricks': (98, 1), 'minecraft:infested_mossy_stone_bricks': (98, 1), - 'minecraft:cracked_stone_bricks': (98, 2), 'minecraft:infested_cracked_stone_bricks': (98, 2), - 'minecraft:chiseled_stone_bricks': (98, 3), 'minecraft:infested_chiseled_stone_bricks': (98, 3), 'minecraft:brown_mushroom_block': (99, 0), 'minecraft:red_mushroom_block': (100, 0), 'minecraft:iron_bars': (101, 0), 'minecraft:glass_pane': (102, 0), - 'minecraft:melon': (103,0), 'minecraft:attached_pumpkin_stem': (104, 0), 'minecraft:attached_melon_stem': (104, 0), 'minecraft:pumpkin_stem': (105, 0), @@ -497,11 +442,7 @@ def __init__(self, regiondir, rel): 'minecraft:oak_fence_gate': (107, 0), 'minecraft:brick_stairs': (108, 0), 'minecraft:stone_brick_stairs': (109, 0), - 'minecraft:mycelium': (110, 0), 'minecraft:lily_pad': (111, 0), - 'minecraft:nether_bricks': (112, 0), - 'minecraft:cracked_nether_bricks': (112, 1), - 'minecraft:chiseled_nether_bricks': (112, 2), 'minecraft:nether_brick_fence': (113, 0), 'minecraft:nether_brick_stairs': (114, 0), 'minecraft:nether_wart': (115, 0), @@ -513,7 +454,6 @@ def __init__(self, regiondir, rel): 'minecraft:powder_snow_cauldron': (118, 3 << 2), 'minecraft:end_portal': (119, 0), 'minecraft:end_portal_frame': (120, 0), - 'minecraft:end_stone': (121, 0), 'minecraft:dragon_egg': (122, 0), 'minecraft:redstone_lamp': (123, 0), 'minecraft:oak_slab': (126, 0), @@ -530,11 +470,9 @@ def __init__(self, regiondir, rel): 'minecraft:ender_chest': (130, 0), 'minecraft:tripwire': (131, 0), 'minecraft:tripwire_hook': (132, 0), - 'minecraft:emerald_block': (133, 0), 'minecraft:spruce_stairs': (134, 0), 'minecraft:birch_stairs': (135, 0), 'minecraft:jungle_stairs': (136, 0), - 'minecraft:command_block': (137, 0), 'minecraft:beacon': (138, 0), 'minecraft:mushroom_stem': (139, 0), 'minecraft:flower_pot': (140, 0), @@ -576,41 +514,19 @@ def __init__(self, regiondir, rel): 'minecraft:heavy_weighted_pressure_plate': (148, 0), 'minecraft:comparator': (149, 0), 'minecraft:daylight_detector': (151, 0), - 'minecraft:redstone_block': (152, 0), 'minecraft:nether_quartz_ore': (153, 0), 'minecraft:hopper': (154, 0), - 'minecraft:quartz_block': (155, 0), 'minecraft:smooth_quartz': (155, 0), # Only bottom texture is different 'minecraft:quartz_pillar': (155, 2), - 'minecraft:chiseled_quartz_block': (155, 1), 'minecraft:quartz_stairs': (156, 0), 'minecraft:activator_rail': (157, 0), 'minecraft:dropper': (158, 0), - 'minecraft:white_terracotta': (159, 0), - 'minecraft:orange_terracotta': (159, 1), - 'minecraft:magenta_terracotta': (159, 2), - 'minecraft:light_blue_terracotta': (159, 3), - 'minecraft:yellow_terracotta': (159, 4), - 'minecraft:lime_terracotta': (159, 5), - 'minecraft:pink_terracotta': (159, 6), - 'minecraft:gray_terracotta': (159, 7), - 'minecraft:light_gray_terracotta': (159, 8), - 'minecraft:cyan_terracotta': (159, 9), - 'minecraft:purple_terracotta': (159, 10), - 'minecraft:blue_terracotta': (159, 11), - 'minecraft:brown_terracotta': (159, 12), - 'minecraft:green_terracotta': (159, 13), - 'minecraft:red_terracotta': (159, 14), - 'minecraft:black_terracotta': (159, 15), 'minecraft:acacia_log': (162, 0), 'minecraft:dark_oak_log': (162, 1), 'minecraft:acacia_stairs': (163, 0), 'minecraft:dark_oak_stairs': (164, 0), 'minecraft:slime_block': (165,0), 'minecraft:iron_trapdoor': (167, 0), - 'minecraft:prismarine': (168, 0), - 'minecraft:dark_prismarine': (168, 2), - 'minecraft:prismarine_bricks': (168, 1), 'minecraft:sea_lantern': (169, 0), 'minecraft:hay_block': (170, 0), 'minecraft:white_carpet': (171, 0), @@ -630,9 +546,6 @@ def __init__(self, regiondir, rel): 'minecraft:red_carpet': (171, 14), 'minecraft:black_carpet': (171, 15), 'minecraft:moss_carpet': (171, 16), - 'minecraft:terracotta': (172, 0), - 'minecraft:coal_block': (173, 0), - 'minecraft:packed_ice': (174, 0), 'minecraft:sunflower': (175, 0), 'minecraft:lilac': (175, 1), 'minecraft:tall_grass': (175, 2), @@ -641,9 +554,6 @@ def __init__(self, regiondir, rel): 'minecraft:peony': (175, 5), 'minecraft:standing_banner': (176, 0), 'minecraft:wall_banner': (177, 0), - 'minecraft:red_sandstone': (179, 0), - 'minecraft:chiseled_red_sandstone': (179, 1), - 'minecraft:cut_red_sandstone': (179, 2), 'minecraft:red_sandstone_stairs': (180, 0), 'minecraft:red_sandstone_slab': (182,0), 'minecraft:spruce_fence_gate': (183, 0), @@ -653,6 +563,8 @@ def __init__(self, regiondir, rel): 'minecraft:acacia_fence_gate': (187, 0), 'minecraft:crimson_fence_gate': (513, 0), 'minecraft:warped_fence_gate': (514, 0), + 'minecraft:mangrove_fence_gate': (455, 0), + 'minecraft:mangrove_fence': (456, 0), 'minecraft:spruce_fence': (188, 0), 'minecraft:birch_fence': (189, 0), 'minecraft:jungle_fence': (190, 0), @@ -665,25 +577,21 @@ def __init__(self, regiondir, rel): 'minecraft:jungle_door': (195, 0), 'minecraft:acacia_door': (196, 0), 'minecraft:dark_oak_door': (197, 0), + 'minecraft:mangrove_door': (457, 0), 'minecraft:crimson_door': (499, 0), 'minecraft:warped_door': (500, 0), + 'minecraft:end_gateway': (209, 0), + 'minecraft:end_rod': (198, 0), 'minecraft:chorus_plant': (199, 0), 'minecraft:chorus_flower': (200, 0), - 'minecraft:purpur_block': (201, 0), 'minecraft:purpur_pillar': (202, 0), 'minecraft:purpur_stairs': (203, 0), 'minecraft:purpur_slab': (205, 0), - 'minecraft:end_stone_bricks': (206, 0), 'minecraft:beetroots': (207, 0), 'minecraft:dirt_path': (208, 0), 'minecraft:grass_path': (208, 0), # compatibility - 'minecraft:repeating_command_block': (210, 0), - 'minecraft:chain_command_block': (211, 0), 'minecraft:frosted_ice': (212, 0), - 'minecraft:magma_block': (213, 0), - 'minecraft:nether_wart_block': (214, 0), - 'minecraft:red_nether_bricks': (215, 0), 'minecraft:bone_block': (216, 0), 'minecraft:observer': (218, 0), @@ -723,9 +631,6 @@ def __init__(self, regiondir, rel): 'minecraft:polished_basalt': (1002, 0), 'minecraft:soul_campfire': (1003, 0), 'minecraft:blackstone': (1004, 0), - 'minecraft:netherite_block': (1005, 0), - 'minecraft:warped_nylium': (1006, 0), - 'minecraft:crimson_nylium': (1007, 0), # Nether logs aka stem 'minecraft:warped_stem': (1008, 0), 'minecraft:stripped_warped_stem': (1008, 1), @@ -737,8 +642,6 @@ def __init__(self, regiondir, rel): 'minecraft:crimson_hyphae': (1009, 2), 'minecraft:stripped_crimson_hyphae': (1009, 3), # nether biomes - 'minecraft:warped_wart_block': (1010, 0), - 'minecraft:shroomlight': (1011, 0), 'minecraft:twisting_vines': (1012, 0), 'minecraft:twisting_vines_plant': (1013, 0), 'minecraft:weeping_vines': (1014, 0), @@ -749,12 +652,6 @@ def __init__(self, regiondir, rel): 'minecraft:crimson_roots': (1019, 0), 'minecraft:soul_soil': (1020, 0), 'minecraft:nether_gold_ore': (1021, 0), - # Solid Nether stone blocks - 'minecraft:polished_blackstone': (1022, 0), - 'minecraft:chiseled_polished_blackstone': (1023, 0), - 'minecraft:gilded_blackstone': (1024, 0), - 'minecraft:cracked_polished_blackstone_bricks': (1025, 0), - 'minecraft:polished_blackstone_bricks': (1026, 0), # Nether slabs 'minecraft:blackstone_slab': (1027, 0), 'minecraft:polished_blackstone_slab': (1028, 0), @@ -767,39 +664,23 @@ def __init__(self, regiondir, rel): 'minecraft:polished_blackstone_pressure_plate': (1033, 0), 'minecraft:polished_blackstone_button': (1034, 0), # advanced nether blocks - 'minecraft:crying_obsidian': (1035, 0), - 'minecraft:lodestone': (1036, 0), 'minecraft:respawn_anchor': (1037, 0), # soul lightning 'minecraft:soul_lantern': (1038, 0), 'minecraft:soul_wall_torch': (1039, 0), 'minecraft:soul_torch': (1039, 5), 'minecraft:soul_fire': (1040, 0), - # quartz bricks - 'minecraft:quartz_bricks': (1041, 0), # 1.17 blocks go here - 'minecraft:amethyst_block': (1042, 0), - 'minecraft:raw_iron_block': (1043, 0), - 'minecraft:raw_gold_block': (1044, 0), 'minecraft:budding_amethyst': (1045, 0), - 'minecraft:copper_block': (1046, 0), - 'minecraft:exposed_copper': (1047, 0), - 'minecraft:weathered_copper': (1048, 0), - 'minecraft:oxidized_copper': (1049, 0), 'minecraft:waxed_copper_block': (1050, 0), 'minecraft:waxed_exposed_copper': (1051, 0), 'minecraft:waxed_weathered_copper': (1052, 0), 'minecraft:waxed_oxidized_copper': (1053, 0), - 'minecraft:cut_copper': (1054, 0), - 'minecraft:exposed_cut_copper': (1055, 0), - 'minecraft:weathered_cut_copper': (1056, 0), - 'minecraft:oxidized_cut_copper': (1057, 0), 'minecraft:waxed_cut_copper': (1058, 0), 'minecraft:waxed_exposed_cut_copper': (1059, 0), 'minecraft:waxed_weathered_cut_copper': (1060, 0), 'minecraft:waxed_oxidized_cut_copper': (1061, 0), - 'minecraft:raw_copper_block': (1062, 0), 'minecraft:copper_ore': (1063, 0), 'minecraft:cut_copper_stairs': (1064, 0), 'minecraft:exposed_cut_copper_stairs': (1065, 0), @@ -817,13 +698,8 @@ def __init__(self, regiondir, rel): 'minecraft:waxed_exposed_cut_copper_slab': (1077, 0), 'minecraft:waxed_weathered_cut_copper_slab': (1078, 0), 'minecraft:waxed_oxidized_cut_copper_slab': (1079, 0), - 'minecraft:moss_block': (1080, 0), - 'minecraft:calcite': (1081, 0), - 'minecraft:rooted_dirt': (1082, 0), 'minecraft:deepslate': (1083, 0), 'minecraft:infested_deepslate': (1083, 0), - 'minecraft:cobbled_deepslate': (1084, 0), - 'minecraft:polished_deepslate': (1085, 0), 'minecraft:deepslate_coal_ore': (1086, 0), 'minecraft:deepslate_iron_ore': (1087, 0), 'minecraft:deepslate_copper_ore': (1088, 0), @@ -832,11 +708,6 @@ def __init__(self, regiondir, rel): 'minecraft:deepslate_lapis_ore': (1091, 0), 'minecraft:deepslate_diamond_ore': (1092, 0), 'minecraft:deepslate_redstone_ore': (1093, 0), - 'minecraft:deepslate_bricks': (1094, 0), - 'minecraft:cracked_deepslate_bricks': (1095, 0), - 'minecraft:deepslate_tiles': (1096, 0), - 'minecraft:cracked_deepslate_tiles': (1097, 0), - 'minecraft:chiseled_deepslate': (1098, 0), 'minecraft:cobbled_deepslate_stairs': (1099, 0), 'minecraft:polished_deepslate_stairs': (1100, 0), @@ -848,12 +719,8 @@ def __init__(self, regiondir, rel): 'minecraft:deepslate_brick_slab': (1105, 0), 'minecraft:deepslate_tile_slab': (1106, 0), - 'minecraft:dripstone_block': (1107, 0), - 'minecraft:smooth_basalt': (1108, 0), - 'minecraft:tuff': (1109, 0), 'minecraft:pointed_dripstone': (1110, 0), - 'minecraft:powder_snow': (1111, 0), 'minecraft:hanging_roots': (1112, 0), 'minecraft:small_amethyst_bud': (1113, 0), 'minecraft:medium_amethyst_bud': (1114, 0), @@ -865,14 +732,10 @@ def __init__(self, regiondir, rel): 'minecraft:spore_blossom': (1120, 0), # 1.19 blocks - 'minecraft:mud': (1121, 0), - 'minecraft:packed_mud': (1122, 0), - 'minecraft:mud_bricks': (1123, 0), 'minecraft:mud_brick_slab': (1124, 0), 'minecraft:mangrove_roots': (1125, 0), 'minecraft:mangrove_log': (1126, 0), 'minecraft:stripped_mangrove_log': (1126, 1), - 'minecraft:muddy_mangrove_roots': (1127, 0), # New blocks 'minecraft:carved_pumpkin': (11300, 0), @@ -883,6 +746,7 @@ def __init__(self, regiondir, rel): 'minecraft:dark_oak_pressure_plate': (11305, 0), 'minecraft:crimson_pressure_plate': (11517, 0), 'minecraft:warped_pressure_plate': (11518, 0), + 'minecraft:mangrove_pressure_plate': (1127, 0), 'minecraft:stripped_oak_log': (11306, 0), 'minecraft:stripped_spruce_log': (11306, 1), 'minecraft:stripped_birch_log': (11306, 2), @@ -901,20 +765,6 @@ def __init__(self, regiondir, rel): 'minecraft:stripped_jungle_wood': (11310, 3), 'minecraft:stripped_acacia_wood': (11311, 0), 'minecraft:stripped_dark_oak_wood': (11311, 1), - 'minecraft:blue_ice': (11312, 0), - 'minecraft:smooth_stone': (11313, 0), - 'minecraft:smooth_sandstone': (11314, 0), - 'minecraft:smooth_red_sandstone': (11315, 0), - 'minecraft:brain_coral_block': (11316, 0), - 'minecraft:bubble_coral_block': (11317, 0), - 'minecraft:fire_coral_block': (11318, 0), - 'minecraft:horn_coral_block': (11319, 0), - 'minecraft:tube_coral_block': (11320, 0), - 'minecraft:dead_brain_coral_block': (11321, 0), - 'minecraft:dead_bubble_coral_block': (11322, 0), - 'minecraft:dead_fire_coral_block': (11323, 0), - 'minecraft:dead_horn_coral_block': (11324, 0), - 'minecraft:dead_tube_coral_block': (11325, 0), 'minecraft:spruce_button': (11326,0), 'minecraft:birch_button': (11327,0), 'minecraft:jungle_button': (11328,0), @@ -922,7 +772,8 @@ def __init__(self, regiondir, rel): 'minecraft:dark_oak_button': (11330,0), 'minecraft:crimson_button': (11515,0), 'minecraft:warped_button': (11516,0), - 'minecraft:dried_kelp_block': (11331,0), + 'minecraft:mangrove_button': (1128,0), + 'minecraft:mangrove_trapdoor': (451, 0), 'minecraft:spruce_trapdoor': (11332, 0), 'minecraft:birch_trapdoor': (11333, 0), 'minecraft:jungle_trapdoor': (11334, 0), @@ -953,9 +804,6 @@ def __init__(self, regiondir, rel): "minecraft:mossy_stone_brick_slab": (11356, 0), "minecraft:smooth_quartz_slab": (11357, 0), "minecraft:smooth_stone_slab": (11358, 0), - "minecraft:fletching_table": (11359, 0), - "minecraft:cartography_table": (11360, 0), - "minecraft:smithing_table": (11361, 0), "minecraft:blast_furnace": (11362, 0), "minecraft:smoker": (11364, 0), "minecraft:lectern": (11366, 0), @@ -992,7 +840,6 @@ def __init__(self, regiondir, rel): # 1.15 blocks below 'minecraft:beehive': (11501, 0), 'minecraft:bee_nest': (11502, 0), - 'minecraft:honeycomb_block': (11503, 0), 'minecraft:honey_block': (11504, 0), 'minecraft:sweet_berry_bush': (11505, 0), 'minecraft:campfire': (11506, 0), @@ -1020,6 +867,7 @@ def __init__(self, regiondir, rel): 'minecraft:polished_deepslate_wall': (1810, 0), 'minecraft:deepslate_brick_wall': (1811, 0), 'minecraft:deepslate_tile_wall': (1812, 0), + 'minecraft:mud_brick_wall': (1813, 0), } colors = [ 'white', 'orange', 'magenta', 'light_blue', @@ -1035,8 +883,6 @@ def __init__(self, regiondir, rel): self._blockmap['minecraft:%s_wall_banner' % colors[i]] = (177, i) # not rendering self._blockmap['minecraft:%s_shulker_box' % colors[i]] = (219 + i, 0) self._blockmap['minecraft:%s_glazed_terracotta' % colors[i]] = (235 + i, 0) - self._blockmap['minecraft:%s_concrete' % colors[i]] = (251, i) - self._blockmap['minecraft:%s_concrete_powder' % colors[i]] = (252, i) # Re-initialize upon unpickling def __getstate__(self): @@ -1135,15 +981,12 @@ def _get_block(self, palette_entry): (block, data) = self._blockmap[key] elif key in modelblocks: (block, data) = modelblocks[key] - print('found ' + str(block) + ' : ' + str(key)) else: - print(str(type(modelblocks))) - print('unknown key ' + key ) raise UnknownBlockException(key) if key in ['minecraft:redstone_ore', 'minecraft:redstone_lamp']: if palette_entry['Properties']['lit'] == 'true': - block += 1 + data = 1 elif key.endswith('gate'): facing = palette_entry['Properties']['facing'] data = {'south': 0, 'west': 1, 'north': 2, 'east': 3}[facing] @@ -1186,8 +1029,11 @@ def _get_block(self, palette_entry): elif palette_entry['Properties']['type'] == 'double': if key in wood_slabs: block = 125 # block_double_wooden_slab - else: - (block, data) = self._blockmap[slab_to_double[key]] + elif key in slab_to_double : + if slab_to_double[key] in self._blockmap: + (block, data) = self._blockmap[slab_to_double[key]] + else: + (block, data) = modelblocks[slab_to_double[key]] elif key in ['minecraft:ladder', 'minecraft:chest', 'minecraft:ender_chest', 'minecraft:trapped_chest', 'minecraft:furnace', @@ -1240,14 +1086,8 @@ def _get_block(self, palette_entry): data |= 4 elif axis == 'z': data |= 8 - elif key == 'minecraft:quartz_pillar': - axis = palette_entry['Properties']['axis'] - if axis == 'x': - data = 1 - if axis == 'z': - data = 2 elif key in ['minecraft:basalt', 'minecraft:polished_basalt', 'minecraft:chain', 'minecraft:purpur_pillar', - 'minecraft:deepslate', 'minecraft:hay_block']: + 'minecraft:deepslate', 'minecraft:hay_block', 'minecraft:quartz_pillar']: axis = palette_entry['Properties']['axis'] data = {'y': 0, 'x': 1, 'z': 2}[axis] elif key in ['minecraft:redstone_torch','minecraft:redstone_wall_torch','minecraft:wall_torch', @@ -1543,7 +1383,9 @@ def _get_blockdata_v118(self, section, longarray_unpacker): try: translated_blocks[i], translated_data[i] = self._get_block(key) except UnknownBlockException as e: - pass # We already have initialised arrays with 0 (= air) + # unrecognized blocks are usually found in 'blockstate' and need to be manually implemented for now + # inclused heads, skulls and candles + pass # Turn the BlockStates array into a 16x16x16 numpy matrix of shorts. blocks = numpy.empty((4096,), dtype=numpy.uint16) From 34081bfb8f66446f33beaacf017fedebca1523c0 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Sat, 9 Jul 2022 23:43:47 +0200 Subject: [PATCH 18/34] modiefied docs to reflect new textures.py setup --- docs/contributing.rst | 59 +++------ overviewer_core/textures.py | 239 ++++++++++++++++++++++-------------- 2 files changed, 168 insertions(+), 130 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 329c532b3..7592fff2d 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -127,10 +127,10 @@ Let's take a closer look at the ``overviewer_core/`` directory: * ``signals.py`` is multiprocessing communication code. Scary stuff. -* ``textures.py`` contains all the block definitions and how Overviewer should - render them. If you want to add a new block to the Overviewer, this is where - you'll want to do it. Additionally, this code also controls how the textures - are loaded. +* ``textures.py`` contains the custom block definitions and how Overviewer + should render them. If a block is not rendering properly in Overviewer, + this is where you'll want to fix it. Additionally, this code also controls + how the textures are loaded. * ``tileset.py`` contains code that maps a render dict entry to the output tiled image structure. @@ -138,8 +138,10 @@ Let's take a closer look at the ``overviewer_core/`` directory: * ``util.py`` contains random utility code that has no home anywhere else. * ``world.py`` is a whole lot of code that does things like choosing which - chunks to load and to cache, and general functionality revolving around the - concept of Minecraft worlds. + chunks to load and to cache, how to interpret block properties, and + general functionality revolving around the concept of Minecraft worlds. + If a block is not behaving like you expect this is probably where + you'll fix that. docs ---- @@ -184,8 +186,8 @@ Adding a Block Let's assume you want to add support for a new block to the Overviewer. This is probably one of the most common ways people start contributing to the project, -as all blocks in the Overviewer are currently hardcoded and code to handle them -needs to be added by hand. +as anything but the simplest blocks in the Overviewer are currently hardcoded +and code to handle them needs to be added by hand. The place to look here is ``textures.py``. It contains the block definitions, which are assisted by Python decorators_, which make it quite a bit simpler to @@ -202,46 +204,25 @@ as ``solid=True`` to indicate that the block is a solid block. Simple Solid 6-Sided Block ~~~~~~~~~~~~~~~~~~~~~~~~~~ -A lot of times, new blocks are basically just your standard full-height block -with a new texture. For a block this simple, we don't even really need to use -the material decorator. As an example, check out the definition of the coal -block:: +Most blocks are simple full height solid blocks. These blocks are automatically +picked up by the ``unbound_models()`` method from the minecraft assets. +Sometimes these blocks have special properties that can not be picked up +from the assets, like transparency. These blocks can be added like this:: - block(blockid=173, top_image="assets/minecraft/textures/blocks/coal_block.png") - -Block with a Different Top -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Another common theme is a block where the top is a different texture than the -sides. Here we use the ``@material`` decorator to create the jukebox block:: - - @material(blockid=84, data=range(16), solid=True) - def jukebox(self, blockid, data): - return self.build_block(self.load_image_texture("assets/minecraft/textures/blocks/jukebox_top.png"), self.load_image_texture("assets/minecraft/textures/blocks/noteblock.png")) - -As you can see, we define a method called ``jukebox``, taking the parameters -``blockid`` and ``data``, decorated by a decorator stating that the following -definition is a material with a ``blockid`` of ``84`` and a data value range -from ``0`` to ``15`` (or ``range(16)``), which we won't use as it doesn't affect -the rendering of the block. We also specify that the block is solid. - -Inside the method, we then return the return value of ``self.build_block()``, -which is a helper method that takes a texture for the top and a texture for the -side as its arguments. + transparentmodelblock(blockid=1125, name="mangrove_roots") Block with Variable Colors ~~~~~~~~~~~~~~~~~~~~~~~~~~ Occasionally, blocks can have colors stored in their data values. ``textures.py`` includes an easy mapping list, called ``color_map``, to map -between data values and Minecraft color names. Let's take stained hardened clay +between data values and Minecraft color names. Let's take carpet as an example of how this is used:: - @material(blockid=159, data=range(16), solid=True) - def stained_clay(self, blockid, data): - texture = self.load_image_texture("assets/minecraft/textures/blocks/hardened_clay_stained_%s.png" % color_map[data]) - - return self.build_block(texture,texture) + @material(blockid=171, data=list(range(17)), transparent=True) + def carpet(self, blockid, data): + if data < 16: + texture = self.load_image_texture("assets/minecraft/textures/block/%s_wool.png" % color_map[data]) As you can see, we specify that the block has 16 data values, then depending on the data value we load the right block texture by looking up the color name diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index d0979a85f..4473a97f6 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -75,6 +75,7 @@ class Textures(object): rendering. It accepts a background color, north direction, and local textures path. """ + def __init__(self, texturepath=None, bgcolor=(26, 26, 26, 0), northdirection=0): self.bgcolor = bgcolor self.rotation = northdirection @@ -107,6 +108,7 @@ def __getstate__(self): pass attributes['jars'] = OrderedDict() return attributes + def __setstate__(self, attrs): # regenerate textures, if needed for attr, val in list(attrs.items()): @@ -157,18 +159,21 @@ def generate(self): self.generated = True - #TODO: load models from resource packs, for now only client jars are used - #TODO: load blockstate before models + # TODO: load models from resource packs, for now only client jars are used + # TODO: load blockstate before models def find_models(self, verbose=False): filename = 'assets/minecraft/models/' versiondir = self.versiondir(verbose) available_versions = self.available_versions(versiondir, verbose) if not available_versions: - if verbose: logging.info("Did not find any non-snapshot minecraft jars >=1.8.0") + if verbose: + logging.info("Did not find any non-snapshot minecraft jars >=1.8.0") while(available_versions): most_recent_version = available_versions.pop(0) - if verbose: logging.info("Trying {0}. Searching it for the file...".format(".".join(str(x) for x in most_recent_version))) + if verbose: + logging.info("Trying {0}. Searching it for the file...".format( + ".".join(str(x) for x in most_recent_version))) jarname = ".".join(str(x) for x in most_recent_version) jarpath = os.path.join(versiondir, jarname, jarname + ".jar") @@ -186,7 +191,8 @@ def find_models(self, verbose=False): logging.warning("Your jar {0} is corrupted, I'll be skipping it, but you " "should probably look into that.".format(jarpath)) else: - if verbose: logging.info("Did not find file {0} in jar {1}".format(filename, jarpath)) + if verbose: + logging.info("Did not find file {0} in jar {1}".format(filename, jarpath)) continue models = [] @@ -866,12 +872,13 @@ def load_model(self, modelname): if modelname in self.models: return self.models[modelname] - fileobj = self.find_file('assets/minecraft/models/' + modelname + '.json', verbose=logging.getLogger().isEnabledFor(logging.DEBUG)) + fileobj = self.find_file('assets/minecraft/models/' + modelname + + '.json', verbose=logging.getLogger().isEnabledFor(logging.DEBUG)) self.models[modelname] = json.load(fileobj) fileobj.close() if 'parent' in self.models[modelname]: - parent = self.load_model(re.sub('.*:','',self.models[modelname]['parent'])) + parent = self.load_model(re.sub('.*:', '', self.models[modelname]['parent'])) if 'textures' in parent: self.models[modelname]['textures'].update(parent['textures']) if 'elements' in parent: @@ -881,7 +888,7 @@ def load_model(self, modelname): self.models[modelname]['elements'] = parent['elements'] del self.models[modelname]['parent'] - self.models[modelname] = self.normalize_model(modelname); + self.models[modelname] = self.normalize_model(modelname) return self.models[modelname] # fix known inconsistencies in model info @@ -915,51 +922,51 @@ def build_block_from_model(self, modelname, blockstate={}): if 'elements' not in colmodel: return None - img = Image.new("RGBA", (24,24), self.bgcolor) + img = Image.new("RGBA", (24, 24), self.bgcolor) # for each elements for elem in colmodel['elements']: try: if 'west' in elem['faces']: texture = self.draw_face('west', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (12,6), texture) + alpha_over(img, texture, (12, 6), texture) elif 'east' in elem['faces']: texture = self.draw_face('east', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0,0), texture) + alpha_over(img, texture, (0, 0), texture) if 'north' in elem['faces']: texture = self.draw_face('north', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0,6), texture) + alpha_over(img, texture, (0, 6), texture) elif 'south' in elem['faces']: texture = self.draw_face('south', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (12,0), texture) + alpha_over(img, texture, (12, 0), texture) if 'up' in elem['faces']: texture = self.draw_face('up', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0,0), texture) + alpha_over(img, texture, (0, 0), texture) elif 'down' in elem['faces']: texture = self.draw_face('down', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0,12), texture) + alpha_over(img, texture, (0, 12), texture) except KeyError: # element has an invalid texture; skipping entire element continue # Manually touch up 6 pixels that leave a gap because of how the # shearing works out. This makes the blocks perfectly tessellate-able - for x,y in [(13,23), (17,21), (21,19)]: + for x, y in [(13, 23), (17, 21), (21, 19)]: # Copy a pixel to x,y from x-1,y - img.putpixel((x,y), img.getpixel((x-1,y))) - for x,y in [(3,4), (7,2), (11,0)]: + img.putpixel((x, y), img.getpixel((x - 1, y))) + for x, y in [(3, 4), (7, 2), (11, 0)]: # Copy a pixel to x,y from x+1,y - img.putpixel((x,y), img.getpixel((x+1,y))) + img.putpixel((x, y), img.getpixel((x + 1, y))) return img def numvalue_orientation(self, orientation): - return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4,'down': 6}[orientation] + return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4, 'down': 6}[orientation] def orientation_from_numvalue(self, orientation): - return {0:'south', 1:'west', 2:'north', 3:'east', 4:'up', 6:'down'}[orientation] + return {0: 'south', 1: 'west', 2: 'north', 3: 'east', 4: 'up', 6: 'down'}[orientation] # translates rotation to real face value # facing is the blockproperty @@ -985,25 +992,28 @@ def map_facing_to_real(self, blockfacing, targetblockface): elif targetblockface == 'down': resultface = 'down' else: - resultface = self.orientation_from_numvalue((self.numvalue_orientation(targetblockface) + [0,3,2,1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2)*2) % 4) + resultface = self.orientation_from_numvalue((self.numvalue_orientation( + targetblockface) + [0, 3, 2, 1][self.numvalue_orientation(blockfacing)] + 1 + self.rotation + (self.rotation % 2) * 2) % 4) return resultface def map_axis_to_real(self, axis, textureface): match axis: case 'x': - return {'up':'north','north':'down','down':'south','south':'up','east':'east','west':'west'}[textureface] + return {'up': 'north', 'north': 'down', 'down': 'south', 'south': 'up', 'east': 'east', 'west': 'west'}[textureface] case 'z': - return {'up':'west','west':'down','down':'east','east':'up','north':'north','south':'south'}[textureface] + return {'up': 'west', 'west': 'down', 'down': 'east', 'east': 'up', 'north': 'north', 'south': 'south'}[textureface] case 'y' | _: return textureface def axis_rotation(self, axis, face, texture): match axis: case 'x': - rotation = {'up':270,'north':0,'down':0,'south':0,'east':270,'west':270}[face] + rotation = {'up': 270, 'north': 0, 'down': 0, + 'south': 0, 'east': 270, 'west': 270}[face] return texture.rotate(rotation) case 'z': - rotation = {'up':0,'west':0,'down':0,'east':0,'north':90,'south':90}[face] + rotation = {'up': 0, 'west': 0, 'down': 0, + 'east': 0, 'north': 90, 'south': 90}[face] return texture.rotate(rotation) case 'y' | _: return texture @@ -1015,12 +1025,13 @@ def draw_face(self, direction, elem, data, blockstate, modelname): if 'axis' in blockstate: textureface = self.map_axis_to_real(blockstate['axis'], direction) - texture = self.find_texture_from_model(elem['faces'][textureface]['texture'], data['textures']).copy() + texture = self.find_texture_from_model( + elem['faces'][textureface]['texture'], data['textures']).copy() if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) texture = self.transform_texture(direction, texture, blockstate, elem['faces'][textureface]) - texture = self.adjust_lighting(direction,texture) + texture = self.adjust_lighting(direction, texture) return texture @@ -1047,21 +1058,22 @@ def transform_texture(self, direction, texture, blockstate, faceinfo): case 'down' | 'up': if 'facing' in blockstate: if self.numvalue_orientation(blockstate['facing']) < 4: - rotation += [ 0, 270, 180, 90][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] + rotation += [0, 270, 180, + 90][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] else: - rotation += [180,0][({'up':0,'down':1}[blockstate['facing']])] + rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] return self.transform_image_top(texture.rotate(rotation)) case 'north' | 'south': if 'rotation' in faceinfo: - rotation = {0:180, 90:90, 180:0, 270:270}[faceinfo['rotation']] - if 'facing' in blockstate and blockstate['facing'] in {'up','down'}: - rotation += [90,90][({'up':0,'down':1}[blockstate['facing']])] + rotation = {0: 180, 90: 90, 180: 0, 270: 270}[faceinfo['rotation']] + if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: + rotation += [90, 90][({'up': 0, 'down': 1}[blockstate['facing']])] texture = self.transform_image_side(texture.rotate(rotation)) case 'west' | 'east': if 'rotation' in faceinfo: - rotation = {0:180, 90:270, 180:0, 270:90}[faceinfo['rotation']] - if 'facing' in blockstate and blockstate['facing'] in {'up','down'}: - rotation += [180,0][({'up':0,'down':1}[blockstate['facing']])] + rotation = {0: 180, 90: 270, 180: 0, 270: 90}[faceinfo['rotation']] + if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: + rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] texture = texture.transpose(Image.FLIP_LEFT_RIGHT) texture = self.transform_image_side(texture.rotate(rotation)) texture = texture.transpose(Image.FLIP_LEFT_RIGHT) @@ -1072,18 +1084,18 @@ def find_texture_from_model(self, face, textureset): if face.startswith('#'): return self.find_texture_from_model(textureset[face[1:]], textureset) else: - return self.load_image_texture("assets/minecraft/textures/" + re.sub('.*:','',face) + '.png') + return self.load_image_texture("assets/minecraft/textures/" + re.sub('.*:', '', face) + '.png') - ## TODO: deal with uv, from, to + # TODO: deal with uv, from, to def crop_to_transparancy(self, img, area): # top - ImageDraw.Draw(img).rectangle((area[2],0,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) + ImageDraw.Draw(img).rectangle((area[2], 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # right - ImageDraw.Draw(img).rectangle((0,area[3],16,16),outline=(0,0,0,0),fill=(0,0,0,0)) + ImageDraw.Draw(img).rectangle((0, area[3], 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # bottom - ImageDraw.Draw(img).rectangle((0,0,area[0],16),outline=(0,0,0,0),fill=(0,0,0,0)) + ImageDraw.Draw(img).rectangle((0, 0, area[0], 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # left - ImageDraw.Draw(img).rectangle((0,0,16,area[1]),outline=(0,0,0,0),fill=(0,0,0,0)) + ImageDraw.Draw(img).rectangle((0, 0, 16, area[1]), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) return img ## @@ -1094,7 +1106,8 @@ def crop_to_transparancy(self, img, area): # the material registration decorator def material(blockid=[], data=[0], **kwargs): # mapping from property name to the set to store them in - properties = {"transparent" : transparent_blocks, "solid" : solid_blocks, "fluid" : fluid_blocks, "nospawn" : nospawn_blocks} + properties = {"transparent": transparent_blocks, "solid": solid_blocks, + "fluid": fluid_blocks, "nospawn": nospawn_blocks} # make sure blockid and data are iterable try: @@ -1139,16 +1152,19 @@ def func_wrapper(texobj, blockid, data): return func_wrapper return inner_material + def transparentmodelblock(blockid=[], name=None, **kwargs): - new_kwargs = {'transparent' : True} + new_kwargs = {'transparent': True} new_kwargs.update(kwargs) return modelblock(blockid=blockid, name=name, **new_kwargs) + def solidmodelblock(blockid=[], name=None, **kwargs): - new_kwargs = {'solid' : True} + new_kwargs = {'solid': True} new_kwargs.update(kwargs) return modelblock(blockid=blockid, name=name, **new_kwargs) + def modelblock(blockid=[], name=None, **kwargs): if name is None: raise ValueError("block name was not provided") @@ -1184,6 +1200,7 @@ def inner_billboard(self, unused_id, unused_data): return self.build_billboard(self.load_image_texture(imagename)) return inner_billboard + def unbound_models(): global max_blockid, block_models, next_unclaimed_id @@ -1197,22 +1214,25 @@ def unbound_models(): next_unclaimed_id = 2048 id = next_unclaimed_id solidmodelblock(blockid=id, name=model) - block_models['minecraft:'+model] = (id, 0) + block_models['minecraft:' + model] = (id, 0) ## ## the texture definitions for all blocks that have special rendering conditions ## -@material(blockid=2, data=list(range(11))+[0x10,], solid=True) + +@material(blockid=2, data=list(range(11)) + [0x10, ], solid=True) def grass(self, blockid, data): if data & 0x10: return self.build_block_from_model('grass_block_snow') else: side_img = self.load_image_texture("assets/minecraft/textures/block/grass_block_side.png") - img = self.build_block(self.load_image_texture("assets/minecraft/textures/block/grass_block_top.png"), side_img) + img = self.build_block(self.load_image_texture( + "assets/minecraft/textures/block/grass_block_top.png"), side_img) alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture) return img + @material(blockid=6, data=list(range(16)), transparent=True) def saplings(self, blockid, data): # usual saplings @@ -1230,6 +1250,7 @@ def saplings(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/dark_oak_sapling.png") return self.build_sprite(tex) + sprite(blockid=11385, imagename="assets/minecraft/textures/block/oak_sapling.png") sprite(blockid=11386, imagename="assets/minecraft/textures/block/spruce_sapling.png") sprite(blockid=11387, imagename="assets/minecraft/textures/block/birch_sapling.png") @@ -1286,6 +1307,7 @@ def lava(self, blockid, data): lavatex = self.load_lava() return self.build_block(lavatex, lavatex) + # Mineral overlay blocks # gold ore solidmodelblock(blockid=14, name='gold_ore') @@ -1294,13 +1316,14 @@ def lava(self, blockid, data): # coal ore solidmodelblock(blockid=16, name='coal_ore') + @material(blockid=[17, 162, 11306, 11307, 11308, 11309, 11310, 11311, 1008, 1009, 1126], data=list(range(12)), solid=True) def wood(self, blockid, data): type = data & 3 blockstate = {} - blockstate['axis'] = { 0 : 'y', 4: 'x', 8 : 'z'}[data & 12] + blockstate['axis'] = {0: 'y', 4: 'x', 8: 'z'}[data & 12] if blockid == 17: if type == 0: @@ -1394,6 +1417,7 @@ def wood(self, blockid, data): return self.build_block_from_model('oak_log', blockstate) + @material(blockid=[18, 161], data=list(range(16)), transparent=True, solid=True) def leaves(self, blockid, data): # mask out the bits 4 and 8 @@ -1418,6 +1442,7 @@ def leaves(self, blockid, data): else: return self.build_block_from_model("mangrove_leaves") + @material(blockid=19, data=list(range(2)), solid=True) def sponge(self, blockid, data): if data == 0: @@ -1425,44 +1450,48 @@ def sponge(self, blockid, data): if data == 1: return self.build_block_from_model('wet_sponge') + # mineral overlay # lapis lazuli ore solidmodelblock(blockid=21, name="lapis_ore") # lapis lazuli block solidmodelblock(blockid=22, name="lapis_block") + @material(blockid=[23, 158], data=list(range(6)), solid=True) def dropper(self, blockid, data): facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data] if blockid == 158: - if data in {0,1}: - return self.build_block_from_model('dropper_vertical', {'facing':facing}) - return self.build_block_from_model('dropper', {'facing':facing}) + if data in {0, 1}: + return self.build_block_from_model('dropper_vertical', {'facing': facing}) + return self.build_block_from_model('dropper', {'facing': facing}) if blockid == 23: - if data in {0,1}: - return self.build_block_from_model('dispenser_vertical', {'facing':facing}) - return self.build_block_from_model('dispenser', {'facing':facing}) + if data in {0, 1}: + return self.build_block_from_model('dispenser_vertical', {'facing': facing}) + return self.build_block_from_model('dispenser', {'facing': facing}) # furnace, blast furnace, and smoker -@material(blockid=[ 61, 11362, 11364], data=list(range(14)), solid=True) + + +@material(blockid=[61, 11362, 11364], data=list(range(14)), solid=True) def furnaces(self, blockid, data): lit = data & 0b1000 == 8 oriention = data & 0b111 - facing = {0: '', 1: '', 2: 'north', 3: 'south', 4: 'west', 5: 'east', 6:'',7:''}[oriention] + facing = {0: '', 1: '', 2: 'north', 3: 'south', 4: 'west', 5: 'east', 6: '', 7: ''}[oriention] if blockid == 61: if lit: - return self.build_block_from_model('furnace_on', {'facing':facing}) - return self.build_block_from_model('furnace', {'facing':facing}) + return self.build_block_from_model('furnace_on', {'facing': facing}) + return self.build_block_from_model('furnace', {'facing': facing}) if blockid == 11362: if lit: - return self.build_block_from_model('blast_furnace_on', {'facing':facing}) - return self.build_block_from_model('blast_furnace', {'facing':facing}) + return self.build_block_from_model('blast_furnace_on', {'facing': facing}) + return self.build_block_from_model('blast_furnace', {'facing': facing}) if blockid == 11364: if lit: - return self.build_block_from_model('smoker_on', {'facing':facing}) - return self.build_block_from_model('smoker', {'facing':facing}) + return self.build_block_from_model('smoker_on', {'facing': facing}) + return self.build_block_from_model('smoker', {'facing': facing}) # Bed @material(blockid=26, data=list(range(256)), transparent=True, nospawn=True) @@ -4356,13 +4385,13 @@ def hidden_silverfish(self, blockid, data): else: return self.build_block_from_model("stone_bricks") if blockid == 98: - if data == 0: # normal + if data == 0: # normal return self.build_block_from_model("stone_bricks") - elif data == 1: # mossy + elif data == 1: # mossy return self.build_block_from_model("mossy_stone_bricks") - elif data == 2: # cracked + elif data == 2: # cracked return self.build_block_from_model("cracked_stone_bricks") - elif data == 3: # "circle" stone brick + elif data == 3: # "circle" stone brick return self.build_block_from_model("chiseled_stone_bricks") @material(blockid=[99, 100, 139], data=list(range(64)), solid=True) @@ -4766,9 +4795,10 @@ def end_portal_frame(self, blockid, data): # NOTE: this isn't a block, but I think it's better than nothing transparentmodelblock(blockid=122, name="dragon_egg") + @material(blockid=[123], data=list(range(2)), solid=True) def redstone_lamp(self, blockid, data): - if data == 0: # off + if data == 0: # off return self.build_block_from_model('redstone_lamp') return self.build_block_from_model('redstone_lamp_on') @@ -5210,9 +5240,11 @@ def anvil(self, blockid, data): solidmodelblock(blockid=153, name="nether_quartz_ore") # block of quartz + + @material(blockid=155, data=list(range(3)), solid=True) def quartz_pillar(self, blockid, data): - return self.build_block_from_model('quartz_pillar', blockstate = {'axis': ({ 0 : 'y', 1: 'x', 2 : 'z'}[data])}) + return self.build_block_from_model('quartz_pillar', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) # hopper @material(blockid=154, data=list(range(4)), transparent=True) @@ -5245,9 +5277,11 @@ def hopper(self, blockid, data): solidmodelblock(blockid=169, name="sea_lantern") # hay block + + @material(blockid=170, data=list(range(3)), solid=True) def hayblock(self, blockid, data): - return self.build_block_from_model('hay_block', blockstate = {'axis': ({ 0 : 'y', 1: 'x', 2 : 'z'}[data])}) + return self.build_block_from_model('hay_block', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) # carpet - wool block that's small? @material(blockid=171, data=list(range(17)), transparent=True) @@ -5293,27 +5327,34 @@ def chorus_flower(self, blockid, data): return self.build_block(texture,texture) # purpur pillar + + @material(blockid=202, data=list(range(3)), solid=True) def purpur_pillar(self, blockid, data): - return self.build_block_from_model('purpur_pillar', blockstate = {'axis': ({ 0 : 'y', 1: 'x', 2 : 'z'}[data])}) + return self.build_block_from_model('purpur_pillar', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) # frosted ice + + @material(blockid=212, data=list(range(4)), solid=True) def frosted_ice(self, blockid, data): return self.build_block_from_model("frosted_ice_%d" % data) + @material(blockid=216, data=list(range(12)), solid=True) def boneblock(self, blockid, data): - return self.build_block_from_model('bone_block', blockstate = {'axis': ({ 0 : 'y', 4: 'x', 8 : 'z'}[data & 12])}) + return self.build_block_from_model('bone_block', blockstate={'axis': ({0: 'y', 4: 'x', 8: 'z'}[data & 12])}) # observer + + @material(blockid=218, data=[0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13], solid=True, nospawn=True) def observer(self, blockid, data): facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data & 0b0111] if data & 0b1000: - return self.build_block_from_model('observer', {'facing':facing}) + return self.build_block_from_model('observer', {'facing': facing}) else: - return self.build_block_from_model('observer_on', {'facing':facing}) + return self.build_block_from_model('observer_on', {'facing': facing}) # shulker box @material(blockid=list(range(219, 235)) + [257], data=list(range(6)), solid=True, nospawn=True) @@ -5405,43 +5446,52 @@ def crops(self, blockid, data): @material(blockid=list(range(235, 251)), data=list(range(4)), solid=True) def glazed_terracotta(self, blockid, data): facing = {0: 'south', 1: 'west', 2: 'north', 3: 'east'}[data] - return self.build_block_from_model("%s_glazed_terracotta" % color_map[blockid - 235], {'facing':facing}) + return self.build_block_from_model("%s_glazed_terracotta" % color_map[blockid - 235], {'facing': facing}) # scaffolding + + @material(blockid=[11414], data=list(range(2)), solid=False, transparent=True) def scaffolding(self, blockid, data): top = self.load_image_texture("assets/minecraft/textures/block/scaffolding_top.png") side = self.load_image_texture("assets/minecraft/textures/block/scaffolding_side.png") - img = self.build_block(top,side) + img = self.build_block(top, side) return img # beehive and bee_nest + + @material(blockid=[11501, 11502], data=list(range(8)), solid=True) def beehivenest(self, blockid, data): facing = {0: 'south', 1: 'west', 2: 'north', 3: 'east'}[data % 4] if blockid == 11501: if data >= 4: - return self.build_block_from_model('beehive_honey', {'facing':facing}) - return self.build_block_from_model('beehive', {'facing':facing}) - else: # blockid == 11502: + return self.build_block_from_model('beehive_honey', {'facing': facing}) + return self.build_block_from_model('beehive', {'facing': facing}) + else: # blockid == 11502: if data >= 4: - return self.build_block_from_model('bee_nest_honey', {'facing':facing}) - return self.build_block_from_model('bee_nest', {'facing':facing}) + return self.build_block_from_model('bee_nest_honey', {'facing': facing}) + return self.build_block_from_model('bee_nest', {'facing': facing}) + # honey_block transparentmodelblock(blockid=11504, name="honey_block") # Barrel + + @material(blockid=11418, data=list(range(12)), solid=True) def barrel(self, blockid, data): - facing = { 0: 'up', 1: 'down', 2: 'south', 3: 'east', 4: 'north', 5: 'west'}[data >> 1] + facing = {0: 'up', 1: 'down', 2: 'south', 3: 'east', 4: 'north', 5: 'west'}[data >> 1] if data & 0x01: - return self.build_block_from_model('barrel_open', {'facing':facing}) - return self.build_block_from_model('barrel', {'facing':facing}) + return self.build_block_from_model('barrel_open', {'facing': facing}) + return self.build_block_from_model('barrel', {'facing': facing}) # Campfire (11506) and soul campfire (1003) + + @material(blockid=[11506, 1003], data=list(range(8)), solid=True, transparent=True, nospawn=True) def campfire(self, blockid, data): # Do rotation, mask to not clobber lit data @@ -5669,18 +5719,22 @@ def create_tile(img_src, coord_crop, coord_paste, rot): return img + # nether roof # Ancient Debris solidmodelblock(blockid=[1000], name="ancient_debris") # Basalt + + @material(blockid=[1001, 1002], data=list(range(3)), solid=True) def basalt(self, blockid, data): - axis = { 0 : 'y', 1: 'x', 2 : 'z'}[data] - if blockid == 1001: # basalt - return self.build_block_from_model('basalt', {'axis':axis}) - if blockid == 1002: # polished_basalt - return self.build_block_from_model('polished_basalt', {'axis':axis}) + axis = {0: 'y', 1: 'x', 2: 'z'}[data] + if blockid == 1001: # basalt + return self.build_block_from_model('basalt', {'axis': axis}) + if blockid == 1002: # polished_basalt + return self.build_block_from_model('polished_basalt', {'axis': axis}) + # nether roof # Blackstone block @@ -5749,9 +5803,12 @@ def respawn_anchor(self, blockid, data): solidmodelblock(blockid=1063, name="copper_ore") # deepslate + + @material(blockid=1083, data=list(range(3)), solid=True) def deepslate(self, blockid, data): - return self.build_block_from_model('deepslate', {'axis': { 0 : 'y', 1: 'x', 2 : 'z'}[data]}) + return self.build_block_from_model('deepslate', {'axis': {0: 'y', 1: 'x', 2: 'z'}[data]}) + # mineral overlay solidmodelblock(blockid=1086, name="deepslate_coal_ore") @@ -6063,4 +6120,4 @@ def spore_blossom(self, blockid, data): # Render all blocks not explicitly declared before # Must run last to prevent being hidden by blocks with fixed IDs -unbound_models() \ No newline at end of file +unbound_models() From 6f7911e47c949d5f330753b7a2ee15f7397b3876 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Mon, 11 Jul 2022 19:09:03 +0200 Subject: [PATCH 19/34] slabs and minor fixes --- overviewer_core/textures.py | 82 ++++++++++++++++++++++++++++--------- overviewer_core/world.py | 10 ++++- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 4473a97f6..e552654bf 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -41,7 +41,7 @@ used_datas = set() max_blockid = 0 max_data = 0 -next_unclaimed_id = 1 +next_unclaimed_id = 2048 transparent_blocks = set() solid_blocks = set() @@ -894,6 +894,9 @@ def load_model(self, modelname): # fix known inconsistencies in model info def normalize_model(self, modelname): match modelname: + case 'block/observer': + self.models[modelname] = deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['up']['uv'] = [0, 0, 16, 16] # remap textures of blocks with the rotation property to match the mapping of the observer textures case 'block/loom': self.models[modelname] = deepcopy(self.models[modelname]) @@ -928,27 +931,20 @@ def build_block_from_model(self, modelname, blockstate={}): for elem in colmodel['elements']: try: if 'west' in elem['faces']: - texture = self.draw_face('west', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (12, 6), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'west') elif 'east' in elem['faces']: - texture = self.draw_face('east', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0, 0), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'east') if 'north' in elem['faces']: - texture = self.draw_face('north', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0, 6), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'north') elif 'south' in elem['faces']: - texture = self.draw_face('south', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (12, 0), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'south') if 'up' in elem['faces']: - texture = self.draw_face('up', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0, 0), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'up') elif 'down' in elem['faces']: - texture = self.draw_face('down', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0, 12), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'down') except KeyError: - # element has an invalid texture; skipping entire element continue # Manually touch up 6 pixels that leave a gap because of how the @@ -962,6 +958,37 @@ def build_block_from_model(self, modelname, blockstate={}): return img + def draw_block(self, img, elem, colmodel, blockstate, modelname, direction): + if 'facing' in blockstate: + facing = self.map_facing_to_real(blockstate['facing'], direction) + else: + facing = 'north' + texture = self.draw_face(direction, elem, colmodel, blockstate, modelname) + alpha_over(img, texture, self.image_pos(direction, elem, facing), texture) + + def image_pos(self, direction, element, facing): + + # TODO: deal with uv, from, to + match direction: + + case 'west': return (12, 6) + case 'east': return (0, 0) + case 'north': return(0, 6) + case 'south': return (12, 0) + # # move up + case 'down': + fromy = 12 + if 'from' in element: + fromy = int(math.ceil(((16 - element['from'][1])/16*12.))) + return (0, fromy) # 0,0 + + # # move down + case 'up' | _: + toy = 0 + if 'to' in element: + toy = int(math.ceil(((16 - element['to'][1])/16*12.))) + return (0, toy) # 0,6 + def numvalue_orientation(self, orientation): return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4, 'down': 6}[orientation] @@ -1027,6 +1054,17 @@ def draw_face(self, direction, elem, data, blockstate, modelname): texture = self.find_texture_from_model( elem['faces'][textureface]['texture'], data['textures']).copy() + + if 'uv' in elem['faces'][textureface]: + if 'facing' in blockstate and textureface in {'up','down'}: + texture = texture.rotate(90) + uvface = {'north':'east','east':'south','south':'west','west':'north','up':'up','down':'down'}[textureface] + texture = self.crop_to_transparancy(texture, elem['faces'][uvface]['uv']) + if 'facing' in blockstate and textureface in {'up','down'}: + texture = texture.rotate(270) + + # TODO: deal with rotation + if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) @@ -1088,14 +1126,20 @@ def find_texture_from_model(self, face, textureset): # TODO: deal with uv, from, to def crop_to_transparancy(self, img, area): + if area == [ 0, 0, 16, 16 ]: + return img # top - ImageDraw.Draw(img).rectangle((area[2], 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + if area[2] != 0: + ImageDraw.Draw(img).rectangle((area[2]+1, 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # right - ImageDraw.Draw(img).rectangle((0, area[3], 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + if area[3] != 0: + ImageDraw.Draw(img).rectangle((0, area[3]+1, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # bottom - ImageDraw.Draw(img).rectangle((0, 0, area[0], 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + if area[0] != 16: + ImageDraw.Draw(img).rectangle((0, 0, area[0]-1, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # left - ImageDraw.Draw(img).rectangle((0, 0, 16, area[1]), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + if area[1] != 16: + ImageDraw.Draw(img).rectangle((0, 0, 16, area[1]-1), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) return img ## @@ -5277,8 +5321,6 @@ def hopper(self, blockid, data): solidmodelblock(blockid=169, name="sea_lantern") # hay block - - @material(blockid=170, data=list(range(3)), solid=True) def hayblock(self, blockid, data): return self.build_block_from_model('hay_block', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index ed16045ae..1826f9899 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -375,6 +375,7 @@ def __init__(self, regiondir, rel): 'minecraft:oak_stairs': (53, 0), 'minecraft:crimson_stairs': (509, 0), 'minecraft:warped_stairs': (510, 0), + 'minecraft:mangrove_stairs': (577, 0), 'minecraft:chest': (54, 0), 'minecraft:redstone_wire': (55, 0), 'minecraft:diamond_ore': (56, 0), @@ -924,6 +925,8 @@ def _get_block(self, palette_entry): 'minecraft:waxed_weathered_cut_copper_slab', 'minecraft:waxed_oxidized_cut_copper_slab' ) + unbound_slabs = ('minecraft:mangrove_slab',) + # Map from slab to double slab block slab_to_double = { 'minecraft:stone_slab': 'minecraft:stone', @@ -969,7 +972,8 @@ def _get_block(self, palette_entry): 'minecraft:prismarine_slab': 'minecraft:prismarine', 'minecraft:dark_prismarine_slab': 'minecraft:dark_prismarine', 'minecraft:prismarine_brick_slab': 'minecraft:prismarine_bricks', - } + 'minecraft:mangrove_slab': 'minecraft:mangrove_planks', + } colors = ['white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime', 'pink', 'gray', 'light_gray', 'cyan', 'purple', 'blue', 'brown', 'green', 'red', 'black'] @@ -1022,7 +1026,9 @@ def _get_block(self, palette_entry): elif key in ('minecraft:sunflower', 'minecraft:lilac', 'minecraft:tall_grass', 'minecraft:large_fern', 'minecraft:rose_bush', 'minecraft:peony'): if palette_entry['Properties']['half'] == 'upper': data |= 0x08 - elif key in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs: + elif key.endswith('_slab') and palette_entry['Properties']['type'] == 'top': + (block, data) = modelblocks[key+'_top'] + elif key in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs + unbound_slabs: # handle double slabs if palette_entry['Properties']['type'] == 'top': data |= 0x08 From ce0b6070eac636091ddfd81b3f10d855bedc2b35 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Fri, 15 Jul 2022 18:31:55 +0200 Subject: [PATCH 20/34] process offset valies for north and west faces --- overviewer_core/textures.py | 201 ++++++++++++++++++++++++++---------- 1 file changed, 147 insertions(+), 54 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index e552654bf..50d90c6c0 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -931,20 +931,20 @@ def build_block_from_model(self, modelname, blockstate={}): for elem in colmodel['elements']: try: if 'west' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'west') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'west') elif 'east' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'east') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'east') if 'north' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'north') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'north') elif 'south' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'south') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'south') if 'up' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'up') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'up') elif 'down' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'down') - except KeyError: + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'down') + except KeyError as e: continue # Manually touch up 6 pixels that leave a gap because of how the @@ -958,23 +958,71 @@ def build_block_from_model(self, modelname, blockstate={}): return img - def draw_block(self, img, elem, colmodel, blockstate, modelname, direction): + def draw_blockface(self, img, elem, colmodel, blockstate, modelname, direction): if 'facing' in blockstate: facing = self.map_facing_to_real(blockstate['facing'], direction) + elif 'axis' in blockstate: + facing = self.map_axis_to_real(blockstate['axis'], direction) else: - facing = 'north' - texture = self.draw_face(direction, elem, colmodel, blockstate, modelname) - alpha_over(img, texture, self.image_pos(direction, elem, facing), texture) + facing = direction + texture = self.build_texture(direction, elem, colmodel, blockstate, modelname, facing) + alpha_over(img, texture, self.image_pos(direction, elem, facing, modelname), texture) - def image_pos(self, direction, element, facing): + def image_pos(self, elementdirection, element, facing, modelname): - # TODO: deal with uv, from, to - match direction: + match elementdirection: - case 'west': return (12, 6) + # case 'west': return (12, 6) case 'east': return (0, 0) - case 'north': return(0, 6) + # case 'north': return(0, 6) case 'south': return (12, 0) + # case 'up': return (0, 0) + # case 'down': return (0, 12) + + # # 24x24 image + ## WIP + # Down and to the right + # 16 => 12,0 + # 0 => 6,6 + # case 'south': + # toxa = 12 + # tox = 0 + # # if 'to' in element: + # # toxa = int(math.ceil(6 + (6/16 * element[face[0]][face[1]]))) + # # tox = int(math.ceil(6 - (6/16 * element[face[0]][face[1]]))) + # return (toxa, tox) # 12,0 + + # # # # Up and to the right + # # # # 0 => 0,6 + # # # # 16 => 12,0 + case 'west': + setback = 16 - self.setback(element, facing) + + if modelname == 'block/anvil': + print('hit anvil west with ' + facing + ' and ' + str(setback)) + + toya = int(math.ceil(12/16 * (setback))) + toy = int(math.ceil(6/16 * (setback))) + return (toya, toy) # 12, 6 + + # Up and to the left + # 16 => 12,0 + # 0 => 0,6 + case 'north': + setback = self.setback(element, facing) + toya = int(math.ceil((12/16 * (setback)))) + toy = int(math.ceil(6 - (6/16 * (setback)))) + return (toya, toy) # 0, 6 + + # # # # Down and to the right + # # # # 0 => 0,0 + # # # # 16 => 6,6 + # case 'east': + # setback = self.setback(element, facing) + # toya = int(math.ceil(6/16 * (setback))) + # toy = int(math.ceil(6/16 * (setback))) + # return (toya, toy) # 0, 0 + # # move up case 'down': fromy = 12 @@ -989,6 +1037,12 @@ def image_pos(self, direction, element, facing): toy = int(math.ceil(((16 - element['to'][1])/16*12.))) return (0, toy) # 0,6 + def setback(self, element, facing): + return {'up': 16, 'down': 0, + 'north': element['from'][2], 'south': 16 - element['to'][2], + 'east': 16 - element['to'][0], 'west': element['from'][0]}[facing] + + def numvalue_orientation(self, orientation): return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4, 'down': 6}[orientation] @@ -1045,34 +1099,83 @@ def axis_rotation(self, axis, face, texture): case 'y' | _: return texture - def draw_face(self, direction, elem, data, blockstate, modelname): - textureface = direction - if 'facing' in blockstate: - textureface = self.map_facing_to_real(blockstate['facing'], direction) - if 'axis' in blockstate: - textureface = self.map_axis_to_real(blockstate['axis'], direction) + def build_texture(self, direction, elem, data, blockstate, modelname, textureface): texture = self.find_texture_from_model( elem['faces'][textureface]['texture'], data['textures']).copy() - if 'uv' in elem['faces'][textureface]: - if 'facing' in blockstate and textureface in {'up','down'}: - texture = texture.rotate(90) - uvface = {'north':'east','east':'south','south':'west','west':'north','up':'up','down':'down'}[textureface] - texture = self.crop_to_transparancy(texture, elem['faces'][uvface]['uv']) - if 'facing' in blockstate and textureface in {'up','down'}: - texture = texture.rotate(270) - - # TODO: deal with rotation - if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) + texture = self.texture_rotation(direction, texture, blockstate, elem['faces'][textureface], modelname) + + if 'from' in elem and 'to' in elem and (elem['from'] != [0,0,0] or elem['to'] != [16,16,16]): + area = [0,0,16,16] + + match textureface: + + case 'west': + area = [16-elem['from'][2],elem['from'][1],16-elem['to'][2],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + case 'east': + area = [elem['from'][2],elem['from'][1],elem['to'][2],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + case 'north': + area = [16-elem['from'][0],elem['from'][1],16-elem['to'][0],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + case 'south': + area = [elem['from'][0],elem['from'][1],elem['to'][0],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + case 'up'|'down'|_: + if 'facing' in blockstate and blockstate['facing'] in {'north'}: + area = [elem['from'][0],elem['from'][2],elem['to'][0],elem['to'][2]] + elif 'facing' in blockstate and blockstate['facing'] in {'south'}: + area = [16-elem['from'][0],16-elem['from'][2],16-elem['to'][0],16-elem['to'][2]] + elif 'facing' in blockstate and blockstate['facing'] in {'west'}: + area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] + elif 'facing' in blockstate and blockstate['facing'] in {'east'}: + area = [16-elem['from'][2],16-elem['from'][0],16-elem['to'][2],16-elem['to'][0]] + else: + area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] + texture = self.crop_to_transparancy(texture, area) + + # TODO: deal with rotation texture = self.transform_texture(direction, texture, blockstate, elem['faces'][textureface]) texture = self.adjust_lighting(direction, texture) return texture + def crop_to_transparancy(self, img, area): + # PIL image coordinates do not match MC texture coordinates + # PIL starts in lower left + # MC starts in upper left + # r, b, l, t + + if area[0] > area[2]: + area = [area[2], area[1], area[0], area[3]] + if area[1] > area[3]: + area = [area[0], area[3], area[2], area[1]] + if area == [ 0, 0, 16, 16 ]: + return img + + # cut from top + if area[3] != 16: + ImageDraw.Draw(img).rectangle((0, 0, 16, 16 - area[3]-1), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + + # cut from bottom + if area[1] != 0: + ImageDraw.Draw(img).rectangle((0, 16 - (area[1]-1), 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + + # cut from right + if area[2] != 16: + ImageDraw.Draw(img).rectangle((area[2]-1, 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + + # cut from left + if area[0] != 0: + ImageDraw.Draw(img).rectangle((0, 0, area[0]-1, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + + return img + def adjust_lighting(self, direction, texture): match direction: case 'south' | 'west': @@ -1088,7 +1191,7 @@ def adjust_lighting(self, direction, texture): case 'down' | 'up' | _: return texture - def transform_texture(self, direction, texture, blockstate, faceinfo): + def texture_rotation(self, direction, texture, blockstate, faceinfo, modelname): rotation = 0 if 'texturerotation' in faceinfo: rotation += faceinfo['texturerotation'] @@ -1100,20 +1203,28 @@ def transform_texture(self, direction, texture, blockstate, faceinfo): 90][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] else: rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] - return self.transform_image_top(texture.rotate(rotation)) case 'north' | 'south': if 'rotation' in faceinfo: rotation = {0: 180, 90: 90, 180: 0, 270: 270}[faceinfo['rotation']] if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: rotation += [90, 90][({'up': 0, 'down': 1}[blockstate['facing']])] - texture = self.transform_image_side(texture.rotate(rotation)) case 'west' | 'east': if 'rotation' in faceinfo: rotation = {0: 180, 90: 270, 180: 0, 270: 90}[faceinfo['rotation']] if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] + + return texture.rotate(rotation % 360) + + def transform_texture(self, direction, texture, blockstate, faceinfo): + match direction: + case 'down' | 'up': + return self.transform_image_top(texture) + case 'north' | 'south': + texture = self.transform_image_side(texture) + case 'west' | 'east': texture = texture.transpose(Image.FLIP_LEFT_RIGHT) - texture = self.transform_image_side(texture.rotate(rotation)) + texture = self.transform_image_side(texture) texture = texture.transpose(Image.FLIP_LEFT_RIGHT) return texture @@ -1124,24 +1235,6 @@ def find_texture_from_model(self, face, textureset): else: return self.load_image_texture("assets/minecraft/textures/" + re.sub('.*:', '', face) + '.png') - # TODO: deal with uv, from, to - def crop_to_transparancy(self, img, area): - if area == [ 0, 0, 16, 16 ]: - return img - # top - if area[2] != 0: - ImageDraw.Draw(img).rectangle((area[2]+1, 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - # right - if area[3] != 0: - ImageDraw.Draw(img).rectangle((0, area[3]+1, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - # bottom - if area[0] != 16: - ImageDraw.Draw(img).rectangle((0, 0, area[0]-1, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - # left - if area[1] != 16: - ImageDraw.Draw(img).rectangle((0, 0, 16, area[1]-1), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - return img - ## ## The other big one: @material and associated framework ## From 3286d52fe9142c7230075f3160f01f43a5b33ca4 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Sun, 17 Jul 2022 19:36:56 +0200 Subject: [PATCH 21/34] added mangrove slabs --- overviewer_core/src/block_class.c | 3 +- overviewer_core/src/mc_id.h | 7 +- overviewer_core/src/overviewer.h | 2 +- overviewer_core/textures.py | 299 ++++++++---------------------- overviewer_core/world.py | 40 ++-- 5 files changed, 98 insertions(+), 253 deletions(-) diff --git a/overviewer_core/src/block_class.c b/overviewer_core/src/block_class.c index 65f93ce4b..497602610 100644 --- a/overviewer_core/src/block_class.c +++ b/overviewer_core/src/block_class.c @@ -345,7 +345,8 @@ const mc_block_t block_class_alt_height[] = { block_polished_deepslate_slab, block_deepslate_brick_slab, block_deepslate_tile_slab, - block_mud_brick_slab}; + block_mud_brick_slab, + block_mangrove_slab}; const size_t block_class_alt_height_len = COUNT_OF(block_class_alt_height); const mc_block_t block_class_nether_roof[] = { diff --git a/overviewer_core/src/mc_id.h b/overviewer_core/src/mc_id.h index 1442f2139..2c034b972 100644 --- a/overviewer_core/src/mc_id.h +++ b/overviewer_core/src/mc_id.h @@ -118,7 +118,6 @@ enum mc_block_id { block_spruce_stairs = 134, block_birch_stairs = 135, block_jungle_stairs = 136, - block_beacon = 138, block_mushroom_stem = 139, block_flower_pot = 140, block_carrots = 141, @@ -147,9 +146,7 @@ enum mc_block_id { block_slime = 165, block_barrier = 166, block_iron_trapdoor = 167, - block_sea_lantern = 169, block_hay_block = 170, - block_carpet = 171, block_double_plant = 175, block_standing_banner = 176, block_wall_banner = 177, @@ -266,7 +263,6 @@ enum mc_block_id { block_soul_fire = 1040, // 1.17 - block_budding_amethyst = 1045, block_waxed_copper = 1050, block_waxed_exposed_copper = 1051, block_waxed_weathered_copper = 1052, @@ -334,6 +330,7 @@ enum mc_block_id { block_mud_brick_slab = 1124, block_mangrove_roots = 1125, block_mangrove_log = 1126, + block_mangrove_slab = 1789, // adding a gap in the numbering of walls to keep them all // in one numbering block starting at 1792 @@ -390,9 +387,7 @@ enum mc_block_id { block_smooth_quartz_slab = 11357, block_smooth_stone_slab = 11358, block_blast_furnace = 11362, - // block_blast_furnace lit 11363 block_smoker = 11364, - // block_smoker lit = 11365, block_lectern = 11366, block_loom = 11367, block_stonecutter = 11368, diff --git a/overviewer_core/src/overviewer.h b/overviewer_core/src/overviewer.h index 413cdb24c..3173bdf78 100644 --- a/overviewer_core/src/overviewer.h +++ b/overviewer_core/src/overviewer.h @@ -31,7 +31,7 @@ // increment this value if you've made a change to the c extension // and want to force users to rebuild -#define OVERVIEWER_EXTENSION_VERSION 113 +#define OVERVIEWER_EXTENSION_VERSION 114 #include #include diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 50d90c6c0..084c1374f 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -969,7 +969,7 @@ def draw_blockface(self, img, elem, colmodel, blockstate, modelname, direction): alpha_over(img, texture, self.image_pos(direction, elem, facing, modelname), texture) def image_pos(self, elementdirection, element, facing, modelname): - + match elementdirection: # case 'west': return (12, 6) @@ -997,10 +997,6 @@ def image_pos(self, elementdirection, element, facing, modelname): # # # # 16 => 12,0 case 'west': setback = 16 - self.setback(element, facing) - - if modelname == 'block/anvil': - print('hit anvil west with ' + facing + ' and ' + str(setback)) - toya = int(math.ceil(12/16 * (setback))) toy = int(math.ceil(6/16 * (setback))) return (toya, toy) # 12, 6 @@ -1042,7 +1038,6 @@ def setback(self, element, facing): 'north': element['from'][2], 'south': 16 - element['to'][2], 'east': 16 - element['to'][0], 'west': element['from'][0]}[facing] - def numvalue_orientation(self, orientation): return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4, 'down': 6}[orientation] @@ -1103,7 +1098,7 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac texture = self.find_texture_from_model( elem['faces'][textureface]['texture'], data['textures']).copy() - + if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) texture = self.texture_rotation(direction, texture, blockstate, elem['faces'][textureface], modelname) @@ -1114,10 +1109,10 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac match textureface: case 'west': - area = [16-elem['from'][2],elem['from'][1],16-elem['to'][2],elem['to'][1]] + area = [elem['from'][2],elem['from'][1],elem['to'][2],elem['to'][1]] texture = self.crop_to_transparancy(texture, area) case 'east': - area = [elem['from'][2],elem['from'][1],elem['to'][2],elem['to'][1]] + area = [16-elem['from'][2],elem['from'][1],16-elem['to'][2],elem['to'][1]] texture = self.crop_to_transparancy(texture, area) case 'north': area = [16-elem['from'][0],elem['from'][1],16-elem['to'][0],elem['to'][1]] @@ -1127,9 +1122,9 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac texture = self.crop_to_transparancy(texture, area) case 'up'|'down'|_: if 'facing' in blockstate and blockstate['facing'] in {'north'}: - area = [elem['from'][0],elem['from'][2],elem['to'][0],elem['to'][2]] + area = [elem['from'][0],16-elem['from'][2],elem['to'][0],16-elem['to'][2]] elif 'facing' in blockstate and blockstate['facing'] in {'south'}: - area = [16-elem['from'][0],16-elem['from'][2],16-elem['to'][0],16-elem['to'][2]] + area = [16-elem['from'][0],elem['from'][2],16-elem['to'][0],elem['to'][2]] elif 'facing' in blockstate and blockstate['facing'] in {'west'}: area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] elif 'facing' in blockstate and blockstate['facing'] in {'east'}: @@ -1137,7 +1132,7 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac else: area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] texture = self.crop_to_transparancy(texture, area) - + # TODO: deal with rotation texture = self.transform_texture(direction, texture, blockstate, elem['faces'][textureface]) @@ -1340,9 +1335,23 @@ def inner_billboard(self, unused_id, unused_data): def unbound_models(): global max_blockid, block_models, next_unclaimed_id + tex = Textures() - models = Textures.find_models(Textures()) + models = tex.find_models(tex) for model in models: + # determine transparency + + colmodel = tex.load_model('block/' + model) + if 'elements' not in colmodel: + continue + transp = False + + # for each elements + for elem in colmodel['elements']: + if 'from' in elem and 'to' in elem and (elem['from'] != [0,0,0] or elem['to'] != [16,16,16]): + transp = True + break + # find next unclaimed id to keep id values as low as possible while (next_unclaimed_id, 0) in blockmap_generators: next_unclaimed_id = next_unclaimed_id + 1 @@ -1350,7 +1359,7 @@ def unbound_models(): if next_unclaimed_id < 2048 and next_unclaimed_id > 1791: next_unclaimed_id = 2048 id = next_unclaimed_id - solidmodelblock(blockid=id, name=model) + modelblock(blockid=id, name=model, transparent=transp, solid=True) block_models['minecraft:' + model] = (id, 0) ## @@ -1594,6 +1603,10 @@ def sponge(self, blockid, data): # lapis lazuli block solidmodelblock(blockid=22, name="lapis_block") +@material(blockid=[577], data=list(range(8)), solid=True, transparent=True) +def modern_stairs(self, blockid, data): + facing = {3: 'north', 0: 'east', 2: 'south', 1: 'west' }[data%4] + return self.build_block_from_model('mangrove_stairs', {'facing': facing}) @material(blockid=[23, 158], data=list(range(6)), solid=True) def dropper(self, blockid, data): @@ -2024,10 +2037,10 @@ def flower(self, blockid, data): # 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, add prismarine slabs -@material(blockid=[43, 44, 181, 182, 204, 205, 1124] + list(range(11340, 11359)) + +@material(blockid=[43, 44, 181, 182, 204, 205, 1124, 1789] + list(range(11340, 11359)) + list(range(1027, 1030)) + list(range(1072, 1080)) + list(range(1103, 1107)), data=list(range(16)), - transparent=[44, 182, 205, 1124] + list(range(11340, 11359)) + list(range(1027, 1030)) + + transparent=[44, 182, 205, 1124, 1789] + list(range(11340, 11359)) + list(range(1027, 1030)) + list(range(1072, 1080)) + list(range(1103, 1107)), solid=True) def slabs(self, blockid, data): if blockid == 44 or blockid == 182: @@ -2146,11 +2159,13 @@ def slabs(self, blockid, data): top = side = self.load_image_texture(deepslate_tex[blockid]).copy() elif blockid == 1124: top = side = self.load_image_texture("assets/minecraft/textures/block/mud_bricks.png").copy() + elif blockid == 1789: + top = side = self.load_image_texture("assets/minecraft/textures/block/mangrove_planks.png").copy() if blockid == 43 or blockid == 181 or blockid == 204: # double slab return self.build_block(top, side) - return self.build_slab_block(top, side, data & 8 == 8); + return self.build_slab_block(top, side, data & 8 == 8) # TNT solidmodelblock(blockid=46, name="tnt", nospawn=True) @@ -4453,6 +4468,26 @@ def build_torch(active): # the trapdoor is looks like a sprite when opened, that's not good @material(blockid=[96,167,451,11332,11333,11334,11335,11336,12501,12502], data=list(range(16)), transparent=True, nospawn=True) def trapdoor(self, blockid, data): + + # texture generation + model_map = {96:"oak_trapdoor", + 167:"iron_trapdoor", + 451:"mangrove_trapdoor", + 11332:"spruce_trapdoor", + 11333:"birch_trapdoor", + 11334:"jungle_trapdoor", + 11335:"acacia_trapdoor", + 11336:"dark_oak_trapdoor", + 12501:"crimson_trapdoor", + 12502:"warped_trapdoor", + } + facing = {0: 'north', 1: 'south', 2: 'west', 3: 'east'}[data % 4] + + if data & 0x4 == 0x4: # off + return self.build_block_from_model("%s_open" % model_map[blockid], {'facing': facing}) + if data & 0x8 == 0x8: # off + return self.build_block_from_model("%s_top" % model_map[blockid] ) + return self.build_block_from_model("%s_bottom" % model_map[blockid]) # rotation # Masked to not clobber opened/closed info @@ -4831,15 +4866,10 @@ def nether_wart(self, blockid, data): return img # enchantment table -# TODO there's no book at the moment +# there's no book at the moment because it is not a part of the model @material(blockid=116, transparent=True) def enchantment_table(self, blockid, data): - # no book at the moment - top = self.load_image_texture("assets/minecraft/textures/block/enchanting_table_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/enchanting_table_side.png") - img = self.build_full_block((top, 4), None, None, side, side) - - return img + return self.build_block_from_model('enchanting_table') # brewing stand # TODO this is a place holder, is a 2d image pasted @@ -4895,7 +4925,7 @@ def end_portal(self, blockid, data): return self.build_block(t, t) t = self.transform_image_top(t) - alpha_over(img, t, (0,0), t) + alpha_over(img, t, (0,6), t) return img @@ -4903,33 +4933,13 @@ def end_portal(self, blockid, data): # end portal frame (data range 8 to get all orientations of filled) @material(blockid=120, data=list(range(8)), transparent=True, solid=True, nospawn=True) def end_portal_frame(self, blockid, data): - # Do rotation, only seems to affect ender eye & top of frame - data = data & 0b100 | ((self.rotation + (data & 0b11)) % 4) - - top = self.load_image_texture("assets/minecraft/textures/block/end_portal_frame_top.png").copy() - top = top.rotate((data % 4) * 90) - side = self.load_image_texture("assets/minecraft/textures/block/end_portal_frame_side.png") - img = self.build_full_block((top, 4), None, None, side, side) - if data & 0x4 == 0x4: # ender eye on it - # generate the eye - eye_t = self.load_image_texture("assets/minecraft/textures/block/end_portal_frame_eye.png").copy() - eye_t_s = eye_t.copy() - # cut out from the texture the side and the top of the eye - ImageDraw.Draw(eye_t).rectangle((0, 0, 15, 4), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(eye_t_s).rectangle((0, 4, 15, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - # transform images and paste - eye = self.transform_image_top(eye_t.rotate((data % 4) * 90)) - eye_s = self.transform_image_side(eye_t_s) - eye_os = eye_s.transpose(Image.FLIP_LEFT_RIGHT) - alpha_over(img, eye_s, (5, 5), eye_s) - alpha_over(img, eye_os, (9, 5), eye_os) - alpha_over(img, eye, (0, 0), eye) - - return img + facing = {2: 'north', 0: 'south', 1: 'west', 3: 'east'}[data % 4] + if data & 0x4 == 0x4: + return self.build_block_from_model('end_portal_frame_filled', {'facing': facing}) + return self.build_block_from_model('end_portal_frame', {'facing': facing}) # dragon egg -# NOTE: this isn't a block, but I think it's better than nothing transparentmodelblock(blockid=122, name="dragon_egg") @@ -4943,34 +4953,9 @@ def redstone_lamp(self, blockid, data): @material(blockid=[151,178], transparent=True) def daylight_sensor(self, blockid, data): if blockid == 151: # daylight sensor - top = self.load_image_texture("assets/minecraft/textures/block/daylight_detector_top.png") + return self.build_block_from_model('daylight_detector') else: # inverted daylight sensor - top = self.load_image_texture("assets/minecraft/textures/block/daylight_detector_inverted_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/daylight_detector_side.png") - - # 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) - - img = Image.new("RGBA", (24,24), self.bgcolor) - alpha_over(img, side, (0,12), side) - alpha_over(img, otherside, (12,12), otherside) - alpha_over(img, top, (0,6), top) - - return img + return self.build_block_from_model('daylight_detector_inverted') # wooden double and normal slabs @@ -5088,29 +5073,6 @@ def cocoa_plant(self, blockid, data): return img -# beacon block -# at the moment of writing this, it seems the beacon block doens't use -# the data values -@material(blockid=138, transparent=True) -def beacon(self, blockid, data): - # generate the three pieces of the block - t = self.load_image_texture("assets/minecraft/textures/block/glass.png") - glass = self.build_block(t,t) - t = self.load_image_texture("assets/minecraft/textures/block/obsidian.png") - obsidian = self.build_full_block((t,12),None, None, t, t) - obsidian = obsidian.resize((20,20), Image.ANTIALIAS) - t = self.load_image_texture("assets/minecraft/textures/block/beacon.png") - crystal = self.build_block(t,t) - crystal = crystal.resize((16,16),Image.ANTIALIAS) - - # compose the block - img = Image.new("RGBA", (24,24), self.bgcolor) - alpha_over(img, obsidian, (2, 4), obsidian) - alpha_over(img, crystal, (4,3), crystal) - alpha_over(img, glass, (0,0), glass) - - return img - # cobblestone and mossy cobblestone walls, chorus plants, mossy stone brick walls # one additional bit of data value added for mossy and cobblestone @material(blockid=[199]+list(range(1792, 1813 + 1)), data=list(range(32)), transparent=True, nospawn=True) @@ -5286,106 +5248,35 @@ def crops4(self, blockid, data): return img -# anvils @material(blockid=145, data=list(range(12)), transparent=True, nospawn=True) def anvil(self, blockid, data): - # anvils only have two orientations, invert it for rotations 1 and 3 - orientation = data & 0x1 - if self.rotation in (1, 3): - if orientation == 1: - orientation = 0 - else: - orientation = 1 - - # get the correct textures - # the bits 0x4 and 0x8 determine how damaged is the anvil + facing = {2: 'north', 0: 'south', 1: 'west', 3: 'east'}[data % 4] if (data & 0xc) == 0: # non damaged anvil - # return self.build_block_from_model('anvil') - top = self.load_image_texture("assets/minecraft/textures/block/anvil_top.png") + return self.build_block_from_model('anvil', {'facing': facing}) elif (data & 0xc) == 0x4: # slightly damaged - top = self.load_image_texture("assets/minecraft/textures/block/chipped_anvil_top.png") + return self.build_block_from_model('chipped_anvil', {'facing': facing}) elif (data & 0xc) == 0x8: # very damaged - top = self.load_image_texture("assets/minecraft/textures/block/damaged_anvil_top.png") - # everything else use this texture - big_side = self.load_image_texture("assets/minecraft/textures/block/anvil.png").copy() - small_side = self.load_image_texture("assets/minecraft/textures/block/anvil.png").copy() - base = self.load_image_texture("assets/minecraft/textures/block/anvil.png").copy() - small_base = self.load_image_texture("assets/minecraft/textures/block/anvil.png").copy() - - # cut needed patterns - ImageDraw.Draw(big_side).rectangle((0, 8, 15, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(small_side).rectangle((0, 0, 2, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(small_side).rectangle((13, 0, 15, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(small_side).rectangle((0, 8, 15, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(base).rectangle((0, 0, 15, 15), outline=(0, 0, 0, 0)) - ImageDraw.Draw(base).rectangle((1, 1, 14, 14), outline=(0, 0, 0, 0)) - ImageDraw.Draw(small_base).rectangle((0, 0, 15, 15), outline=(0, 0, 0, 0)) - ImageDraw.Draw(small_base).rectangle((1, 1, 14, 14), outline=(0, 0, 0, 0)) - ImageDraw.Draw(small_base).rectangle((2, 2, 13, 13), outline=(0, 0, 0, 0)) - ImageDraw.Draw(small_base).rectangle((3, 3, 12, 12), outline=(0, 0, 0, 0)) - - # check orientation and compose the anvil - if orientation == 1: # bottom-left top-right - top = top.rotate(90) - left_side = small_side - left_pos = (1, 6) - right_side = big_side - right_pos = (10, 5) - else: # top-left bottom-right - right_side = small_side - right_pos = (12, 6) - left_side = big_side - left_pos = (3, 5) - - img = Image.new("RGBA", (24, 24), self.bgcolor) - - # darken sides - alpha = big_side.split()[3] - big_side = ImageEnhance.Brightness(big_side).enhance(0.8) - big_side.putalpha(alpha) - alpha = small_side.split()[3] - small_side = ImageEnhance.Brightness(small_side).enhance(0.9) - small_side.putalpha(alpha) - alpha = base.split()[3] - base_d = ImageEnhance.Brightness(base).enhance(0.8) - base_d.putalpha(alpha) - - # compose - base = self.transform_image_top(base) - base_d = self.transform_image_top(base_d) - small_base = self.transform_image_top(small_base) - top = self.transform_image_top(top) - - alpha_over(img, base_d, (0, 12), base_d) - alpha_over(img, base_d, (0, 11), base_d) - alpha_over(img, base_d, (0, 10), base_d) - alpha_over(img, small_base, (0, 10), small_base) - - alpha_over(img, top, (0, 1), top) # Fix gap between block edges - alpha_over(img, top, (0, 0), top) - - left_side = self.transform_image_side(left_side) - right_side = self.transform_image_side(right_side).transpose(Image.FLIP_LEFT_RIGHT) - - alpha_over(img, left_side, left_pos, left_side) - alpha_over(img, right_side, right_pos, right_side) - - return img + return self.build_block_from_model('damaged_anvil', {'facing': facing}) # mineral overlay # nether quartz ore solidmodelblock(blockid=153, name="nether_quartz_ore") # block of quartz - - @material(blockid=155, data=list(range(3)), solid=True) def quartz_pillar(self, blockid, data): return self.build_block_from_model('quartz_pillar', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) # hopper -@material(blockid=154, data=list(range(4)), transparent=True) +@material(blockid=154, data=list(range(6)), transparent=True) def hopper(self, blockid, data): + # # TODO: + # facing = {0: 'down', 1: 'up', 2: 'east', 3: 'south', 4: 'west', 5: 'north'}[data] + # if facing == 'down': + # return self.build_block_from_model('hopper', {'facing': facing}) + # return self.build_block_from_model('hopper_side', {'facing': facing}) + + #build the top side = self.load_image_texture("assets/minecraft/textures/block/hopper_outside.png") top = self.load_image_texture("assets/minecraft/textures/block/hopper_top.png") @@ -5410,25 +5301,11 @@ def hopper(self, blockid, data): # slime block transparentmodelblock(blockid=165, name="slime_block") -# sea lantern -solidmodelblock(blockid=169, name="sea_lantern") - # hay block @material(blockid=170, data=list(range(3)), solid=True) def hayblock(self, blockid, data): return self.build_block_from_model('hay_block', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) -# carpet - wool block that's small? -@material(blockid=171, data=list(range(17)), transparent=True) -def carpet(self, blockid, data): - if data < 16: - texture = self.load_image_texture("assets/minecraft/textures/block/%s_wool.png" % color_map[data]) - elif data == 16: - texture = self.load_image_texture("assets/minecraft/textures/block/moss_block.png") - - return self.build_full_block((texture,15),texture,texture,texture,texture) - - @material(blockid=175, data=list(range(16)), transparent=True) def flower(self, blockid, data): double_plant_map = ["sunflower", "lilac", "tall_grass", "large_fern", "rose_bush", "peony", "peony", "peony"] @@ -5462,15 +5339,11 @@ def chorus_flower(self, blockid, data): return self.build_block(texture,texture) # purpur pillar - - @material(blockid=202, data=list(range(3)), solid=True) def purpur_pillar(self, blockid, data): return self.build_block_from_model('purpur_pillar', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) # frosted ice - - @material(blockid=212, data=list(range(4)), solid=True) def frosted_ice(self, blockid, data): return self.build_block_from_model("frosted_ice_%d" % data) @@ -5481,8 +5354,6 @@ def boneblock(self, blockid, data): return self.build_block_from_model('bone_block', blockstate={'axis': ({0: 'y', 4: 'x', 8: 'z'}[data & 12])}) # observer - - @material(blockid=218, data=[0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13], solid=True, nospawn=True) def observer(self, blockid, data): facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data & 0b0111] @@ -5584,8 +5455,6 @@ def glazed_terracotta(self, blockid, data): return self.build_block_from_model("%s_glazed_terracotta" % color_map[blockid - 235], {'facing': facing}) # scaffolding - - @material(blockid=[11414], data=list(range(2)), solid=False, transparent=True) def scaffolding(self, blockid, data): top = self.load_image_texture("assets/minecraft/textures/block/scaffolding_top.png") @@ -5594,8 +5463,6 @@ def scaffolding(self, blockid, data): return img # beehive and bee_nest - - @material(blockid=[11501, 11502], data=list(range(8)), solid=True) def beehivenest(self, blockid, data): facing = {0: 'south', 1: 'west', 2: 'north', 3: 'east'}[data % 4] @@ -5613,11 +5480,8 @@ def beehivenest(self, blockid, data): transparentmodelblock(blockid=11504, name="honey_block") # Barrel - - @material(blockid=11418, data=list(range(12)), solid=True) def barrel(self, blockid, data): - facing = {0: 'up', 1: 'down', 2: 'south', 3: 'east', 4: 'north', 5: 'west'}[data >> 1] if data & 0x01: @@ -5625,8 +5489,6 @@ def barrel(self, blockid, data): return self.build_block_from_model('barrel', {'facing': facing}) # Campfire (11506) and soul campfire (1003) - - @material(blockid=[11506, 1003], data=list(range(8)), solid=True, transparent=True, nospawn=True) def campfire(self, blockid, data): # Do rotation, mask to not clobber lit data @@ -5860,8 +5722,6 @@ def create_tile(img_src, coord_crop, coord_paste, rot): solidmodelblock(blockid=[1000], name="ancient_debris") # Basalt - - @material(blockid=[1001, 1002], data=list(range(3)), solid=True) def basalt(self, blockid, data): axis = {0: 'y', 1: 'x', 2: 'z'}[data] @@ -5922,8 +5782,6 @@ def respawn_anchor(self, blockid, data): # nether gold ore solidmodelblock(blockid=1021, name="nether_gold_ore") -solidmodelblock(blockid=1045, name="budding_amethyst") - # waxed copper solidmodelblock(blockid=[1050], name="copper_block") solidmodelblock(blockid=[1051], name="exposed_copper") @@ -5935,11 +5793,10 @@ def respawn_anchor(self, blockid, data): solidmodelblock(blockid=[1060], name="weathered_cut_copper") solidmodelblock(blockid=[1061], name="oxidized_cut_copper") +# mineral overlay solidmodelblock(blockid=1063, name="copper_ore") # deepslate - - @material(blockid=1083, data=list(range(3)), solid=True) def deepslate(self, blockid, data): return self.build_block_from_model('deepslate', {'axis': {0: 'y', 1: 'x', 2: 'z'}[data]}) @@ -6062,9 +5919,15 @@ def cave_vines(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/cave_vines.png") return self.build_sprite(tex) - @material(blockid=1118, data=list(range(6)), transparent=True, solid=True) def lightning_rod(self, blockid, data): + + # lignting rod default model is for facing 'up' + # TODO: for generic processing the texture requires uv handling + + # facing = {0: 'down', 1: 'up', 2: 'east', 3: 'south', 4: 'west', 5: 'north'}[data] + # return self.build_block_from_model('lightning_rod', {'facing': 'north'}) + tex = self.load_image_texture("assets/minecraft/textures/block/lightning_rod.png") img = Image.new("RGBA", (24, 24), self.bgcolor) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 1826f9899..761045d51 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -465,6 +465,7 @@ def __init__(self, regiondir, rel): 'minecraft:dark_oak_slab': (126, 5), 'minecraft:crimson_slab': (126, 6), 'minecraft:warped_slab': (126, 7), + 'minecraft:mangrove_slab': (1789, 0), 'minecraft:cocoa': (127, 0), 'minecraft:sandstone_stairs': (128, 0), 'minecraft:emerald_ore': (129, 0), @@ -474,7 +475,6 @@ def __init__(self, regiondir, rel): 'minecraft:spruce_stairs': (134, 0), 'minecraft:birch_stairs': (135, 0), 'minecraft:jungle_stairs': (136, 0), - 'minecraft:beacon': (138, 0), 'minecraft:mushroom_stem': (139, 0), 'minecraft:flower_pot': (140, 0), 'minecraft:potted_poppy': (140, 0), # Pots not rendering @@ -528,25 +528,7 @@ def __init__(self, regiondir, rel): 'minecraft:dark_oak_stairs': (164, 0), 'minecraft:slime_block': (165,0), 'minecraft:iron_trapdoor': (167, 0), - 'minecraft:sea_lantern': (169, 0), 'minecraft:hay_block': (170, 0), - 'minecraft:white_carpet': (171, 0), - 'minecraft:orange_carpet': (171, 1), - 'minecraft:magenta_carpet': (171, 2), - 'minecraft:light_blue_carpet': (171, 3), - 'minecraft:yellow_carpet': (171, 4), - 'minecraft:lime_carpet': (171, 5), - 'minecraft:pink_carpet': (171, 6), - 'minecraft:gray_carpet': (171, 7), - 'minecraft:light_gray_carpet': (171, 8), - 'minecraft:cyan_carpet': (171, 9), - 'minecraft:purple_carpet': (171, 10), - 'minecraft:blue_carpet': (171, 11), - 'minecraft:brown_carpet': (171, 12), - 'minecraft:green_carpet': (171, 13), - 'minecraft:red_carpet': (171, 14), - 'minecraft:black_carpet': (171, 15), - 'minecraft:moss_carpet': (171, 16), 'minecraft:sunflower': (175, 0), 'minecraft:lilac': (175, 1), 'minecraft:tall_grass': (175, 2), @@ -673,7 +655,6 @@ def __init__(self, regiondir, rel): 'minecraft:soul_fire': (1040, 0), # 1.17 blocks go here - 'minecraft:budding_amethyst': (1045, 0), 'minecraft:waxed_copper_block': (1050, 0), 'minecraft:waxed_exposed_copper': (1051, 0), 'minecraft:waxed_weathered_copper': (1052, 0), @@ -911,8 +892,8 @@ def _get_block(self, palette_entry): 'minecraft:blackstone_slab','minecraft:polished_blackstone_slab', 'minecraft:polished_blackstone_brick_slab', 'minecraft:cobbled_deepslate_slab', 'minecraft:polished_deepslate_slab', 'minecraft:deepslate_brick_slab', - 'minecraft:deepslate_tile_slab', 'minecraft:mud_brick_slab' - ) + 'minecraft:deepslate_tile_slab', 'minecraft:mud_brick_slab', + 'minecraft:mangrove_slab' ) prismarine_slabs = ('minecraft:prismarine_slab','minecraft:dark_prismarine_slab','minecraft:prismarine_brick_slab') copper_slabs = ( @@ -925,7 +906,6 @@ def _get_block(self, palette_entry): 'minecraft:waxed_weathered_cut_copper_slab', 'minecraft:waxed_oxidized_cut_copper_slab' ) - unbound_slabs = ('minecraft:mangrove_slab',) # Map from slab to double slab block slab_to_double = { @@ -1026,9 +1006,11 @@ def _get_block(self, palette_entry): elif key in ('minecraft:sunflower', 'minecraft:lilac', 'minecraft:tall_grass', 'minecraft:large_fern', 'minecraft:rose_bush', 'minecraft:peony'): if palette_entry['Properties']['half'] == 'upper': data |= 0x08 - elif key.endswith('_slab') and palette_entry['Properties']['type'] == 'top': - (block, data) = modelblocks[key+'_top'] - elif key in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs + unbound_slabs: + # handle unknown slabs. The lighting on these will suck. + elif key.endswith('_slab') and palette_entry['Properties']['type'] == 'top' and key not in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs: + if key+'_top' in modelblocks: + (block, data) = modelblocks[key+'_top'] + elif key in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs: # handle double slabs if palette_entry['Properties']['type'] == 'top': data |= 0x08 @@ -1040,6 +1022,10 @@ def _get_block(self, palette_entry): (block, data) = self._blockmap[slab_to_double[key]] else: (block, data) = modelblocks[slab_to_double[key]] + else: + if key+'_top' in modelblocks: + # unknown slabs render as top if full is unknown + (block, data) = modelblocks[key+'_top'] elif key in ['minecraft:ladder', 'minecraft:chest', 'minecraft:ender_chest', 'minecraft:trapped_chest', 'minecraft:furnace', @@ -1246,7 +1232,7 @@ def _get_block(self, palette_entry): data = {'tip': 0, 'tip_merge': 1, 'middle': 2, 'frustum': 3, 'base': 4}[p['thickness']] data |= {'up': 0, 'down': 0b1000}[p['vertical_direction']] elif key in ['minecraft:small_amethyst_bud', 'minecraft:medium_amethyst_bud', 'minecraft:large_amethyst_bud', - 'minecraft:lightning_rod']: + 'minecraft:lightning_rod', 'minecraft:hopper']: p = palette_entry['Properties'] data = {'down': 0, 'up': 1, 'east': 2, 'south': 3, 'west': 4, 'north': 5}[p['facing']] elif key in ['minecraft:cave_vines_plant', 'minecraft:cave_vines']: From ebdeefb0b6fc43068a8e537fb84c36900ab42cf1 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Mon, 11 Jul 2022 19:09:03 +0200 Subject: [PATCH 22/34] slabs and minor fixes --- overviewer_core/textures.py | 82 ++++++++++++++++++++++++++++--------- overviewer_core/world.py | 10 ++++- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 4473a97f6..e552654bf 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -41,7 +41,7 @@ used_datas = set() max_blockid = 0 max_data = 0 -next_unclaimed_id = 1 +next_unclaimed_id = 2048 transparent_blocks = set() solid_blocks = set() @@ -894,6 +894,9 @@ def load_model(self, modelname): # fix known inconsistencies in model info def normalize_model(self, modelname): match modelname: + case 'block/observer': + self.models[modelname] = deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['up']['uv'] = [0, 0, 16, 16] # remap textures of blocks with the rotation property to match the mapping of the observer textures case 'block/loom': self.models[modelname] = deepcopy(self.models[modelname]) @@ -928,27 +931,20 @@ def build_block_from_model(self, modelname, blockstate={}): for elem in colmodel['elements']: try: if 'west' in elem['faces']: - texture = self.draw_face('west', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (12, 6), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'west') elif 'east' in elem['faces']: - texture = self.draw_face('east', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0, 0), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'east') if 'north' in elem['faces']: - texture = self.draw_face('north', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0, 6), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'north') elif 'south' in elem['faces']: - texture = self.draw_face('south', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (12, 0), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'south') if 'up' in elem['faces']: - texture = self.draw_face('up', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0, 0), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'up') elif 'down' in elem['faces']: - texture = self.draw_face('down', elem, colmodel, blockstate, modelname) - alpha_over(img, texture, (0, 12), texture) + self.draw_block(img, elem, colmodel, blockstate, modelname, 'down') except KeyError: - # element has an invalid texture; skipping entire element continue # Manually touch up 6 pixels that leave a gap because of how the @@ -962,6 +958,37 @@ def build_block_from_model(self, modelname, blockstate={}): return img + def draw_block(self, img, elem, colmodel, blockstate, modelname, direction): + if 'facing' in blockstate: + facing = self.map_facing_to_real(blockstate['facing'], direction) + else: + facing = 'north' + texture = self.draw_face(direction, elem, colmodel, blockstate, modelname) + alpha_over(img, texture, self.image_pos(direction, elem, facing), texture) + + def image_pos(self, direction, element, facing): + + # TODO: deal with uv, from, to + match direction: + + case 'west': return (12, 6) + case 'east': return (0, 0) + case 'north': return(0, 6) + case 'south': return (12, 0) + # # move up + case 'down': + fromy = 12 + if 'from' in element: + fromy = int(math.ceil(((16 - element['from'][1])/16*12.))) + return (0, fromy) # 0,0 + + # # move down + case 'up' | _: + toy = 0 + if 'to' in element: + toy = int(math.ceil(((16 - element['to'][1])/16*12.))) + return (0, toy) # 0,6 + def numvalue_orientation(self, orientation): return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4, 'down': 6}[orientation] @@ -1027,6 +1054,17 @@ def draw_face(self, direction, elem, data, blockstate, modelname): texture = self.find_texture_from_model( elem['faces'][textureface]['texture'], data['textures']).copy() + + if 'uv' in elem['faces'][textureface]: + if 'facing' in blockstate and textureface in {'up','down'}: + texture = texture.rotate(90) + uvface = {'north':'east','east':'south','south':'west','west':'north','up':'up','down':'down'}[textureface] + texture = self.crop_to_transparancy(texture, elem['faces'][uvface]['uv']) + if 'facing' in blockstate and textureface in {'up','down'}: + texture = texture.rotate(270) + + # TODO: deal with rotation + if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) @@ -1088,14 +1126,20 @@ def find_texture_from_model(self, face, textureset): # TODO: deal with uv, from, to def crop_to_transparancy(self, img, area): + if area == [ 0, 0, 16, 16 ]: + return img # top - ImageDraw.Draw(img).rectangle((area[2], 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + if area[2] != 0: + ImageDraw.Draw(img).rectangle((area[2]+1, 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # right - ImageDraw.Draw(img).rectangle((0, area[3], 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + if area[3] != 0: + ImageDraw.Draw(img).rectangle((0, area[3]+1, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # bottom - ImageDraw.Draw(img).rectangle((0, 0, area[0], 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + if area[0] != 16: + ImageDraw.Draw(img).rectangle((0, 0, area[0]-1, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # left - ImageDraw.Draw(img).rectangle((0, 0, 16, area[1]), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + if area[1] != 16: + ImageDraw.Draw(img).rectangle((0, 0, 16, area[1]-1), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) return img ## @@ -5277,8 +5321,6 @@ def hopper(self, blockid, data): solidmodelblock(blockid=169, name="sea_lantern") # hay block - - @material(blockid=170, data=list(range(3)), solid=True) def hayblock(self, blockid, data): return self.build_block_from_model('hay_block', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index ed16045ae..1826f9899 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -375,6 +375,7 @@ def __init__(self, regiondir, rel): 'minecraft:oak_stairs': (53, 0), 'minecraft:crimson_stairs': (509, 0), 'minecraft:warped_stairs': (510, 0), + 'minecraft:mangrove_stairs': (577, 0), 'minecraft:chest': (54, 0), 'minecraft:redstone_wire': (55, 0), 'minecraft:diamond_ore': (56, 0), @@ -924,6 +925,8 @@ def _get_block(self, palette_entry): 'minecraft:waxed_weathered_cut_copper_slab', 'minecraft:waxed_oxidized_cut_copper_slab' ) + unbound_slabs = ('minecraft:mangrove_slab',) + # Map from slab to double slab block slab_to_double = { 'minecraft:stone_slab': 'minecraft:stone', @@ -969,7 +972,8 @@ def _get_block(self, palette_entry): 'minecraft:prismarine_slab': 'minecraft:prismarine', 'minecraft:dark_prismarine_slab': 'minecraft:dark_prismarine', 'minecraft:prismarine_brick_slab': 'minecraft:prismarine_bricks', - } + 'minecraft:mangrove_slab': 'minecraft:mangrove_planks', + } colors = ['white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime', 'pink', 'gray', 'light_gray', 'cyan', 'purple', 'blue', 'brown', 'green', 'red', 'black'] @@ -1022,7 +1026,9 @@ def _get_block(self, palette_entry): elif key in ('minecraft:sunflower', 'minecraft:lilac', 'minecraft:tall_grass', 'minecraft:large_fern', 'minecraft:rose_bush', 'minecraft:peony'): if palette_entry['Properties']['half'] == 'upper': data |= 0x08 - elif key in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs: + elif key.endswith('_slab') and palette_entry['Properties']['type'] == 'top': + (block, data) = modelblocks[key+'_top'] + elif key in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs + unbound_slabs: # handle double slabs if palette_entry['Properties']['type'] == 'top': data |= 0x08 From 06b95a55dce46f1ba807ffd695a1f03868d76206 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Fri, 15 Jul 2022 18:31:55 +0200 Subject: [PATCH 23/34] process offset valies for north and west faces --- overviewer_core/textures.py | 201 ++++++++++++++++++++++++++---------- 1 file changed, 147 insertions(+), 54 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index e552654bf..50d90c6c0 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -931,20 +931,20 @@ def build_block_from_model(self, modelname, blockstate={}): for elem in colmodel['elements']: try: if 'west' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'west') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'west') elif 'east' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'east') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'east') if 'north' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'north') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'north') elif 'south' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'south') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'south') if 'up' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'up') + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'up') elif 'down' in elem['faces']: - self.draw_block(img, elem, colmodel, blockstate, modelname, 'down') - except KeyError: + self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'down') + except KeyError as e: continue # Manually touch up 6 pixels that leave a gap because of how the @@ -958,23 +958,71 @@ def build_block_from_model(self, modelname, blockstate={}): return img - def draw_block(self, img, elem, colmodel, blockstate, modelname, direction): + def draw_blockface(self, img, elem, colmodel, blockstate, modelname, direction): if 'facing' in blockstate: facing = self.map_facing_to_real(blockstate['facing'], direction) + elif 'axis' in blockstate: + facing = self.map_axis_to_real(blockstate['axis'], direction) else: - facing = 'north' - texture = self.draw_face(direction, elem, colmodel, blockstate, modelname) - alpha_over(img, texture, self.image_pos(direction, elem, facing), texture) + facing = direction + texture = self.build_texture(direction, elem, colmodel, blockstate, modelname, facing) + alpha_over(img, texture, self.image_pos(direction, elem, facing, modelname), texture) - def image_pos(self, direction, element, facing): + def image_pos(self, elementdirection, element, facing, modelname): - # TODO: deal with uv, from, to - match direction: + match elementdirection: - case 'west': return (12, 6) + # case 'west': return (12, 6) case 'east': return (0, 0) - case 'north': return(0, 6) + # case 'north': return(0, 6) case 'south': return (12, 0) + # case 'up': return (0, 0) + # case 'down': return (0, 12) + + # # 24x24 image + ## WIP + # Down and to the right + # 16 => 12,0 + # 0 => 6,6 + # case 'south': + # toxa = 12 + # tox = 0 + # # if 'to' in element: + # # toxa = int(math.ceil(6 + (6/16 * element[face[0]][face[1]]))) + # # tox = int(math.ceil(6 - (6/16 * element[face[0]][face[1]]))) + # return (toxa, tox) # 12,0 + + # # # # Up and to the right + # # # # 0 => 0,6 + # # # # 16 => 12,0 + case 'west': + setback = 16 - self.setback(element, facing) + + if modelname == 'block/anvil': + print('hit anvil west with ' + facing + ' and ' + str(setback)) + + toya = int(math.ceil(12/16 * (setback))) + toy = int(math.ceil(6/16 * (setback))) + return (toya, toy) # 12, 6 + + # Up and to the left + # 16 => 12,0 + # 0 => 0,6 + case 'north': + setback = self.setback(element, facing) + toya = int(math.ceil((12/16 * (setback)))) + toy = int(math.ceil(6 - (6/16 * (setback)))) + return (toya, toy) # 0, 6 + + # # # # Down and to the right + # # # # 0 => 0,0 + # # # # 16 => 6,6 + # case 'east': + # setback = self.setback(element, facing) + # toya = int(math.ceil(6/16 * (setback))) + # toy = int(math.ceil(6/16 * (setback))) + # return (toya, toy) # 0, 0 + # # move up case 'down': fromy = 12 @@ -989,6 +1037,12 @@ def image_pos(self, direction, element, facing): toy = int(math.ceil(((16 - element['to'][1])/16*12.))) return (0, toy) # 0,6 + def setback(self, element, facing): + return {'up': 16, 'down': 0, + 'north': element['from'][2], 'south': 16 - element['to'][2], + 'east': 16 - element['to'][0], 'west': element['from'][0]}[facing] + + def numvalue_orientation(self, orientation): return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4, 'down': 6}[orientation] @@ -1045,34 +1099,83 @@ def axis_rotation(self, axis, face, texture): case 'y' | _: return texture - def draw_face(self, direction, elem, data, blockstate, modelname): - textureface = direction - if 'facing' in blockstate: - textureface = self.map_facing_to_real(blockstate['facing'], direction) - if 'axis' in blockstate: - textureface = self.map_axis_to_real(blockstate['axis'], direction) + def build_texture(self, direction, elem, data, blockstate, modelname, textureface): texture = self.find_texture_from_model( elem['faces'][textureface]['texture'], data['textures']).copy() - if 'uv' in elem['faces'][textureface]: - if 'facing' in blockstate and textureface in {'up','down'}: - texture = texture.rotate(90) - uvface = {'north':'east','east':'south','south':'west','west':'north','up':'up','down':'down'}[textureface] - texture = self.crop_to_transparancy(texture, elem['faces'][uvface]['uv']) - if 'facing' in blockstate and textureface in {'up','down'}: - texture = texture.rotate(270) - - # TODO: deal with rotation - if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) + texture = self.texture_rotation(direction, texture, blockstate, elem['faces'][textureface], modelname) + + if 'from' in elem and 'to' in elem and (elem['from'] != [0,0,0] or elem['to'] != [16,16,16]): + area = [0,0,16,16] + + match textureface: + + case 'west': + area = [16-elem['from'][2],elem['from'][1],16-elem['to'][2],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + case 'east': + area = [elem['from'][2],elem['from'][1],elem['to'][2],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + case 'north': + area = [16-elem['from'][0],elem['from'][1],16-elem['to'][0],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + case 'south': + area = [elem['from'][0],elem['from'][1],elem['to'][0],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + case 'up'|'down'|_: + if 'facing' in blockstate and blockstate['facing'] in {'north'}: + area = [elem['from'][0],elem['from'][2],elem['to'][0],elem['to'][2]] + elif 'facing' in blockstate and blockstate['facing'] in {'south'}: + area = [16-elem['from'][0],16-elem['from'][2],16-elem['to'][0],16-elem['to'][2]] + elif 'facing' in blockstate and blockstate['facing'] in {'west'}: + area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] + elif 'facing' in blockstate and blockstate['facing'] in {'east'}: + area = [16-elem['from'][2],16-elem['from'][0],16-elem['to'][2],16-elem['to'][0]] + else: + area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] + texture = self.crop_to_transparancy(texture, area) + + # TODO: deal with rotation texture = self.transform_texture(direction, texture, blockstate, elem['faces'][textureface]) texture = self.adjust_lighting(direction, texture) return texture + def crop_to_transparancy(self, img, area): + # PIL image coordinates do not match MC texture coordinates + # PIL starts in lower left + # MC starts in upper left + # r, b, l, t + + if area[0] > area[2]: + area = [area[2], area[1], area[0], area[3]] + if area[1] > area[3]: + area = [area[0], area[3], area[2], area[1]] + if area == [ 0, 0, 16, 16 ]: + return img + + # cut from top + if area[3] != 16: + ImageDraw.Draw(img).rectangle((0, 0, 16, 16 - area[3]-1), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + + # cut from bottom + if area[1] != 0: + ImageDraw.Draw(img).rectangle((0, 16 - (area[1]-1), 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + + # cut from right + if area[2] != 16: + ImageDraw.Draw(img).rectangle((area[2]-1, 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + + # cut from left + if area[0] != 0: + ImageDraw.Draw(img).rectangle((0, 0, area[0]-1, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + + return img + def adjust_lighting(self, direction, texture): match direction: case 'south' | 'west': @@ -1088,7 +1191,7 @@ def adjust_lighting(self, direction, texture): case 'down' | 'up' | _: return texture - def transform_texture(self, direction, texture, blockstate, faceinfo): + def texture_rotation(self, direction, texture, blockstate, faceinfo, modelname): rotation = 0 if 'texturerotation' in faceinfo: rotation += faceinfo['texturerotation'] @@ -1100,20 +1203,28 @@ def transform_texture(self, direction, texture, blockstate, faceinfo): 90][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] else: rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] - return self.transform_image_top(texture.rotate(rotation)) case 'north' | 'south': if 'rotation' in faceinfo: rotation = {0: 180, 90: 90, 180: 0, 270: 270}[faceinfo['rotation']] if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: rotation += [90, 90][({'up': 0, 'down': 1}[blockstate['facing']])] - texture = self.transform_image_side(texture.rotate(rotation)) case 'west' | 'east': if 'rotation' in faceinfo: rotation = {0: 180, 90: 270, 180: 0, 270: 90}[faceinfo['rotation']] if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] + + return texture.rotate(rotation % 360) + + def transform_texture(self, direction, texture, blockstate, faceinfo): + match direction: + case 'down' | 'up': + return self.transform_image_top(texture) + case 'north' | 'south': + texture = self.transform_image_side(texture) + case 'west' | 'east': texture = texture.transpose(Image.FLIP_LEFT_RIGHT) - texture = self.transform_image_side(texture.rotate(rotation)) + texture = self.transform_image_side(texture) texture = texture.transpose(Image.FLIP_LEFT_RIGHT) return texture @@ -1124,24 +1235,6 @@ def find_texture_from_model(self, face, textureset): else: return self.load_image_texture("assets/minecraft/textures/" + re.sub('.*:', '', face) + '.png') - # TODO: deal with uv, from, to - def crop_to_transparancy(self, img, area): - if area == [ 0, 0, 16, 16 ]: - return img - # top - if area[2] != 0: - ImageDraw.Draw(img).rectangle((area[2]+1, 0, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - # right - if area[3] != 0: - ImageDraw.Draw(img).rectangle((0, area[3]+1, 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - # bottom - if area[0] != 16: - ImageDraw.Draw(img).rectangle((0, 0, area[0]-1, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - # left - if area[1] != 16: - ImageDraw.Draw(img).rectangle((0, 0, 16, area[1]-1), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - return img - ## ## The other big one: @material and associated framework ## From 79bc83d96ff1d1815325be7ec3c2a73014628198 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Sun, 17 Jul 2022 19:36:56 +0200 Subject: [PATCH 24/34] added mangrove slabs --- overviewer_core/src/block_class.c | 3 +- overviewer_core/src/mc_id.h | 7 +- overviewer_core/src/overviewer.h | 2 +- overviewer_core/textures.py | 299 ++++++++---------------------- overviewer_core/world.py | 40 ++-- 5 files changed, 98 insertions(+), 253 deletions(-) diff --git a/overviewer_core/src/block_class.c b/overviewer_core/src/block_class.c index 65f93ce4b..497602610 100644 --- a/overviewer_core/src/block_class.c +++ b/overviewer_core/src/block_class.c @@ -345,7 +345,8 @@ const mc_block_t block_class_alt_height[] = { block_polished_deepslate_slab, block_deepslate_brick_slab, block_deepslate_tile_slab, - block_mud_brick_slab}; + block_mud_brick_slab, + block_mangrove_slab}; const size_t block_class_alt_height_len = COUNT_OF(block_class_alt_height); const mc_block_t block_class_nether_roof[] = { diff --git a/overviewer_core/src/mc_id.h b/overviewer_core/src/mc_id.h index 1442f2139..2c034b972 100644 --- a/overviewer_core/src/mc_id.h +++ b/overviewer_core/src/mc_id.h @@ -118,7 +118,6 @@ enum mc_block_id { block_spruce_stairs = 134, block_birch_stairs = 135, block_jungle_stairs = 136, - block_beacon = 138, block_mushroom_stem = 139, block_flower_pot = 140, block_carrots = 141, @@ -147,9 +146,7 @@ enum mc_block_id { block_slime = 165, block_barrier = 166, block_iron_trapdoor = 167, - block_sea_lantern = 169, block_hay_block = 170, - block_carpet = 171, block_double_plant = 175, block_standing_banner = 176, block_wall_banner = 177, @@ -266,7 +263,6 @@ enum mc_block_id { block_soul_fire = 1040, // 1.17 - block_budding_amethyst = 1045, block_waxed_copper = 1050, block_waxed_exposed_copper = 1051, block_waxed_weathered_copper = 1052, @@ -334,6 +330,7 @@ enum mc_block_id { block_mud_brick_slab = 1124, block_mangrove_roots = 1125, block_mangrove_log = 1126, + block_mangrove_slab = 1789, // adding a gap in the numbering of walls to keep them all // in one numbering block starting at 1792 @@ -390,9 +387,7 @@ enum mc_block_id { block_smooth_quartz_slab = 11357, block_smooth_stone_slab = 11358, block_blast_furnace = 11362, - // block_blast_furnace lit 11363 block_smoker = 11364, - // block_smoker lit = 11365, block_lectern = 11366, block_loom = 11367, block_stonecutter = 11368, diff --git a/overviewer_core/src/overviewer.h b/overviewer_core/src/overviewer.h index 413cdb24c..3173bdf78 100644 --- a/overviewer_core/src/overviewer.h +++ b/overviewer_core/src/overviewer.h @@ -31,7 +31,7 @@ // increment this value if you've made a change to the c extension // and want to force users to rebuild -#define OVERVIEWER_EXTENSION_VERSION 113 +#define OVERVIEWER_EXTENSION_VERSION 114 #include #include diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 50d90c6c0..084c1374f 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -969,7 +969,7 @@ def draw_blockface(self, img, elem, colmodel, blockstate, modelname, direction): alpha_over(img, texture, self.image_pos(direction, elem, facing, modelname), texture) def image_pos(self, elementdirection, element, facing, modelname): - + match elementdirection: # case 'west': return (12, 6) @@ -997,10 +997,6 @@ def image_pos(self, elementdirection, element, facing, modelname): # # # # 16 => 12,0 case 'west': setback = 16 - self.setback(element, facing) - - if modelname == 'block/anvil': - print('hit anvil west with ' + facing + ' and ' + str(setback)) - toya = int(math.ceil(12/16 * (setback))) toy = int(math.ceil(6/16 * (setback))) return (toya, toy) # 12, 6 @@ -1042,7 +1038,6 @@ def setback(self, element, facing): 'north': element['from'][2], 'south': 16 - element['to'][2], 'east': 16 - element['to'][0], 'west': element['from'][0]}[facing] - def numvalue_orientation(self, orientation): return {'south': 0, 'west': 1, 'north': 2, 'east': 3, 'up': 4, 'down': 6}[orientation] @@ -1103,7 +1098,7 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac texture = self.find_texture_from_model( elem['faces'][textureface]['texture'], data['textures']).copy() - + if 'axis' in blockstate: texture = self.axis_rotation(blockstate['axis'], direction, texture) texture = self.texture_rotation(direction, texture, blockstate, elem['faces'][textureface], modelname) @@ -1114,10 +1109,10 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac match textureface: case 'west': - area = [16-elem['from'][2],elem['from'][1],16-elem['to'][2],elem['to'][1]] + area = [elem['from'][2],elem['from'][1],elem['to'][2],elem['to'][1]] texture = self.crop_to_transparancy(texture, area) case 'east': - area = [elem['from'][2],elem['from'][1],elem['to'][2],elem['to'][1]] + area = [16-elem['from'][2],elem['from'][1],16-elem['to'][2],elem['to'][1]] texture = self.crop_to_transparancy(texture, area) case 'north': area = [16-elem['from'][0],elem['from'][1],16-elem['to'][0],elem['to'][1]] @@ -1127,9 +1122,9 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac texture = self.crop_to_transparancy(texture, area) case 'up'|'down'|_: if 'facing' in blockstate and blockstate['facing'] in {'north'}: - area = [elem['from'][0],elem['from'][2],elem['to'][0],elem['to'][2]] + area = [elem['from'][0],16-elem['from'][2],elem['to'][0],16-elem['to'][2]] elif 'facing' in blockstate and blockstate['facing'] in {'south'}: - area = [16-elem['from'][0],16-elem['from'][2],16-elem['to'][0],16-elem['to'][2]] + area = [16-elem['from'][0],elem['from'][2],16-elem['to'][0],elem['to'][2]] elif 'facing' in blockstate and blockstate['facing'] in {'west'}: area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] elif 'facing' in blockstate and blockstate['facing'] in {'east'}: @@ -1137,7 +1132,7 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac else: area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] texture = self.crop_to_transparancy(texture, area) - + # TODO: deal with rotation texture = self.transform_texture(direction, texture, blockstate, elem['faces'][textureface]) @@ -1340,9 +1335,23 @@ def inner_billboard(self, unused_id, unused_data): def unbound_models(): global max_blockid, block_models, next_unclaimed_id + tex = Textures() - models = Textures.find_models(Textures()) + models = tex.find_models(tex) for model in models: + # determine transparency + + colmodel = tex.load_model('block/' + model) + if 'elements' not in colmodel: + continue + transp = False + + # for each elements + for elem in colmodel['elements']: + if 'from' in elem and 'to' in elem and (elem['from'] != [0,0,0] or elem['to'] != [16,16,16]): + transp = True + break + # find next unclaimed id to keep id values as low as possible while (next_unclaimed_id, 0) in blockmap_generators: next_unclaimed_id = next_unclaimed_id + 1 @@ -1350,7 +1359,7 @@ def unbound_models(): if next_unclaimed_id < 2048 and next_unclaimed_id > 1791: next_unclaimed_id = 2048 id = next_unclaimed_id - solidmodelblock(blockid=id, name=model) + modelblock(blockid=id, name=model, transparent=transp, solid=True) block_models['minecraft:' + model] = (id, 0) ## @@ -1594,6 +1603,10 @@ def sponge(self, blockid, data): # lapis lazuli block solidmodelblock(blockid=22, name="lapis_block") +@material(blockid=[577], data=list(range(8)), solid=True, transparent=True) +def modern_stairs(self, blockid, data): + facing = {3: 'north', 0: 'east', 2: 'south', 1: 'west' }[data%4] + return self.build_block_from_model('mangrove_stairs', {'facing': facing}) @material(blockid=[23, 158], data=list(range(6)), solid=True) def dropper(self, blockid, data): @@ -2024,10 +2037,10 @@ def flower(self, blockid, data): # 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, add prismarine slabs -@material(blockid=[43, 44, 181, 182, 204, 205, 1124] + list(range(11340, 11359)) + +@material(blockid=[43, 44, 181, 182, 204, 205, 1124, 1789] + list(range(11340, 11359)) + list(range(1027, 1030)) + list(range(1072, 1080)) + list(range(1103, 1107)), data=list(range(16)), - transparent=[44, 182, 205, 1124] + list(range(11340, 11359)) + list(range(1027, 1030)) + + transparent=[44, 182, 205, 1124, 1789] + list(range(11340, 11359)) + list(range(1027, 1030)) + list(range(1072, 1080)) + list(range(1103, 1107)), solid=True) def slabs(self, blockid, data): if blockid == 44 or blockid == 182: @@ -2146,11 +2159,13 @@ def slabs(self, blockid, data): top = side = self.load_image_texture(deepslate_tex[blockid]).copy() elif blockid == 1124: top = side = self.load_image_texture("assets/minecraft/textures/block/mud_bricks.png").copy() + elif blockid == 1789: + top = side = self.load_image_texture("assets/minecraft/textures/block/mangrove_planks.png").copy() if blockid == 43 or blockid == 181 or blockid == 204: # double slab return self.build_block(top, side) - return self.build_slab_block(top, side, data & 8 == 8); + return self.build_slab_block(top, side, data & 8 == 8) # TNT solidmodelblock(blockid=46, name="tnt", nospawn=True) @@ -4453,6 +4468,26 @@ def build_torch(active): # the trapdoor is looks like a sprite when opened, that's not good @material(blockid=[96,167,451,11332,11333,11334,11335,11336,12501,12502], data=list(range(16)), transparent=True, nospawn=True) def trapdoor(self, blockid, data): + + # texture generation + model_map = {96:"oak_trapdoor", + 167:"iron_trapdoor", + 451:"mangrove_trapdoor", + 11332:"spruce_trapdoor", + 11333:"birch_trapdoor", + 11334:"jungle_trapdoor", + 11335:"acacia_trapdoor", + 11336:"dark_oak_trapdoor", + 12501:"crimson_trapdoor", + 12502:"warped_trapdoor", + } + facing = {0: 'north', 1: 'south', 2: 'west', 3: 'east'}[data % 4] + + if data & 0x4 == 0x4: # off + return self.build_block_from_model("%s_open" % model_map[blockid], {'facing': facing}) + if data & 0x8 == 0x8: # off + return self.build_block_from_model("%s_top" % model_map[blockid] ) + return self.build_block_from_model("%s_bottom" % model_map[blockid]) # rotation # Masked to not clobber opened/closed info @@ -4831,15 +4866,10 @@ def nether_wart(self, blockid, data): return img # enchantment table -# TODO there's no book at the moment +# there's no book at the moment because it is not a part of the model @material(blockid=116, transparent=True) def enchantment_table(self, blockid, data): - # no book at the moment - top = self.load_image_texture("assets/minecraft/textures/block/enchanting_table_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/enchanting_table_side.png") - img = self.build_full_block((top, 4), None, None, side, side) - - return img + return self.build_block_from_model('enchanting_table') # brewing stand # TODO this is a place holder, is a 2d image pasted @@ -4895,7 +4925,7 @@ def end_portal(self, blockid, data): return self.build_block(t, t) t = self.transform_image_top(t) - alpha_over(img, t, (0,0), t) + alpha_over(img, t, (0,6), t) return img @@ -4903,33 +4933,13 @@ def end_portal(self, blockid, data): # end portal frame (data range 8 to get all orientations of filled) @material(blockid=120, data=list(range(8)), transparent=True, solid=True, nospawn=True) def end_portal_frame(self, blockid, data): - # Do rotation, only seems to affect ender eye & top of frame - data = data & 0b100 | ((self.rotation + (data & 0b11)) % 4) - - top = self.load_image_texture("assets/minecraft/textures/block/end_portal_frame_top.png").copy() - top = top.rotate((data % 4) * 90) - side = self.load_image_texture("assets/minecraft/textures/block/end_portal_frame_side.png") - img = self.build_full_block((top, 4), None, None, side, side) - if data & 0x4 == 0x4: # ender eye on it - # generate the eye - eye_t = self.load_image_texture("assets/minecraft/textures/block/end_portal_frame_eye.png").copy() - eye_t_s = eye_t.copy() - # cut out from the texture the side and the top of the eye - ImageDraw.Draw(eye_t).rectangle((0, 0, 15, 4), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(eye_t_s).rectangle((0, 4, 15, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - # transform images and paste - eye = self.transform_image_top(eye_t.rotate((data % 4) * 90)) - eye_s = self.transform_image_side(eye_t_s) - eye_os = eye_s.transpose(Image.FLIP_LEFT_RIGHT) - alpha_over(img, eye_s, (5, 5), eye_s) - alpha_over(img, eye_os, (9, 5), eye_os) - alpha_over(img, eye, (0, 0), eye) - - return img + facing = {2: 'north', 0: 'south', 1: 'west', 3: 'east'}[data % 4] + if data & 0x4 == 0x4: + return self.build_block_from_model('end_portal_frame_filled', {'facing': facing}) + return self.build_block_from_model('end_portal_frame', {'facing': facing}) # dragon egg -# NOTE: this isn't a block, but I think it's better than nothing transparentmodelblock(blockid=122, name="dragon_egg") @@ -4943,34 +4953,9 @@ def redstone_lamp(self, blockid, data): @material(blockid=[151,178], transparent=True) def daylight_sensor(self, blockid, data): if blockid == 151: # daylight sensor - top = self.load_image_texture("assets/minecraft/textures/block/daylight_detector_top.png") + return self.build_block_from_model('daylight_detector') else: # inverted daylight sensor - top = self.load_image_texture("assets/minecraft/textures/block/daylight_detector_inverted_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/daylight_detector_side.png") - - # 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) - - img = Image.new("RGBA", (24,24), self.bgcolor) - alpha_over(img, side, (0,12), side) - alpha_over(img, otherside, (12,12), otherside) - alpha_over(img, top, (0,6), top) - - return img + return self.build_block_from_model('daylight_detector_inverted') # wooden double and normal slabs @@ -5088,29 +5073,6 @@ def cocoa_plant(self, blockid, data): return img -# beacon block -# at the moment of writing this, it seems the beacon block doens't use -# the data values -@material(blockid=138, transparent=True) -def beacon(self, blockid, data): - # generate the three pieces of the block - t = self.load_image_texture("assets/minecraft/textures/block/glass.png") - glass = self.build_block(t,t) - t = self.load_image_texture("assets/minecraft/textures/block/obsidian.png") - obsidian = self.build_full_block((t,12),None, None, t, t) - obsidian = obsidian.resize((20,20), Image.ANTIALIAS) - t = self.load_image_texture("assets/minecraft/textures/block/beacon.png") - crystal = self.build_block(t,t) - crystal = crystal.resize((16,16),Image.ANTIALIAS) - - # compose the block - img = Image.new("RGBA", (24,24), self.bgcolor) - alpha_over(img, obsidian, (2, 4), obsidian) - alpha_over(img, crystal, (4,3), crystal) - alpha_over(img, glass, (0,0), glass) - - return img - # cobblestone and mossy cobblestone walls, chorus plants, mossy stone brick walls # one additional bit of data value added for mossy and cobblestone @material(blockid=[199]+list(range(1792, 1813 + 1)), data=list(range(32)), transparent=True, nospawn=True) @@ -5286,106 +5248,35 @@ def crops4(self, blockid, data): return img -# anvils @material(blockid=145, data=list(range(12)), transparent=True, nospawn=True) def anvil(self, blockid, data): - # anvils only have two orientations, invert it for rotations 1 and 3 - orientation = data & 0x1 - if self.rotation in (1, 3): - if orientation == 1: - orientation = 0 - else: - orientation = 1 - - # get the correct textures - # the bits 0x4 and 0x8 determine how damaged is the anvil + facing = {2: 'north', 0: 'south', 1: 'west', 3: 'east'}[data % 4] if (data & 0xc) == 0: # non damaged anvil - # return self.build_block_from_model('anvil') - top = self.load_image_texture("assets/minecraft/textures/block/anvil_top.png") + return self.build_block_from_model('anvil', {'facing': facing}) elif (data & 0xc) == 0x4: # slightly damaged - top = self.load_image_texture("assets/minecraft/textures/block/chipped_anvil_top.png") + return self.build_block_from_model('chipped_anvil', {'facing': facing}) elif (data & 0xc) == 0x8: # very damaged - top = self.load_image_texture("assets/minecraft/textures/block/damaged_anvil_top.png") - # everything else use this texture - big_side = self.load_image_texture("assets/minecraft/textures/block/anvil.png").copy() - small_side = self.load_image_texture("assets/minecraft/textures/block/anvil.png").copy() - base = self.load_image_texture("assets/minecraft/textures/block/anvil.png").copy() - small_base = self.load_image_texture("assets/minecraft/textures/block/anvil.png").copy() - - # cut needed patterns - ImageDraw.Draw(big_side).rectangle((0, 8, 15, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(small_side).rectangle((0, 0, 2, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(small_side).rectangle((13, 0, 15, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(small_side).rectangle((0, 8, 15, 15), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) - ImageDraw.Draw(base).rectangle((0, 0, 15, 15), outline=(0, 0, 0, 0)) - ImageDraw.Draw(base).rectangle((1, 1, 14, 14), outline=(0, 0, 0, 0)) - ImageDraw.Draw(small_base).rectangle((0, 0, 15, 15), outline=(0, 0, 0, 0)) - ImageDraw.Draw(small_base).rectangle((1, 1, 14, 14), outline=(0, 0, 0, 0)) - ImageDraw.Draw(small_base).rectangle((2, 2, 13, 13), outline=(0, 0, 0, 0)) - ImageDraw.Draw(small_base).rectangle((3, 3, 12, 12), outline=(0, 0, 0, 0)) - - # check orientation and compose the anvil - if orientation == 1: # bottom-left top-right - top = top.rotate(90) - left_side = small_side - left_pos = (1, 6) - right_side = big_side - right_pos = (10, 5) - else: # top-left bottom-right - right_side = small_side - right_pos = (12, 6) - left_side = big_side - left_pos = (3, 5) - - img = Image.new("RGBA", (24, 24), self.bgcolor) - - # darken sides - alpha = big_side.split()[3] - big_side = ImageEnhance.Brightness(big_side).enhance(0.8) - big_side.putalpha(alpha) - alpha = small_side.split()[3] - small_side = ImageEnhance.Brightness(small_side).enhance(0.9) - small_side.putalpha(alpha) - alpha = base.split()[3] - base_d = ImageEnhance.Brightness(base).enhance(0.8) - base_d.putalpha(alpha) - - # compose - base = self.transform_image_top(base) - base_d = self.transform_image_top(base_d) - small_base = self.transform_image_top(small_base) - top = self.transform_image_top(top) - - alpha_over(img, base_d, (0, 12), base_d) - alpha_over(img, base_d, (0, 11), base_d) - alpha_over(img, base_d, (0, 10), base_d) - alpha_over(img, small_base, (0, 10), small_base) - - alpha_over(img, top, (0, 1), top) # Fix gap between block edges - alpha_over(img, top, (0, 0), top) - - left_side = self.transform_image_side(left_side) - right_side = self.transform_image_side(right_side).transpose(Image.FLIP_LEFT_RIGHT) - - alpha_over(img, left_side, left_pos, left_side) - alpha_over(img, right_side, right_pos, right_side) - - return img + return self.build_block_from_model('damaged_anvil', {'facing': facing}) # mineral overlay # nether quartz ore solidmodelblock(blockid=153, name="nether_quartz_ore") # block of quartz - - @material(blockid=155, data=list(range(3)), solid=True) def quartz_pillar(self, blockid, data): return self.build_block_from_model('quartz_pillar', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) # hopper -@material(blockid=154, data=list(range(4)), transparent=True) +@material(blockid=154, data=list(range(6)), transparent=True) def hopper(self, blockid, data): + # # TODO: + # facing = {0: 'down', 1: 'up', 2: 'east', 3: 'south', 4: 'west', 5: 'north'}[data] + # if facing == 'down': + # return self.build_block_from_model('hopper', {'facing': facing}) + # return self.build_block_from_model('hopper_side', {'facing': facing}) + + #build the top side = self.load_image_texture("assets/minecraft/textures/block/hopper_outside.png") top = self.load_image_texture("assets/minecraft/textures/block/hopper_top.png") @@ -5410,25 +5301,11 @@ def hopper(self, blockid, data): # slime block transparentmodelblock(blockid=165, name="slime_block") -# sea lantern -solidmodelblock(blockid=169, name="sea_lantern") - # hay block @material(blockid=170, data=list(range(3)), solid=True) def hayblock(self, blockid, data): return self.build_block_from_model('hay_block', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) -# carpet - wool block that's small? -@material(blockid=171, data=list(range(17)), transparent=True) -def carpet(self, blockid, data): - if data < 16: - texture = self.load_image_texture("assets/minecraft/textures/block/%s_wool.png" % color_map[data]) - elif data == 16: - texture = self.load_image_texture("assets/minecraft/textures/block/moss_block.png") - - return self.build_full_block((texture,15),texture,texture,texture,texture) - - @material(blockid=175, data=list(range(16)), transparent=True) def flower(self, blockid, data): double_plant_map = ["sunflower", "lilac", "tall_grass", "large_fern", "rose_bush", "peony", "peony", "peony"] @@ -5462,15 +5339,11 @@ def chorus_flower(self, blockid, data): return self.build_block(texture,texture) # purpur pillar - - @material(blockid=202, data=list(range(3)), solid=True) def purpur_pillar(self, blockid, data): return self.build_block_from_model('purpur_pillar', blockstate={'axis': ({0: 'y', 1: 'x', 2: 'z'}[data])}) # frosted ice - - @material(blockid=212, data=list(range(4)), solid=True) def frosted_ice(self, blockid, data): return self.build_block_from_model("frosted_ice_%d" % data) @@ -5481,8 +5354,6 @@ def boneblock(self, blockid, data): return self.build_block_from_model('bone_block', blockstate={'axis': ({0: 'y', 4: 'x', 8: 'z'}[data & 12])}) # observer - - @material(blockid=218, data=[0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13], solid=True, nospawn=True) def observer(self, blockid, data): facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data & 0b0111] @@ -5584,8 +5455,6 @@ def glazed_terracotta(self, blockid, data): return self.build_block_from_model("%s_glazed_terracotta" % color_map[blockid - 235], {'facing': facing}) # scaffolding - - @material(blockid=[11414], data=list(range(2)), solid=False, transparent=True) def scaffolding(self, blockid, data): top = self.load_image_texture("assets/minecraft/textures/block/scaffolding_top.png") @@ -5594,8 +5463,6 @@ def scaffolding(self, blockid, data): return img # beehive and bee_nest - - @material(blockid=[11501, 11502], data=list(range(8)), solid=True) def beehivenest(self, blockid, data): facing = {0: 'south', 1: 'west', 2: 'north', 3: 'east'}[data % 4] @@ -5613,11 +5480,8 @@ def beehivenest(self, blockid, data): transparentmodelblock(blockid=11504, name="honey_block") # Barrel - - @material(blockid=11418, data=list(range(12)), solid=True) def barrel(self, blockid, data): - facing = {0: 'up', 1: 'down', 2: 'south', 3: 'east', 4: 'north', 5: 'west'}[data >> 1] if data & 0x01: @@ -5625,8 +5489,6 @@ def barrel(self, blockid, data): return self.build_block_from_model('barrel', {'facing': facing}) # Campfire (11506) and soul campfire (1003) - - @material(blockid=[11506, 1003], data=list(range(8)), solid=True, transparent=True, nospawn=True) def campfire(self, blockid, data): # Do rotation, mask to not clobber lit data @@ -5860,8 +5722,6 @@ def create_tile(img_src, coord_crop, coord_paste, rot): solidmodelblock(blockid=[1000], name="ancient_debris") # Basalt - - @material(blockid=[1001, 1002], data=list(range(3)), solid=True) def basalt(self, blockid, data): axis = {0: 'y', 1: 'x', 2: 'z'}[data] @@ -5922,8 +5782,6 @@ def respawn_anchor(self, blockid, data): # nether gold ore solidmodelblock(blockid=1021, name="nether_gold_ore") -solidmodelblock(blockid=1045, name="budding_amethyst") - # waxed copper solidmodelblock(blockid=[1050], name="copper_block") solidmodelblock(blockid=[1051], name="exposed_copper") @@ -5935,11 +5793,10 @@ def respawn_anchor(self, blockid, data): solidmodelblock(blockid=[1060], name="weathered_cut_copper") solidmodelblock(blockid=[1061], name="oxidized_cut_copper") +# mineral overlay solidmodelblock(blockid=1063, name="copper_ore") # deepslate - - @material(blockid=1083, data=list(range(3)), solid=True) def deepslate(self, blockid, data): return self.build_block_from_model('deepslate', {'axis': {0: 'y', 1: 'x', 2: 'z'}[data]}) @@ -6062,9 +5919,15 @@ def cave_vines(self, blockid, data): tex = self.load_image_texture("assets/minecraft/textures/block/cave_vines.png") return self.build_sprite(tex) - @material(blockid=1118, data=list(range(6)), transparent=True, solid=True) def lightning_rod(self, blockid, data): + + # lignting rod default model is for facing 'up' + # TODO: for generic processing the texture requires uv handling + + # facing = {0: 'down', 1: 'up', 2: 'east', 3: 'south', 4: 'west', 5: 'north'}[data] + # return self.build_block_from_model('lightning_rod', {'facing': 'north'}) + tex = self.load_image_texture("assets/minecraft/textures/block/lightning_rod.png") img = Image.new("RGBA", (24, 24), self.bgcolor) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 1826f9899..761045d51 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -465,6 +465,7 @@ def __init__(self, regiondir, rel): 'minecraft:dark_oak_slab': (126, 5), 'minecraft:crimson_slab': (126, 6), 'minecraft:warped_slab': (126, 7), + 'minecraft:mangrove_slab': (1789, 0), 'minecraft:cocoa': (127, 0), 'minecraft:sandstone_stairs': (128, 0), 'minecraft:emerald_ore': (129, 0), @@ -474,7 +475,6 @@ def __init__(self, regiondir, rel): 'minecraft:spruce_stairs': (134, 0), 'minecraft:birch_stairs': (135, 0), 'minecraft:jungle_stairs': (136, 0), - 'minecraft:beacon': (138, 0), 'minecraft:mushroom_stem': (139, 0), 'minecraft:flower_pot': (140, 0), 'minecraft:potted_poppy': (140, 0), # Pots not rendering @@ -528,25 +528,7 @@ def __init__(self, regiondir, rel): 'minecraft:dark_oak_stairs': (164, 0), 'minecraft:slime_block': (165,0), 'minecraft:iron_trapdoor': (167, 0), - 'minecraft:sea_lantern': (169, 0), 'minecraft:hay_block': (170, 0), - 'minecraft:white_carpet': (171, 0), - 'minecraft:orange_carpet': (171, 1), - 'minecraft:magenta_carpet': (171, 2), - 'minecraft:light_blue_carpet': (171, 3), - 'minecraft:yellow_carpet': (171, 4), - 'minecraft:lime_carpet': (171, 5), - 'minecraft:pink_carpet': (171, 6), - 'minecraft:gray_carpet': (171, 7), - 'minecraft:light_gray_carpet': (171, 8), - 'minecraft:cyan_carpet': (171, 9), - 'minecraft:purple_carpet': (171, 10), - 'minecraft:blue_carpet': (171, 11), - 'minecraft:brown_carpet': (171, 12), - 'minecraft:green_carpet': (171, 13), - 'minecraft:red_carpet': (171, 14), - 'minecraft:black_carpet': (171, 15), - 'minecraft:moss_carpet': (171, 16), 'minecraft:sunflower': (175, 0), 'minecraft:lilac': (175, 1), 'minecraft:tall_grass': (175, 2), @@ -673,7 +655,6 @@ def __init__(self, regiondir, rel): 'minecraft:soul_fire': (1040, 0), # 1.17 blocks go here - 'minecraft:budding_amethyst': (1045, 0), 'minecraft:waxed_copper_block': (1050, 0), 'minecraft:waxed_exposed_copper': (1051, 0), 'minecraft:waxed_weathered_copper': (1052, 0), @@ -911,8 +892,8 @@ def _get_block(self, palette_entry): 'minecraft:blackstone_slab','minecraft:polished_blackstone_slab', 'minecraft:polished_blackstone_brick_slab', 'minecraft:cobbled_deepslate_slab', 'minecraft:polished_deepslate_slab', 'minecraft:deepslate_brick_slab', - 'minecraft:deepslate_tile_slab', 'minecraft:mud_brick_slab' - ) + 'minecraft:deepslate_tile_slab', 'minecraft:mud_brick_slab', + 'minecraft:mangrove_slab' ) prismarine_slabs = ('minecraft:prismarine_slab','minecraft:dark_prismarine_slab','minecraft:prismarine_brick_slab') copper_slabs = ( @@ -925,7 +906,6 @@ def _get_block(self, palette_entry): 'minecraft:waxed_weathered_cut_copper_slab', 'minecraft:waxed_oxidized_cut_copper_slab' ) - unbound_slabs = ('minecraft:mangrove_slab',) # Map from slab to double slab block slab_to_double = { @@ -1026,9 +1006,11 @@ def _get_block(self, palette_entry): elif key in ('minecraft:sunflower', 'minecraft:lilac', 'minecraft:tall_grass', 'minecraft:large_fern', 'minecraft:rose_bush', 'minecraft:peony'): if palette_entry['Properties']['half'] == 'upper': data |= 0x08 - elif key.endswith('_slab') and palette_entry['Properties']['type'] == 'top': - (block, data) = modelblocks[key+'_top'] - elif key in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs + unbound_slabs: + # handle unknown slabs. The lighting on these will suck. + elif key.endswith('_slab') and palette_entry['Properties']['type'] == 'top' and key not in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs: + if key+'_top' in modelblocks: + (block, data) = modelblocks[key+'_top'] + elif key in wood_slabs + stone_slabs + prismarine_slabs + copper_slabs: # handle double slabs if palette_entry['Properties']['type'] == 'top': data |= 0x08 @@ -1040,6 +1022,10 @@ def _get_block(self, palette_entry): (block, data) = self._blockmap[slab_to_double[key]] else: (block, data) = modelblocks[slab_to_double[key]] + else: + if key+'_top' in modelblocks: + # unknown slabs render as top if full is unknown + (block, data) = modelblocks[key+'_top'] elif key in ['minecraft:ladder', 'minecraft:chest', 'minecraft:ender_chest', 'minecraft:trapped_chest', 'minecraft:furnace', @@ -1246,7 +1232,7 @@ def _get_block(self, palette_entry): data = {'tip': 0, 'tip_merge': 1, 'middle': 2, 'frustum': 3, 'base': 4}[p['thickness']] data |= {'up': 0, 'down': 0b1000}[p['vertical_direction']] elif key in ['minecraft:small_amethyst_bud', 'minecraft:medium_amethyst_bud', 'minecraft:large_amethyst_bud', - 'minecraft:lightning_rod']: + 'minecraft:lightning_rod', 'minecraft:hopper']: p = palette_entry['Properties'] data = {'down': 0, 'up': 1, 'east': 2, 'south': 3, 'west': 4, 'north': 5}[p['facing']] elif key in ['minecraft:cave_vines_plant', 'minecraft:cave_vines']: From 62a6c377e277dfa2baceb743d521c3b57d87e253 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Mon, 18 Jul 2022 12:34:53 +0200 Subject: [PATCH 25/34] element render order --- docs/contributing.rst | 5 +-- overviewer_core/src/mc_id.h | 4 --- overviewer_core/textures.py | 69 ++++++++----------------------------- overviewer_core/world.py | 4 --- 4 files changed, 17 insertions(+), 65 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 7592fff2d..bbbd493cc 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -207,9 +207,10 @@ Simple Solid 6-Sided Block Most blocks are simple full height solid blocks. These blocks are automatically picked up by the ``unbound_models()`` method from the minecraft assets. Sometimes these blocks have special properties that can not be picked up -from the assets, like transparency. These blocks can be added like this:: +from the assets, like nospawn, or because you want to include them in an overview. +These blocks can be added like this:: - transparentmodelblock(blockid=1125, name="mangrove_roots") + solidmodelblock(blockid=1125, name="mangrove_roots") Block with Variable Colors ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/overviewer_core/src/mc_id.h b/overviewer_core/src/mc_id.h index 2c034b972..d1d569677 100644 --- a/overviewer_core/src/mc_id.h +++ b/overviewer_core/src/mc_id.h @@ -105,7 +105,6 @@ enum mc_block_id { block_cauldron = 118, block_end_portal = 119, block_end_portal_frame = 120, - block_dragon_egg = 122, block_redstone_lamp = 123, block_double_wooden_slab = 125, block_wooden_slab = 126, @@ -143,7 +142,6 @@ enum mc_block_id { block_dark_oak_stairs = 164, block_crimson_stairs = 509, block_warped_stairs = 510, - block_slime = 165, block_barrier = 166, block_iron_trapdoor = 167, block_hay_block = 170, @@ -328,7 +326,6 @@ enum mc_block_id { block_spore_blossom = 1120, block_mud_brick_slab = 1124, - block_mangrove_roots = 1125, block_mangrove_log = 1126, block_mangrove_slab = 1789, @@ -435,7 +432,6 @@ enum mc_block_id { // 1.15 blocks below block_beehive = 11501, block_bee_nest = 11502, - block_honey_block = 11504, block_sweet_berry_bush = 11505, block_campfire = 11506, block_bell = 11507, diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 084c1374f..6e3838799 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -925,10 +925,13 @@ def build_block_from_model(self, modelname, blockstate={}): if 'elements' not in colmodel: return None + elements = colmodel['elements'] + elements.sort(key=lambda x: (x['to'][1], 16 - (x['from'][0]+x['to'][0]),16 - (x['from'][2]+x['to'][2]))) + img = Image.new("RGBA", (24, 24), self.bgcolor) # for each elements - for elem in colmodel['elements']: + for elem in elements: try: if 'west' in elem['faces']: self.draw_blockface(img, elem, colmodel, blockstate, modelname, 'west') @@ -1159,7 +1162,7 @@ def crop_to_transparancy(self, img, area): # cut from bottom if area[1] != 0: - ImageDraw.Draw(img).rectangle((0, 16 - (area[1]-1), 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + ImageDraw.Draw(img).rectangle((0, 16 - (area[1]-2), 16, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) # cut from right if area[2] != 16: @@ -1167,7 +1170,7 @@ def crop_to_transparancy(self, img, area): # cut from left if area[0] != 0: - ImageDraw.Draw(img).rectangle((0, 0, area[0]-1, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) + ImageDraw.Draw(img).rectangle((0, 0, area[0]-2, 16), outline=(0, 0, 0, 0), fill=(0, 0, 0, 0)) return img @@ -1285,12 +1288,6 @@ def func_wrapper(texobj, blockid, data): return inner_material -def transparentmodelblock(blockid=[], name=None, **kwargs): - new_kwargs = {'transparent': True} - new_kwargs.update(kwargs) - return modelblock(blockid=blockid, name=name, **new_kwargs) - - def solidmodelblock(blockid=[], name=None, **kwargs): new_kwargs = {'solid': True} new_kwargs.update(kwargs) @@ -1622,8 +1619,6 @@ def dropper(self, blockid, data): return self.build_block_from_model('dispenser', {'facing': facing}) # furnace, blast furnace, and smoker - - @material(blockid=[61, 11362, 11364], data=list(range(14)), solid=True) def furnaces(self, blockid, data): lit = data & 0b1000 == 8 @@ -2397,7 +2392,7 @@ def fire(self, blockid, data): return self.build_block_from_model('soul_fire_floor0') # monster spawner -transparentmodelblock(blockid=52, name="spawner") +modelblock(blockid=52, name="spawner", solid=True, transparent=True) # wooden, cobblestone, red brick, stone brick, netherbrick, sandstone, spruce, birch, # jungle, quartz, red sandstone, purpur_stairs, crimson_stairs, warped_stairs, (dark) prismarine, @@ -3144,17 +3139,7 @@ def create_tile(img_src, coord_crop, coord_paste, scale): # crops with 8 data values (like wheat) @material(blockid=59, data=list(range(8)), transparent=True, nospawn=True) def crops8(self, blockid, data): - raw_crop = self.load_image_texture("assets/minecraft/textures/block/wheat_stage%d.png" % data) - crop1 = self.transform_image_top(raw_crop) - crop2 = self.transform_image_side(raw_crop) - crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) - - img = Image.new("RGBA", (24,24), self.bgcolor) - alpha_over(img, crop1, (0,12), crop1) - alpha_over(img, crop2, (6,3), crop2) - alpha_over(img, crop3, (6,3), crop3) - return img - + return self.build_block_from_model("wheat_stage%d" % data) # farmland and grass path (15/16 blocks) @material(blockid=[60, 208], data=list(range(2)), solid=True, transparent=True, nospawn=True) @@ -4938,11 +4923,6 @@ def end_portal_frame(self, blockid, data): return self.build_block_from_model('end_portal_frame_filled', {'facing': facing}) return self.build_block_from_model('end_portal_frame', {'facing': facing}) - -# dragon egg -transparentmodelblock(blockid=122, name="dragon_egg") - - @material(blockid=[123], data=list(range(2)), solid=True) def redstone_lamp(self, blockid, data): if data == 0: # off @@ -5298,9 +5278,6 @@ def hopper(self, blockid, data): return img -# slime block -transparentmodelblock(blockid=165, name="slime_block") - # hay block @material(blockid=170, data=list(range(3)), solid=True) def hayblock(self, blockid, data): @@ -5332,11 +5309,9 @@ def flower(self, blockid, data): def chorus_flower(self, blockid, data): # aged 5, dead if data == 5: - texture = self.load_image_texture("assets/minecraft/textures/block/chorus_flower_dead.png") + return self.build_block_from_model("chorus_flower_dead") else: - texture = self.load_image_texture("assets/minecraft/textures/block/chorus_flower.png") - - return self.build_block(texture,texture) + return self.build_block_from_model("chorus_flower") # purpur pillar @material(blockid=202, data=list(range(3)), solid=True) @@ -5431,13 +5406,10 @@ def jigsaw_block(self, blockid, data): # beetroots(207), berry bushes (11505) @material(blockid=[207, 11505], data=list(range(4)), transparent=True, nospawn=True) def crops(self, blockid, data): - - crops_id_to_tex = { - 207: "assets/minecraft/textures/block/beetroots_stage%d.png", - 11505: "assets/minecraft/textures/block/sweet_berry_bush_stage%d.png", - } - - raw_crop = self.load_image_texture(crops_id_to_tex[blockid] % data) + if blockid == 207: + return self.build_block_from_model("beetroots_stage%d" % data) + else: + raw_crop = self.load_image_texture("assets/minecraft/textures/block/sweet_berry_bush_stage%d.png" % data) crop1 = self.transform_image_top(raw_crop) crop2 = self.transform_image_side(raw_crop) crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) @@ -5475,10 +5447,6 @@ def beehivenest(self, blockid, data): return self.build_block_from_model('bee_nest_honey', {'facing': facing}) return self.build_block_from_model('bee_nest', {'facing': facing}) - -# honey_block -transparentmodelblock(blockid=11504, name="honey_block") - # Barrel @material(blockid=11418, data=list(range(12)), solid=True) def barrel(self, blockid, data): @@ -5921,13 +5889,6 @@ def cave_vines(self, blockid, data): @material(blockid=1118, data=list(range(6)), transparent=True, solid=True) def lightning_rod(self, blockid, data): - - # lignting rod default model is for facing 'up' - # TODO: for generic processing the texture requires uv handling - - # facing = {0: 'down', 1: 'up', 2: 'east', 3: 'south', 4: 'west', 5: 'north'}[data] - # return self.build_block_from_model('lightning_rod', {'facing': 'north'}) - tex = self.load_image_texture("assets/minecraft/textures/block/lightning_rod.png") img = Image.new("RGBA", (24, 24), self.bgcolor) @@ -6114,8 +6075,6 @@ def spore_blossom(self, blockid, data): alpha_over(img, base_top, (0, 0), base_top) return img -transparentmodelblock(blockid=1125, name="mangrove_roots") - # Render all blocks not explicitly declared before # Must run last to prevent being hidden by blocks with fixed IDs unbound_models() diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 761045d51..89a108339 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -455,7 +455,6 @@ def __init__(self, regiondir, rel): 'minecraft:powder_snow_cauldron': (118, 3 << 2), 'minecraft:end_portal': (119, 0), 'minecraft:end_portal_frame': (120, 0), - 'minecraft:dragon_egg': (122, 0), 'minecraft:redstone_lamp': (123, 0), 'minecraft:oak_slab': (126, 0), 'minecraft:spruce_slab': (126, 1), @@ -526,7 +525,6 @@ def __init__(self, regiondir, rel): 'minecraft:dark_oak_log': (162, 1), 'minecraft:acacia_stairs': (163, 0), 'minecraft:dark_oak_stairs': (164, 0), - 'minecraft:slime_block': (165,0), 'minecraft:iron_trapdoor': (167, 0), 'minecraft:hay_block': (170, 0), 'minecraft:sunflower': (175, 0), @@ -715,7 +713,6 @@ def __init__(self, regiondir, rel): # 1.19 blocks 'minecraft:mud_brick_slab': (1124, 0), - 'minecraft:mangrove_roots': (1125, 0), 'minecraft:mangrove_log': (1126, 0), 'minecraft:stripped_mangrove_log': (1126, 1), @@ -822,7 +819,6 @@ def __init__(self, regiondir, rel): # 1.15 blocks below 'minecraft:beehive': (11501, 0), 'minecraft:bee_nest': (11502, 0), - 'minecraft:honey_block': (11504, 0), 'minecraft:sweet_berry_bush': (11505, 0), 'minecraft:campfire': (11506, 0), 'minecraft:bell': (11507, 0), From c84c3c4aa070fcf79ab0c1249287263e03bc46cf Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Sun, 17 Jul 2022 00:12:08 +0200 Subject: [PATCH 26/34] Revert "genpoi: ignore dat files with incomplete player info" This reverts commit 44ffb2658e504313e555ff03d97c155d2f1e084b. Breaks player handling in genpoi. --- overviewer_core/aux_files/genPOI.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/overviewer_core/aux_files/genPOI.py b/overviewer_core/aux_files/genPOI.py index d1f585cc0..3b761fdb4 100644 --- a/overviewer_core/aux_files/genPOI.py +++ b/overviewer_core/aux_files/genPOI.py @@ -331,9 +331,6 @@ def handlePlayers(worldpath, filters, markers): except (IOError, TypeError, KeyError, nbt.CorruptNBTError): logging.warning("Skipping bad player dat file %r.", playerfile) continue - if not "_name" in data: - logging.warning("Skipping bad player dat file %r (incomplete player info).", playerfile) - continue playername = playerfile.split(".")[0] if isSinglePlayer: From 576fb7b6aa46d1256cae69acbe2d1520199a8d20 Mon Sep 17 00:00:00 2001 From: Nicolas F Date: Sun, 17 Jul 2022 00:12:08 +0200 Subject: [PATCH 27/34] Revert "genpoi: ignore dat files with incomplete player info" This reverts commit 44ffb2658e504313e555ff03d97c155d2f1e084b. Breaks player handling in genpoi. --- overviewer_core/aux_files/genPOI.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/overviewer_core/aux_files/genPOI.py b/overviewer_core/aux_files/genPOI.py index d1f585cc0..3b761fdb4 100644 --- a/overviewer_core/aux_files/genPOI.py +++ b/overviewer_core/aux_files/genPOI.py @@ -331,9 +331,6 @@ def handlePlayers(worldpath, filters, markers): except (IOError, TypeError, KeyError, nbt.CorruptNBTError): logging.warning("Skipping bad player dat file %r.", playerfile) continue - if not "_name" in data: - logging.warning("Skipping bad player dat file %r (incomplete player info).", playerfile) - continue playername = playerfile.split(".")[0] if isSinglePlayer: From 4794e570fd5ece8be717d64215b7a1258d22b408 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Mon, 18 Jul 2022 16:29:46 +0200 Subject: [PATCH 28/34] removed WIP comments --- overviewer_core/src/block_class.c | 9 ++- overviewer_core/src/mc_id.h | 1 + overviewer_core/textures.py | 127 ++++++++---------------------- overviewer_core/world.py | 2 +- 4 files changed, 41 insertions(+), 98 deletions(-) diff --git a/overviewer_core/src/block_class.c b/overviewer_core/src/block_class.c index 497602610..97d11a381 100644 --- a/overviewer_core/src/block_class.c +++ b/overviewer_core/src/block_class.c @@ -150,7 +150,8 @@ const mc_block_t block_class_stair[] = { block_cobbled_deepslate_stairs, block_polished_deepslate_stairs, block_deepslate_brick_stairs, - block_deepslate_tile_stairs}; + block_deepslate_tile_stairs, + block_mangrove_stairs}; const size_t block_class_stair_len = COUNT_OF(block_class_stair); const mc_block_t block_class_door[] = { @@ -224,6 +225,7 @@ const mc_block_t block_class_ancil[] = { block_polished_deepslate_stairs, block_deepslate_brick_stairs, block_deepslate_tile_stairs, + block_mangrove_stairs, block_grass, block_flowing_water, block_water, @@ -294,7 +296,7 @@ const mc_block_t block_class_alt_height[] = { block_smooth_sandstone_stairs, block_blackstone_stairs, block_polished_blackstone_stairs, - block_polished_blackstone_brick_stairs, + block_polished_blackstone_brick_stairs, block_prismarine_slab, block_dark_prismarine_slab, block_prismarine_brick_slab, @@ -340,7 +342,8 @@ const mc_block_t block_class_alt_height[] = { block_cobbled_deepslate_stairs, block_polished_deepslate_stairs, block_deepslate_brick_stairs, - block_deepslate_tile_stairs, + block_deepslate_tile_stairs, + block_mangrove_stairs, block_cobbled_deepslate_slab, block_polished_deepslate_slab, block_deepslate_brick_slab, diff --git a/overviewer_core/src/mc_id.h b/overviewer_core/src/mc_id.h index d1d569677..6b41fec8d 100644 --- a/overviewer_core/src/mc_id.h +++ b/overviewer_core/src/mc_id.h @@ -307,6 +307,7 @@ enum mc_block_id { block_polished_deepslate_stairs = 1100, block_deepslate_brick_stairs = 1101, block_deepslate_tile_stairs = 1102, + block_mangrove_stairs = 1108, block_cobbled_deepslate_slab = 1103, block_polished_deepslate_slab = 1104, diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index fd1296434..de6ada9c3 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -975,66 +975,32 @@ def image_pos(self, elementdirection, element, facing, modelname): match elementdirection: - # case 'west': return (12, 6) case 'east': return (0, 0) - # case 'north': return(0, 6) case 'south': return (12, 0) - # case 'up': return (0, 0) - # case 'down': return (0, 12) - - # # 24x24 image - ## WIP - # Down and to the right - # 16 => 12,0 - # 0 => 6,6 - # case 'south': - # toxa = 12 - # tox = 0 - # # if 'to' in element: - # # toxa = int(math.ceil(6 + (6/16 * element[face[0]][face[1]]))) - # # tox = int(math.ceil(6 - (6/16 * element[face[0]][face[1]]))) - # return (toxa, tox) # 12,0 - - # # # # Up and to the right - # # # # 0 => 0,6 - # # # # 16 => 12,0 + case 'west': setback = 16 - self.setback(element, facing) toya = int(math.ceil(12/16 * (setback))) toy = int(math.ceil(6/16 * (setback))) - return (toya, toy) # 12, 6 - - # Up and to the left - # 16 => 12,0 - # 0 => 0,6 + return (toya, toy) + case 'north': setback = self.setback(element, facing) toya = int(math.ceil((12/16 * (setback)))) toy = int(math.ceil(6 - (6/16 * (setback)))) - return (toya, toy) # 0, 6 - - # # # # Down and to the right - # # # # 0 => 0,0 - # # # # 16 => 6,6 - # case 'east': - # setback = self.setback(element, facing) - # toya = int(math.ceil(6/16 * (setback))) - # toy = int(math.ceil(6/16 * (setback))) - # return (toya, toy) # 0, 0 - - # # move up + return (toya, toy) + case 'down': fromy = 12 if 'from' in element: fromy = int(math.ceil(((16 - element['from'][1])/16*12.))) - return (0, fromy) # 0,0 - - # # move down + return (0, fromy) + case 'up' | _: toy = 0 if 'to' in element: toy = int(math.ceil(((16 - element['to'][1])/16*12.))) - return (0, toy) # 0,6 + return (0, toy) def setback(self, element, facing): return {'up': 16, 'down': 0, @@ -1143,11 +1109,11 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac return texture + # TODO: use uv instead of from-to values def crop_to_transparancy(self, img, area): # PIL image coordinates do not match MC texture coordinates # PIL starts in lower left # MC starts in upper left - # r, b, l, t if area[0] > area[2]: area = [area[2], area[1], area[0], area[3]] @@ -1334,7 +1300,7 @@ def unbound_models(): global max_blockid, block_models, next_unclaimed_id tex = Textures() - models = tex.find_models(tex) + models = Textures.find_models(tex) for model in models: # determine transparency @@ -1600,11 +1566,6 @@ def sponge(self, blockid, data): # lapis lazuli block solidmodelblock(blockid=22, name="lapis_block") -@material(blockid=[577], data=list(range(8)), solid=True, transparent=True) -def modern_stairs(self, blockid, data): - facing = {3: 'north', 0: 'east', 2: 'south', 1: 'west' }[data%4] - return self.build_block_from_model('mangrove_stairs', {'facing': facing}) - @material(blockid=[23, 158], data=list(range(6)), solid=True) def dropper(self, blockid, data): facing = {0: 'down', 1: 'up', 2: 'north', 3: 'south', 4: 'west', 5: 'east'}[data] @@ -2387,9 +2348,19 @@ def composter(self, blockid, data): @material(blockid=[51, 1040], transparent=True) def fire(self, blockid, data): if blockid == 51: - return self.build_block_from_model('fire_floor0') - else: - return self.build_block_from_model('soul_fire_floor0') + textureNS = self.load_image_texture("assets/minecraft/textures/block/fire_0.png") + textureEW = self.load_image_texture("assets/minecraft/textures/block/fire_1.png") + elif blockid == 1040: + textureNS = self.load_image_texture("assets/minecraft/textures/block/soul_fire_0.png") + textureEW = self.load_image_texture("assets/minecraft/textures/block/soul_fire_1.png") + side1 = self.transform_image_side(textureNS) + side2 = self.transform_image_side(textureEW).transpose(Image.FLIP_LEFT_RIGHT) + img = Image.new("RGBA", (24,24), self.bgcolor) + alpha_over(img, side1, (12,0), side1) + alpha_over(img, side2, (0,0), side2) + alpha_over(img, side1, (0,6), side1) + alpha_over(img, side2, (12,6), side2) + return img # monster spawner modelblock(blockid=52, name="spawner", solid=True, transparent=True) @@ -2404,7 +2375,7 @@ def fire(self, blockid, data): @material(blockid=[53, 67, 108, 109, 114, 128, 134, 135, 136, 156, 163, 164, 180, 203, 509, 510, 11337, 11338, 11339, 11370, 11371, 11374, 11375, 11376, 11377, 11378, 11379, 11380, 11381, 11382, 11383, 11384, 11415, 1030, 1031, 1032, 1064, 1065, 1066, - 1067, 1068, 1069, 1070, 1071, 1099, 1100, 1101, 1102], + 1067, 1068, 1069, 1070, 1071, 1099, 1100, 1101, 1102, 1108], data=list(range(128)), transparent=True, solid=True, nospawn=True) def stairs(self, blockid, data): # preserve the upside-down bit @@ -2470,6 +2441,7 @@ def stairs(self, blockid, data): 1100: "assets/minecraft/textures/block/polished_deepslate.png", 1101: "assets/minecraft/textures/block/deepslate_bricks.png", 1102: "assets/minecraft/textures/block/deepslate_tiles.png", + 1108: "assets/minecraft/textures/block/mangrove_planks.png", } texture = self.load_image_texture(stair_id_to_tex[blockid]).copy() @@ -4453,26 +4425,6 @@ def build_torch(active): # the trapdoor is looks like a sprite when opened, that's not good @material(blockid=[96,167,451,11332,11333,11334,11335,11336,12501,12502], data=list(range(16)), transparent=True, nospawn=True) def trapdoor(self, blockid, data): - - # texture generation - model_map = {96:"oak_trapdoor", - 167:"iron_trapdoor", - 451:"mangrove_trapdoor", - 11332:"spruce_trapdoor", - 11333:"birch_trapdoor", - 11334:"jungle_trapdoor", - 11335:"acacia_trapdoor", - 11336:"dark_oak_trapdoor", - 12501:"crimson_trapdoor", - 12502:"warped_trapdoor", - } - facing = {0: 'north', 1: 'south', 2: 'west', 3: 'east'}[data % 4] - - if data & 0x4 == 0x4: # off - return self.build_block_from_model("%s_open" % model_map[blockid], {'facing': facing}) - if data & 0x8 == 0x8: # off - return self.build_block_from_model("%s_top" % model_map[blockid] ) - return self.build_block_from_model("%s_bottom" % model_map[blockid]) # rotation # Masked to not clobber opened/closed info @@ -5250,13 +5202,6 @@ def quartz_pillar(self, blockid, data): # hopper @material(blockid=154, data=list(range(6)), transparent=True) def hopper(self, blockid, data): - # # TODO: - # facing = {0: 'down', 1: 'up', 2: 'east', 3: 'south', 4: 'west', 5: 'north'}[data] - # if facing == 'down': - # return self.build_block_from_model('hopper', {'facing': facing}) - # return self.build_block_from_model('hopper_side', {'facing': facing}) - - #build the top side = self.load_image_texture("assets/minecraft/textures/block/hopper_outside.png") top = self.load_image_texture("assets/minecraft/textures/block/hopper_top.png") @@ -5410,15 +5355,15 @@ def crops(self, blockid, data): return self.build_block_from_model("beetroots_stage%d" % data) else: raw_crop = self.load_image_texture("assets/minecraft/textures/block/sweet_berry_bush_stage%d.png" % data) - crop1 = self.transform_image_top(raw_crop) - crop2 = self.transform_image_side(raw_crop) - crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) + crop1 = self.transform_image_top(raw_crop) + crop2 = self.transform_image_side(raw_crop) + crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) - img = Image.new("RGBA", (24,24), self.bgcolor) - alpha_over(img, crop1, (0,12), crop1) - alpha_over(img, crop2, (6,3), crop2) - alpha_over(img, crop3, (6,3), crop3) - return img + img = Image.new("RGBA", (24,24), self.bgcolor) + alpha_over(img, crop1, (0,12), crop1) + alpha_over(img, crop2, (6,3), crop2) + alpha_over(img, crop3, (6,3), crop3) + return img # Glazed Terracotta @material(blockid=list(range(235, 251)), data=list(range(4)), solid=True) @@ -5890,12 +5835,6 @@ def cave_vines(self, blockid, data): @material(blockid=1118, data=list(range(6)), transparent=True, solid=True) def lightning_rod(self, blockid, data): - # lignting rod default model is for facing 'up' - # TODO: for generic processing the texture requires uv handling - - # facing = {0: 'down', 1: 'up', 2: 'east', 3: 'south', 4: 'west', 5: 'north'}[data] - # return self.build_block_from_model('lightning_rod', {'facing': 'north'}) - tex = self.load_image_texture("assets/minecraft/textures/block/lightning_rod.png") img = Image.new("RGBA", (24, 24), self.bgcolor) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 89a108339..5043fa5c9 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -375,7 +375,6 @@ def __init__(self, regiondir, rel): 'minecraft:oak_stairs': (53, 0), 'minecraft:crimson_stairs': (509, 0), 'minecraft:warped_stairs': (510, 0), - 'minecraft:mangrove_stairs': (577, 0), 'minecraft:chest': (54, 0), 'minecraft:redstone_wire': (55, 0), 'minecraft:diamond_ore': (56, 0), @@ -693,6 +692,7 @@ def __init__(self, regiondir, rel): 'minecraft:polished_deepslate_stairs': (1100, 0), 'minecraft:deepslate_brick_stairs': (1101, 0), 'minecraft:deepslate_tile_stairs': (1102, 0), + 'minecraft:mangrove_stairs': (1108, 0), 'minecraft:cobbled_deepslate_slab': (1103, 0), 'minecraft:polished_deepslate_slab': (1104, 0), From a3a3c7e6882f876573f49ee9c3abe84c82f1b945 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Sun, 31 Jul 2022 15:02:31 +0200 Subject: [PATCH 29/34] 3.8 compatable --- overviewer_core/textures.py | 252 +++++++++++++++++------------------- 1 file changed, 120 insertions(+), 132 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index de6ada9c3..5ed9c101f 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -893,27 +893,25 @@ def load_model(self, modelname): # fix known inconsistencies in model info def normalize_model(self, modelname): - match modelname: - case 'block/observer': - self.models[modelname] = deepcopy(self.models[modelname]) - self.models[modelname]['elements'][0]['faces']['up']['uv'] = [0, 0, 16, 16] - # remap textures of blocks with the rotation property to match the mapping of the observer textures - case 'block/loom': - self.models[modelname] = deepcopy(self.models[modelname]) - self.models[modelname]['elements'][0]['faces']['up']['texturerotation'] = 180 - self.models[modelname]['elements'][0]['faces']['down']['texturerotation'] = 180 - case 'block/barrel' | 'block/barrel_open': - self.models[modelname] = deepcopy(self.models[modelname]) - self.models[modelname]['elements'][0]['faces']['north']['texture'] = '#up' - self.models[modelname]['elements'][0]['faces']['south']['texture'] = '#down' - self.models[modelname]['elements'][0]['faces']['down']['texture'] = '#north' - self.models[modelname]['elements'][0]['faces']['up']['texture'] = '#south' - self.models[modelname]['elements'][0]['faces']['east']['texturerotation'] = 90 - self.models[modelname]['elements'][0]['faces']['west']['texturerotation'] = 90 - case 'block/dropper_vertical' | 'block/dispenser_vertical': - self.models[modelname] = deepcopy(self.models[modelname]) - self.models[modelname]['elements'][0]['faces']['north']['texture'] = '#up' - self.models[modelname]['elements'][0]['faces']['up']['texture'] = '#north' + if modelname == 'block/observer': + self.models[modelname] = deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['up']['uv'] = [0, 0, 16, 16] + elif modelname == 'block/loom': + self.models[modelname] = deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['up']['texturerotation'] = 180 + self.models[modelname]['elements'][0]['faces']['down']['texturerotation'] = 180 + elif modelname == 'block/barrel' or modelname == 'block/barrel_open': + self.models[modelname] = deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['north']['texture'] = '#up' + self.models[modelname]['elements'][0]['faces']['south']['texture'] = '#down' + self.models[modelname]['elements'][0]['faces']['down']['texture'] = '#north' + self.models[modelname]['elements'][0]['faces']['up']['texture'] = '#south' + self.models[modelname]['elements'][0]['faces']['east']['texturerotation'] = 90 + self.models[modelname]['elements'][0]['faces']['west']['texturerotation'] = 90 + elif modelname == 'block/dropper_vertical' or modelname == 'block/dispenser_vertical': + self.models[modelname] = deepcopy(self.models[modelname]) + self.models[modelname]['elements'][0]['faces']['north']['texture'] = '#up' + self.models[modelname]['elements'][0]['faces']['up']['texture'] = '#north' return self.models[modelname] @@ -973,34 +971,30 @@ def draw_blockface(self, img, elem, colmodel, blockstate, modelname, direction): def image_pos(self, elementdirection, element, facing, modelname): - match elementdirection: - - case 'east': return (0, 0) - case 'south': return (12, 0) - - case 'west': - setback = 16 - self.setback(element, facing) - toya = int(math.ceil(12/16 * (setback))) - toy = int(math.ceil(6/16 * (setback))) - return (toya, toy) - - case 'north': - setback = self.setback(element, facing) - toya = int(math.ceil((12/16 * (setback)))) - toy = int(math.ceil(6 - (6/16 * (setback)))) - return (toya, toy) - - case 'down': - fromy = 12 - if 'from' in element: - fromy = int(math.ceil(((16 - element['from'][1])/16*12.))) - return (0, fromy) - - case 'up' | _: - toy = 0 - if 'to' in element: - toy = int(math.ceil(((16 - element['to'][1])/16*12.))) - return (0, toy) + if elementdirection == 'east': + return (0, 0) + elif elementdirection == 'south': + return (12, 0) + elif elementdirection == 'west': + setback = 16 - self.setback(element, facing) + toya = int(math.ceil(12/16 * (setback))) + toy = int(math.ceil(6/16 * (setback))) + return (toya, toy) + elif elementdirection == 'north': + setback = self.setback(element, facing) + toya = int(math.ceil((12/16 * (setback)))) + toy = int(math.ceil(6 - (6/16 * (setback)))) + return (toya, toy) + elif elementdirection == 'down': + toy = 12 + if 'from' in element: + fromy = int(math.ceil(((16 - element['from'][1])/16*12.))) + return (0, toy) + else: # up + toy = 0 + if 'to' in element: + toy = int(math.ceil(((16 - element['to'][1])/16*12.))) + return (0, toy) def setback(self, element, facing): return {'up': 16, 'down': 0, @@ -1042,26 +1036,24 @@ def map_facing_to_real(self, blockfacing, targetblockface): return resultface def map_axis_to_real(self, axis, textureface): - match axis: - case 'x': - return {'up': 'north', 'north': 'down', 'down': 'south', 'south': 'up', 'east': 'east', 'west': 'west'}[textureface] - case 'z': - return {'up': 'west', 'west': 'down', 'down': 'east', 'east': 'up', 'north': 'north', 'south': 'south'}[textureface] - case 'y' | _: - return textureface + if axis == 'x': + return {'up': 'north', 'north': 'down', 'down': 'south', 'south': 'up', 'east': 'east', 'west': 'west'}[textureface] + elif axis == 'z': + return {'up': 'west', 'west': 'down', 'down': 'east', 'east': 'up', 'north': 'north', 'south': 'south'}[textureface] + else: + return textureface def axis_rotation(self, axis, face, texture): - match axis: - case 'x': - rotation = {'up': 270, 'north': 0, 'down': 0, - 'south': 0, 'east': 270, 'west': 270}[face] - return texture.rotate(rotation) - case 'z': - rotation = {'up': 0, 'west': 0, 'down': 0, - 'east': 0, 'north': 90, 'south': 90}[face] - return texture.rotate(rotation) - case 'y' | _: - return texture + if axis == 'x': + rotation = {'up': 270, 'north': 0, 'down': 0, + 'south': 0, 'east': 270, 'west': 270}[face] + return texture.rotate(rotation) + elif axis == 'z': + rotation = {'up': 0, 'west': 0, 'down': 0, + 'east': 0, 'north': 90, 'south': 90}[face] + return texture.rotate(rotation) + else: + return texture def build_texture(self, direction, elem, data, blockstate, modelname, textureface): @@ -1075,32 +1067,30 @@ def build_texture(self, direction, elem, data, blockstate, modelname, texturefac if 'from' in elem and 'to' in elem and (elem['from'] != [0,0,0] or elem['to'] != [16,16,16]): area = [0,0,16,16] - match textureface: - - case 'west': - area = [elem['from'][2],elem['from'][1],elem['to'][2],elem['to'][1]] - texture = self.crop_to_transparancy(texture, area) - case 'east': - area = [16-elem['from'][2],elem['from'][1],16-elem['to'][2],elem['to'][1]] - texture = self.crop_to_transparancy(texture, area) - case 'north': - area = [16-elem['from'][0],elem['from'][1],16-elem['to'][0],elem['to'][1]] - texture = self.crop_to_transparancy(texture, area) - case 'south': - area = [elem['from'][0],elem['from'][1],elem['to'][0],elem['to'][1]] - texture = self.crop_to_transparancy(texture, area) - case 'up'|'down'|_: - if 'facing' in blockstate and blockstate['facing'] in {'north'}: - area = [elem['from'][0],16-elem['from'][2],elem['to'][0],16-elem['to'][2]] - elif 'facing' in blockstate and blockstate['facing'] in {'south'}: - area = [16-elem['from'][0],elem['from'][2],16-elem['to'][0],elem['to'][2]] - elif 'facing' in blockstate and blockstate['facing'] in {'west'}: - area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] - elif 'facing' in blockstate and blockstate['facing'] in {'east'}: - area = [16-elem['from'][2],16-elem['from'][0],16-elem['to'][2],16-elem['to'][0]] - else: - area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] - texture = self.crop_to_transparancy(texture, area) + if textureface == 'west': + area = [elem['from'][2],elem['from'][1],elem['to'][2],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + elif textureface == 'east': + area = [16-elem['from'][2],elem['from'][1],16-elem['to'][2],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + elif textureface == 'north': + area = [16-elem['from'][0],elem['from'][1],16-elem['to'][0],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + elif textureface == 'south': + area = [elem['from'][0],elem['from'][1],elem['to'][0],elem['to'][1]] + texture = self.crop_to_transparancy(texture, area) + elif textureface in {'up', 'down'}: + if 'facing' in blockstate and blockstate['facing'] in {'north'}: + area = [elem['from'][0],16-elem['from'][2],elem['to'][0],16-elem['to'][2]] + elif 'facing' in blockstate and blockstate['facing'] in {'south'}: + area = [16-elem['from'][0],elem['from'][2],16-elem['to'][0],elem['to'][2]] + elif 'facing' in blockstate and blockstate['facing'] in {'west'}: + area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] + elif 'facing' in blockstate and blockstate['facing'] in {'east'}: + area = [16-elem['from'][2],16-elem['from'][0],16-elem['to'][2],16-elem['to'][0]] + else: + area = [elem['from'][2],elem['from'][0],elem['to'][2],elem['to'][0]] + texture = self.crop_to_transparancy(texture, area) # TODO: deal with rotation @@ -1141,55 +1131,53 @@ def crop_to_transparancy(self, img, area): return img def adjust_lighting(self, direction, texture): - match direction: - case 'south' | 'west': - sidealpha = texture.split()[3] - texture = ImageEnhance.Brightness(texture).enhance(0.8) - texture.putalpha(sidealpha) - return texture - case 'north' | 'east': - sidealpha = texture.split()[3] - texture = ImageEnhance.Brightness(texture).enhance(0.9) - texture.putalpha(sidealpha) - return texture - case 'down' | 'up' | _: - return texture + if direction in {'south', 'west'}: + sidealpha = texture.split()[3] + texture = ImageEnhance.Brightness(texture).enhance(0.8) + texture.putalpha(sidealpha) + return texture + if direction in {'north', 'east'}: + sidealpha = texture.split()[3] + texture = ImageEnhance.Brightness(texture).enhance(0.9) + texture.putalpha(sidealpha) + return texture + else: + return texture def texture_rotation(self, direction, texture, blockstate, faceinfo, modelname): rotation = 0 if 'texturerotation' in faceinfo: rotation += faceinfo['texturerotation'] - match direction: - case 'down' | 'up': - if 'facing' in blockstate: - if self.numvalue_orientation(blockstate['facing']) < 4: - rotation += [0, 270, 180, - 90][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] - else: - rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] - case 'north' | 'south': - if 'rotation' in faceinfo: - rotation = {0: 180, 90: 90, 180: 0, 270: 270}[faceinfo['rotation']] - if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: - rotation += [90, 90][({'up': 0, 'down': 1}[blockstate['facing']])] - case 'west' | 'east': - if 'rotation' in faceinfo: - rotation = {0: 180, 90: 270, 180: 0, 270: 90}[faceinfo['rotation']] - if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: + if direction in {'down', 'up'}: + if 'facing' in blockstate: + if self.numvalue_orientation(blockstate['facing']) < 4: + rotation += [0, 270, 180, + 90][(self.numvalue_orientation(blockstate['facing']) + self.rotation) % 4] + else: rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] + elif direction in {'north', 'south'}: + if 'rotation' in faceinfo: + rotation = {0: 180, 90: 90, 180: 0, 270: 270}[faceinfo['rotation']] + if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: + rotation += [90, 90][({'up': 0, 'down': 1}[blockstate['facing']])] + elif direction in {'west', 'east'}: + if 'rotation' in faceinfo: + rotation = {0: 180, 90: 270, 180: 0, 270: 90}[faceinfo['rotation']] + if 'facing' in blockstate and blockstate['facing'] in {'up', 'down'}: + rotation += [180, 0][({'up': 0, 'down': 1}[blockstate['facing']])] return texture.rotate(rotation % 360) def transform_texture(self, direction, texture, blockstate, faceinfo): - match direction: - case 'down' | 'up': - return self.transform_image_top(texture) - case 'north' | 'south': - texture = self.transform_image_side(texture) - case 'west' | 'east': - texture = texture.transpose(Image.FLIP_LEFT_RIGHT) - texture = self.transform_image_side(texture) - texture = texture.transpose(Image.FLIP_LEFT_RIGHT) + + if direction in {'down', 'up'}: + return self.transform_image_top(texture) + elif direction in {'north', 'south'}: + texture = self.transform_image_side(texture) + elif direction in {'west', 'east'}: + texture = texture.transpose(Image.FLIP_LEFT_RIGHT) + texture = self.transform_image_side(texture) + texture = texture.transpose(Image.FLIP_LEFT_RIGHT) return texture From 36136ecfa05ce00c52d2a5e625d2cf883a5ff031 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Mon, 1 Aug 2022 07:13:06 +0200 Subject: [PATCH 30/34] optional axis --- overviewer_core/world.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 5043fa5c9..dcc0dc9cd 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -1076,7 +1076,10 @@ def _get_block(self, palette_entry): data |= 8 elif key in ['minecraft:basalt', 'minecraft:polished_basalt', 'minecraft:chain', 'minecraft:purpur_pillar', 'minecraft:deepslate', 'minecraft:hay_block', 'minecraft:quartz_pillar']: - axis = palette_entry['Properties']['axis'] + if 'axis' in palette_entry['Properties']: + axis = palette_entry['Properties']['axis'] + else: + axis = 'y' data = {'y': 0, 'x': 1, 'z': 2}[axis] elif key in ['minecraft:redstone_torch','minecraft:redstone_wall_torch','minecraft:wall_torch', 'minecraft:soul_torch', 'minecraft:soul_wall_torch']: From ca86e1e32b28ee67ea7f3642e73287ce1e38c583 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Tue, 2 Aug 2022 08:00:29 +0200 Subject: [PATCH 31/34] double slab only if modelblocks have been loaded --- overviewer_core/world.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index dcc0dc9cd..fe468e154 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -1016,7 +1016,7 @@ def _get_block(self, palette_entry): elif key in slab_to_double : if slab_to_double[key] in self._blockmap: (block, data) = self._blockmap[slab_to_double[key]] - else: + elif slab_to_double[key] in modelblocks: (block, data) = modelblocks[slab_to_double[key]] else: if key+'_top' in modelblocks: From 3f786062435f4f5d732350ebccfcd52b81d1efeb Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Tue, 2 Aug 2022 14:51:52 +0200 Subject: [PATCH 32/34] typo in variable name --- overviewer_core/textures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 5ed9c101f..ae3e4e82c 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -988,7 +988,7 @@ def image_pos(self, elementdirection, element, facing, modelname): elif elementdirection == 'down': toy = 12 if 'from' in element: - fromy = int(math.ceil(((16 - element['from'][1])/16*12.))) + toy = int(math.ceil(((16 - element['from'][1])/16*12.))) return (0, toy) else: # up toy = 0 @@ -1136,7 +1136,7 @@ def adjust_lighting(self, direction, texture): texture = ImageEnhance.Brightness(texture).enhance(0.8) texture.putalpha(sidealpha) return texture - if direction in {'north', 'east'}: + elif direction in {'north', 'east'}: sidealpha = texture.split()[3] texture = ImageEnhance.Brightness(texture).enhance(0.9) texture.putalpha(sidealpha) From cabcdf91fcc353d3584a7f2af2c8a903dc01a283 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Mon, 8 Aug 2022 07:30:58 +0200 Subject: [PATCH 33/34] stone double slab --- overviewer_core/world.py | 1 + 1 file changed, 1 insertion(+) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index fe468e154..105ab56fd 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -906,6 +906,7 @@ def _get_block(self, palette_entry): # Map from slab to double slab block slab_to_double = { 'minecraft:stone_slab': 'minecraft:stone', + 'minecraft:stone_brick_slab': 'minecraft:stone_bricks', 'minecraft:cobblestone_slab': 'minecraft:cobblestone', 'minecraft:sandstone_slab': 'minecraft:sandstone', 'minecraft:red_sandstone_slab': 'minecraft:red_sandstone', From 7343acfbfab2f140a72c585259adcd6af6da6e53 Mon Sep 17 00:00:00 2001 From: Lieuwe Westra Date: Tue, 16 Aug 2022 07:41:33 +0200 Subject: [PATCH 34/34] mud brick stairs --- overviewer_core/src/block_class.c | 7 +++++-- overviewer_core/src/mc_id.h | 1 + overviewer_core/textures.py | 3 ++- overviewer_core/world.py | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/overviewer_core/src/block_class.c b/overviewer_core/src/block_class.c index 97d11a381..8df171843 100644 --- a/overviewer_core/src/block_class.c +++ b/overviewer_core/src/block_class.c @@ -151,7 +151,8 @@ const mc_block_t block_class_stair[] = { block_polished_deepslate_stairs, block_deepslate_brick_stairs, block_deepslate_tile_stairs, - block_mangrove_stairs}; + block_mangrove_stairs, + block_mud_brick_stairs}; const size_t block_class_stair_len = COUNT_OF(block_class_stair); const mc_block_t block_class_door[] = { @@ -226,6 +227,7 @@ const mc_block_t block_class_ancil[] = { block_deepslate_brick_stairs, block_deepslate_tile_stairs, block_mangrove_stairs, + block_mud_brick_stairs, block_grass, block_flowing_water, block_water, @@ -296,7 +298,8 @@ const mc_block_t block_class_alt_height[] = { block_smooth_sandstone_stairs, block_blackstone_stairs, block_polished_blackstone_stairs, - block_polished_blackstone_brick_stairs, + block_polished_blackstone_brick_stairs, + block_mud_brick_stairs, block_prismarine_slab, block_dark_prismarine_slab, block_prismarine_brick_slab, diff --git a/overviewer_core/src/mc_id.h b/overviewer_core/src/mc_id.h index 6b41fec8d..f0e6d413a 100644 --- a/overviewer_core/src/mc_id.h +++ b/overviewer_core/src/mc_id.h @@ -328,6 +328,7 @@ enum mc_block_id { block_mud_brick_slab = 1124, block_mangrove_log = 1126, + block_mud_brick_stairs = 1129, block_mangrove_slab = 1789, // adding a gap in the numbering of walls to keep them all diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index ae3e4e82c..7ac3fdeda 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -2363,7 +2363,7 @@ def fire(self, blockid, data): @material(blockid=[53, 67, 108, 109, 114, 128, 134, 135, 136, 156, 163, 164, 180, 203, 509, 510, 11337, 11338, 11339, 11370, 11371, 11374, 11375, 11376, 11377, 11378, 11379, 11380, 11381, 11382, 11383, 11384, 11415, 1030, 1031, 1032, 1064, 1065, 1066, - 1067, 1068, 1069, 1070, 1071, 1099, 1100, 1101, 1102, 1108], + 1067, 1068, 1069, 1070, 1071, 1099, 1100, 1101, 1102, 1108, 1129], data=list(range(128)), transparent=True, solid=True, nospawn=True) def stairs(self, blockid, data): # preserve the upside-down bit @@ -2414,6 +2414,7 @@ def stairs(self, blockid, data): 1030: "assets/minecraft/textures/block/blackstone.png", 1031: "assets/minecraft/textures/block/polished_blackstone.png", 1032: "assets/minecraft/textures/block/polished_blackstone_bricks.png", + 1129: "assets/minecraft/textures/block/mud_bricks.png", # Cut copper stairs 1064: "assets/minecraft/textures/block/cut_copper.png", 1065: "assets/minecraft/textures/block/exposed_cut_copper.png", diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 105ab56fd..60181fcfe 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -715,6 +715,7 @@ def __init__(self, regiondir, rel): 'minecraft:mud_brick_slab': (1124, 0), 'minecraft:mangrove_log': (1126, 0), 'minecraft:stripped_mangrove_log': (1126, 1), + 'minecraft:mud_brick_stairs': (1129, 0), # New blocks 'minecraft:carved_pumpkin': (11300, 0),