diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 38d2b35da..387503fd2 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -4068,26 +4068,83 @@ def command_block(self, blockid, data): # 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) +# the data values (we create a "fake" data to add a beam block) +@material(blockid=138, transparent=True, data=range(2)) def beacon(self, blockid, data): - # generate the three pieces of the block - t = self.load_image_texture("assets/minecraft/textures/blocks/glass.png") - glass = self.build_block(t,t) - t = self.load_image_texture("assets/minecraft/textures/blocks/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/blocks/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) + + # First create the normal (real) block + if (data == 0): + # generate the three pieces of the block + t = self.load_image_texture("assets/minecraft/textures/blocks/glass.png") + glass = self.build_block(t,t) + t = self.load_image_texture("assets/minecraft/textures/blocks/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/blocks/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 + return img + + # This is a "fake" block to display the beam + else: + + # first, the beam itself + beacon_beam_top = self.load_image_texture("assets/minecraft/textures/entity/beacon_beam.png") + beacon_beam_top = beacon_beam_top.resize((8,8), Image.ANTIALIAS); + + beam_top = Image.new("RGBA", (24,24), self.bgcolor) + alpha_over(beam_top, beacon_beam_top, (8, 8), beacon_beam_top) + beam_top = self.transform_image_top(beam_top) + + + beacon_beam = self.load_image_texture("assets/minecraft/textures/entity/beacon_beam.png").copy() + beacon_beam = beacon_beam.resize((8,24),Image.ANTIALIAS) + + beam_side = Image.new("RGBA", (24,24), self.bgcolor) + alpha_over(beam_side, beacon_beam, (8, 0), beacon_beam) + beam_side = self.transform_image_side(beam_side) + beam_other_side = beam_side.transpose(Image.FLIP_LEFT_RIGHT) + + # Darken the sides slightly. These methods also affect the alpha layer, + # so save them first (we don't want to "darken" the alpha layer making + # the block transparent) + sidealpha = beam_side.split()[3] + beam_side = ImageEnhance.Brightness(beam_side).enhance(0.9) + beam_side.putalpha(sidealpha) + othersidealpha = beam_other_side.split()[3] + beam_other_side = ImageEnhance.Brightness(beam_other_side).enhance(0.8) + beam_other_side.putalpha(othersidealpha) + + # then, the halo around the beam + halo_top = Image.new("RGBA", (24,24), self.bgcolor) + halo_side = self.load_image_texture("assets/minecraft/textures/entity/beacon_beam.png").copy() + halo_block = self.build_block(halo_top,halo_side) + halo_block_copy = halo_block.copy() + halo_block_copy = ImageEnhance.Brightness(halo_block_copy).enhance(0.2) + halo_block.putalpha(halo_block_copy.split()[3]) + #halo_block = ImageEnhance.Brightness(halo_block).enhance(0.4) + + ## create the block + beam_block = Image.new("RGBA", (24,24), self.bgcolor) + alpha_over(beam_block, beam_top, (0,0), beam_top) + alpha_over(beam_block,beam_side, (4,4),beam_side) + alpha_over(beam_block,beam_other_side, (8,4),beam_other_side) + alpha_over(beam_block,halo_block, (0,0),halo_block) + + + #beam2 = self.build_block(t,t) + #beam2 = beam1.resize((16,24),Image.ANTIALIAS) + + + return beam_block + # cobblestone and mossy cobblestone walls, chorus plants # one additional bit of data value added for mossy and cobblestone diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 49ac9769f..801f7156d 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -394,6 +394,14 @@ def get_chunk(self, x, z): biomes = numpy.zeros((16, 16), dtype=numpy.uint8) chunk_data['Biomes'] = biomes + # Looking for activated beacons + beacons = [] + for entity in chunk_data['TileEntities']: + if (entity['id'] == "minecraft:beacon") and (entity['Levels'] > 0): + beacons.append({'x': entity['x'], 'y': entity['y'], 'z': entity['z']}) + + section_count = 0 + new_sections = [] for section in chunk_data['Sections']: # Turn the Blocks array into a 16x16x16 numpy matrix of shorts, @@ -452,9 +460,49 @@ def get_chunk(self, x, z): logging.debug("Full traceback:", exc_info=1) raise nbt.CorruptChunkError() - - return chunk_data - + + # if we got beacons and missing regions, add one + while beacons and section['Y'] > section_count: + section1 = {'Y': section_count, + 'Blocks': numpy.zeros((16, 16, 16), dtype=numpy.uint16), + 'Data': numpy.zeros((16, 16, 16), dtype=numpy.uint8), + 'SkyLight': numpy.zeros((16, 16, 16), dtype=numpy.uint8), + 'BlockLight': numpy.zeros((16, 16, 16), dtype=numpy.uint8)} + self.add_beams_to_section(beacons, section1) + new_sections.append(section1) + section_count += 1 + + # Add beacon beam to the current section (if needed) + self.add_beams_to_section(beacons, section) + new_sections.append(section) + + section_count += 1 + + # Add section if beacon beams are needed (to reach the sky !!) + while beacons and section_count < 16: + section1 = {'Y': section_count, + 'Blocks': numpy.zeros((16, 16, 16), dtype=numpy.uint16), + 'Data': numpy.zeros((16, 16, 16), dtype=numpy.uint8), + 'SkyLight': numpy.zeros((16, 16, 16), dtype=numpy.uint8), + 'BlockLight': numpy.zeros((16, 16, 16), dtype=numpy.uint8)} + self.add_beams_to_section(beacons, section1) + new_sections.append(section1) + section_count += 1 + + chunk_data['Sections'] = new_sections + + return chunk_data + + def add_beams_to_section(self, beacons, section): + for beacon in beacons: + if (beacon['y'] / 16 <= section['Y']): + y_min=max(0, beacon['y'] - section['Y'] * 16) + for y in range(y_min, 16): + if (section['Blocks'][y][beacon['z'] % 16][beacon['x'] % 16] == 0): + section['Blocks'][y][beacon['z'] % 16][beacon['x'] % 16] = 138 + section['Data'][y][beacon['z'] % 16][beacon['x'] % 16] = 1 + section['BlockLight'][y][beacon['z'] % 16][beacon['x'] % 16] = 15 + section['SkyLight'][y][beacon['z'] % 16][beacon['x'] % 16] = 15 def iterate_chunks(self): """Returns an iterator over all chunk metadata in this world. Iterates