diff --git a/.gitignore b/.gitignore index 3f2e8ef..fbb722e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ MANIFEST build/ dist/ +docs/_build/ Minecraft_Overviewer.egg-info terrain.png cachedir* @@ -40,3 +41,4 @@ overviewer_core/src/primitives.h .idea /.vs/Minecraft-Overviewer/v15/.suo /.vs +.vscode diff --git a/.mailmap b/.mailmap index 23cdf70..9cd54d7 100644 --- a/.mailmap +++ b/.mailmap @@ -3,3 +3,8 @@ Alex Headley Alex Headley aheadley Michael Fallows redorkulated Maciej Malecki Maciej MaƂecki +Nicolas F +Nicolas F CounterPillow +Nicolas F +Nicolas F +Nicolas F diff --git a/.travis.yml b/.travis.yml index f731a34..cc91972 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ python: - "3.6" - "3.7" env: - - MC_VERSION=1.13 + - MC_VERSION=1.14 before_install: - wget https://raw.githubusercontent.com/python-pillow/Pillow/master/src/libImaging/Imaging.h - wget https://raw.githubusercontent.com/python-pillow/Pillow/master/src/libImaging/ImagingUtils.h @@ -18,7 +18,7 @@ install: before_script: - git clone git://github.com/overviewer/Minecraft-Overviewer-Addons.git ~/mcoa/ - mkdir -p ~/.minecraft/versions/${MC_VERSION}/ - - wget -N https://launcher.mojang.com/mc/game/1.13/client/c0b970952cdd279912da384cdbfc0c26e6c6090b/client.jar -O ~/.minecraft/versions/${MC_VERSION}/${MC_VERSION}.jar + - wget -N https://overviewer.org/textures/${MC_VERSION} -O ~/.minecraft/versions/${MC_VERSION}/${MC_VERSION}.jar script: - PYTHONPATH=. python3 test/test_all.py - python3 overviewer.py ~/mcoa/exmaple ~/test-output --rendermodes=smooth-lighting -p1 diff --git a/docs/running.rst b/docs/running.rst index 5f20508..583d66e 100644 --- a/docs/running.rst +++ b/docs/running.rst @@ -267,17 +267,17 @@ If you want or need to provide your own textures, you have several options: Run the first line in a terminal, changing the version string to the latest as appropriate (these docs may not always be updated to reflect the latest). Then paste the second line into your terminal to download the latest version. ``${VERSION}`` will be replaced - by the acutal version string from the first line. + by the actual version string from the first line. :: - VERSION=1.12 - wget https://s3.amazonaws.com/Minecraft.Download/versions/${VERSION}/${VERSION}.jar -P ~/.minecraft/versions/${VERSION}/ + VERSION=1.14 + wget https://overviewer.org/textures/${VERSION} -O ~/.minecraft/versions/${VERSION}/${VERSION}.jar If that's too confusing for you, then just take this single line and paste it into - a terminal to get 1.12 textures:: + a terminal to get 1.14 textures:: - wget https://s3.amazonaws.com/Minecraft.Download/versions/1.12/1.12.jar -P ~/.minecraft/versions/1.12/ + wget https://overviewer.org/textures/1.14 -O ~/.minecraft/versions/1.14/1.14.jar * You can also just run the launcher to install the client. diff --git a/docs/signs.rst b/docs/signs.rst index a78d0c0..341d5d8 100644 --- a/docs/signs.rst +++ b/docs/signs.rst @@ -44,7 +44,7 @@ the Minecraft Wiki. A more complicated filter function can construct a more customized display text:: def chestFilter(poi): - if poi['id'] == "Chest": + if poi['id'] == "Chest" or poi['id'] == 'minecraft:chest': return "Chest with %d items" % len(poi.get('Items', [])) It is also possible to return a tuple from the filter function to specify a hovertext @@ -52,7 +52,7 @@ different from the text displayed in the info window. The first entry of the tup be used as the hover text, the second will be used as the info window content:: def chestFilter(poi): - if poi['id'] == "Chest": + if poi['id'] == "Chest" or poi['id'] == 'minecraft:chest': return ("Chest", "Chest with %d items" % len(poi.get('Items', []))) Because of the way the config file is loaded, if you need to import a function or module @@ -61,7 +61,7 @@ for use in your filter function, you need to explicitly load it into the global global escape from cgi import escape def signFilter(poi): - if poi['id'] == 'Sign': + if poi['id'] == 'Sign' or poi['id'] == 'minecraft:sign': return "\n".join(map(escape, [poi['Text1'], poi['Text2'], poi['Text3'], poi['Text4']])) Since writing these filters can be a little tedious, a set of predefined filters diff --git a/overviewer.py b/overviewer.py index 7f2f851..b5b9a47 100755 --- a/overviewer.py +++ b/overviewer.py @@ -62,6 +62,20 @@ def main(): "permissions instead. Overviewer does not need access to " "critical system resources and therefore does not require " "root access.") + try: + with open("/etc/redhat-release", "r") as release_f: + rel_contents = release_f.read() + try: + major_rel = re.search(r'\d(\.\d+)?', rel_contents).group(0).split('.')[0] + if major_rel == "6": + logging.warning( + "We will be dropping support for this release of your distribution " + "soon. Please upgrade as soon as possible, or you will not receive " + "future Overviewer updates.") + except AttributeError: + pass + except IOError: + pass try: cpus = multiprocessing.cpu_count() diff --git a/overviewer_core/data/js_src/util.js b/overviewer_core/data/js_src/util.js index f4f487b..59294cb 100644 --- a/overviewer_core/data/js_src/util.js +++ b/overviewer_core/data/js_src/util.js @@ -221,6 +221,27 @@ overviewer.util = { 'Overviewer/Leaflet'); overviewer.map.on('baselayerchange', function(ev) { + + // when changing the layer, ensure coordinates remain correct + if (overviewer.current_layer[overviewer.current_world]) { + const center = overviewer.map.getCenter(); + const currentWorldCoords = overviewer.util.fromLatLngToWorld( + center.lat, + center.lng, + overviewer.current_layer[overviewer.current_world].tileSetConfig); + + const newMapCoords = overviewer.util.fromWorldToLatLng( + currentWorldCoords.x, + currentWorldCoords.y, + currentWorldCoords.z, + ev.layer.tileSetConfig); + + overviewer.map.setView( + newMapCoords, + overviewer.map.getZoom(), + { animate: false }); + } + // before updating the current_layer, remove the marker control, if it exists if (overviewer.current_world && overviewer.current_layer[overviewer.current_world]) { let tsc = overviewer.current_layer[overviewer.current_world].tileSetConfig; diff --git a/overviewer_core/src/block_class.c b/overviewer_core/src/block_class.c new file mode 100644 index 0000000..0a62961 --- /dev/null +++ b/overviewer_core/src/block_class.c @@ -0,0 +1,212 @@ +/* + * This file is part of the Minecraft Overviewer. + * + * Minecraft Overviewer is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Minecraft Overviewer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the Overviewer. If not, see . + */ + +#include "block_class.h" +#include "utils.h" + +#if defined(__i386__) || defined(__x86_64__) +#include +#endif + +bool block_class_is_subset( + mc_block_t block, + const mc_block_t block_class[], + size_t block_class_len +) { + size_t i = 0; + +#ifdef __SSE2__ + for (; i / 8 < block_class_len / 8; i += 8) { + const __m128i block_class_vec = _mm_loadu_si128( + (__m128i*)&block_class[i] + ); + const __m128i block_vec = _mm_set1_epi16(block); + const __m128i block_cmp = _mm_cmpeq_epi16(block_vec,block_class_vec); + if (_mm_movemask_epi8(block_cmp)) { + return true; + } + } +#endif +#ifdef __MMX__ + for (; i / 4 < block_class_len / 4; i += 4) { + const __m64 block_class_vec = _mm_cvtsi64_m64( + *(uint64_t*)&block_class[i] + ); + const __m64 block_vec = _mm_set1_pi16(block); + const __m64 block_cmp = _mm_cmpeq_pi16(block_vec,block_class_vec); + if (_mm_cvtm64_si64(block_cmp)) { + return true; + } + } +#endif + for (; i < block_class_len; ++i) { + if (block == block_class[i]) { + return true; + } + } + return false; +} + + +const mc_block_t block_class_stair[] = { + block_oak_stairs, + block_stone_stairs, + block_brick_stairs, + block_stone_brick_stairs, + block_nether_brick_stairs, + block_sandstone_stairs, + block_spruce_stairs, + block_birch_stairs, + block_jungle_stairs, + block_quartz_stairs, + block_acacia_stairs, + block_dark_oak_stairs, + block_red_sandstone_stairs, + block_purpur_stairs, + block_prismarine_stairs, + block_dark_prismarine_stairs, + block_prismarine_brick_stairs +}; +const size_t block_class_stair_len = COUNT_OF(block_class_stair); + +const mc_block_t block_class_door[] = { + block_wooden_door, + block_iron_door, + block_spruce_door, + block_birch_door, + block_jungle_door, + block_acacia_door, + block_dark_oak_door +}; +const size_t block_class_door_len = COUNT_OF(block_class_door); + +const mc_block_t block_class_fence[] = { + block_fence, + block_nether_brick_fence, + block_spruce_fence, + block_birch_fence, + block_jungle_fence, + block_dark_oak_fence, + block_acacia_fence +}; +const size_t block_class_fence_len = COUNT_OF(block_class_fence); + +const mc_block_t block_class_fence_gate[] = { + block_fence_gate, + block_spruce_fence_gate, + block_birch_fence_gate, + block_jungle_fence_gate, + block_dark_oak_fence_gate, + block_acacia_fence_gate +}; +const size_t block_class_fence_gate_len = COUNT_OF(block_class_fence_gate); + +const mc_block_t block_class_ancil[] = { + block_wooden_door, + block_iron_door, + block_spruce_door, + block_birch_door, + block_jungle_door, + block_acacia_door, + block_dark_oak_door, + block_oak_stairs, + block_stone_stairs, + block_brick_stairs, + block_stone_brick_stairs, + block_nether_brick_stairs, + block_sandstone_stairs, + block_spruce_stairs, + block_birch_stairs, + block_jungle_stairs, + block_quartz_stairs, + block_acacia_stairs, + block_dark_oak_stairs, + block_red_sandstone_stairs, + block_purpur_stairs, + block_prismarine_stairs, + block_dark_prismarine_stairs, + block_prismarine_brick_stairs, + block_grass, + block_flowing_water, + block_water, + block_glass, + block_chest, + block_redstone_wire, + block_ice, + block_fence, + block_portal, + block_iron_bars, + block_glass_pane, + block_waterlily, + block_nether_brick_fence, + block_cobblestone_wall, + block_double_plant, + block_stained_glass_pane, + block_stained_glass, + block_trapped_chest, + block_spruce_fence, + block_birch_fence, + block_jungle_fence, + block_dark_oak_fence, + block_acacia_fence +}; +const size_t block_class_ancil_len = COUNT_OF(block_class_ancil); + +const mc_block_t block_class_alt_height[] = { + block_stone_slab, + block_oak_stairs, + block_stone_stairs, + block_brick_stairs, + block_stone_brick_stairs, + block_nether_brick_stairs, + block_sandstone_stairs, + block_spruce_stairs, + block_birch_stairs, + block_jungle_stairs, + block_quartz_stairs, + block_acacia_stairs, + block_dark_oak_stairs, + block_red_sandstone_stairs, + block_prismarine_stairs, + block_dark_prismarine_stairs, + block_prismarine_brick_stairs, + block_prismarine_slab, + block_dark_prismarine_slab, + block_prismarine_brick_slab, + block_andesite_slab, + block_diorite_slab, + block_granite_slab, + block_polished_andesite_slab, + block_polished_diorite_slab, + block_polished_granite_slab, + block_red_nether_brick_slab, + block_smooth_sandstone_slab, + block_cut_sandstone_slab, + block_smooth_red_sandstone_slab, + block_cut_red_sandstone_slab, + block_end_stone_brick_slab, + block_mossy_cobblestone_slab, + block_mossy_stone_brick_slab, + block_smooth_quartz_slab, + block_smooth_stone_slab, + block_stone_slab2, + block_purpur_stairs, + block_purpur_slab, + block_wooden_slab +}; +const size_t block_class_alt_height_len = COUNT_OF(block_class_alt_height); + diff --git a/overviewer_core/src/block_class.h b/overviewer_core/src/block_class.h new file mode 100644 index 0000000..a0db742 --- /dev/null +++ b/overviewer_core/src/block_class.h @@ -0,0 +1,51 @@ +/* + * This file is part of the Minecraft Overviewer. + * + * Minecraft Overviewer is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Minecraft Overviewer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the Overviewer. If not, see . + */ + +#ifndef __BLOCK_CLASS_H_INCLUDED__ +#define __BLOCK_CLASS_H_INCLUDED__ + +#include +#include + +#include "mc_id.h" + +bool block_class_is_subset( + mc_block_t block, + const mc_block_t block_class[], + size_t block_class_len +); + +extern const mc_block_t block_class_stair[]; +extern const size_t block_class_stair_len; + +extern const mc_block_t block_class_door[]; +extern const size_t block_class_door_len; + +extern const mc_block_t block_class_fence[]; +extern const size_t block_class_fence_len; + +extern const mc_block_t block_class_fence_gate[]; +extern const size_t block_class_fence_gate_len; + +extern const mc_block_t block_class_ancil[]; +extern const size_t block_class_ancil_len; + +extern const mc_block_t block_class_alt_height[]; +extern const size_t block_class_alt_height_len; + +#endif + diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index d25cd3c..5809cfc 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -16,6 +16,8 @@ */ #include "overviewer.h" +#include "mc_id.h" +#include "block_class.h" static PyObject *textures = NULL; @@ -242,32 +244,6 @@ check_adjacent_blocks(RenderState *state, int x,int y,int z, unsigned short bloc return pdata; } - -static int -is_stairs(int block) { - /* - * Determines if a block is stairs of any material - */ - switch (block) { - case 53: /* oak wood stairs */ - case 67: /* cobblestone stairs */ - case 108: /* brick stairs */ - case 109: /* stone brick stairs */ - case 114: /* nether brick stairs */ - case 128: /* sandstone stairs */ - case 134: /* spruce wood stairs */ - case 135: /* birch wood stairs */ - case 136: /* jungle wood stairs */ - case 156: /* quartz stairs */ - case 163: /* acacia wood stairs */ - case 164: /* dark wood stairs */ - case 180: /* red sandstone stairs */ - case 203: /* purpur stairs */ - return 1; - } - return 0; -} - unsigned short generate_pseudo_data(RenderState *state, unsigned short ancilData) { /* @@ -277,18 +253,18 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { int x = state->x, y = state->y, z = state->z; unsigned short data = 0; - if (state->block == 2) { /* grass */ + if (state->block == block_grass) { /* grass */ /* return 0x10 if grass is covered in snow */ if (get_data(state, BLOCKS, x, y+1, z) == 78) return 0x10; return ancilData; - } else if (state->block == 8 || state->block == 9) { /* water */ + } else if (block_class_is_subset(state->block, (mc_block_t[]){block_flowing_water,block_water}, 2)) { /* water */ data = check_adjacent_blocks(state, x, y, z, state->block) ^ 0x0f; /* an aditional bit for top is added to the 4 bits of check_adjacent_blocks */ if (get_data(state, BLOCKS, x, y+1, z) != state->block) data |= 0x10; return data; - } else if ((state->block == 20) || (state->block == 79) || (state->block == 95)) { /* glass and ice and stained glass*/ + } else if (block_class_is_subset(state->block, (mc_block_t[]){block_glass,block_ice,block_stained_glass}, 3)) { /* glass and ice and stained glass*/ /* an aditional bit for top is added to the 4 bits of check_adjacent_blocks * Note that stained glass encodes 16 colors using 4 bits. this pushes us over the 8-bits of an unsigned char, * forcing us to use an unsigned short to hold 16 bits of pseudo ancil data @@ -300,14 +276,13 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { } data = (check_adjacent_blocks(state, x, y, z, state->block) ^ 0x0f) | data; return (data << 4) | (ancilData & 0x0f); - } else if ((state->block == 85) || (state->block == 188) || (state->block == 189) || - (state->block == 190) || (state->block == 191) || (state->block == 192)) { /* fences */ + } else if (block_class_is_subset(state->block, block_class_fence, block_class_fence_len)) { /* fences */ /* check for fences AND fence gates */ - return check_adjacent_blocks(state, x, y, z, state->block) | check_adjacent_blocks(state, x, y, z, 107) | - check_adjacent_blocks(state, x, y, z, 183) | check_adjacent_blocks(state, x, y, z, 184) | check_adjacent_blocks(state, x, y, z, 185) | - check_adjacent_blocks(state, x, y, z, 186) | check_adjacent_blocks(state, x, y, z, 187); + return check_adjacent_blocks(state, x, y, z, state->block) | check_adjacent_blocks(state, x, y, z, block_fence_gate) | + check_adjacent_blocks(state, x, y, z, block_fence_gate) | check_adjacent_blocks(state, x, y, z, block_birch_fence_gate) | check_adjacent_blocks(state, x, y, z, block_jungle_fence_gate) | + check_adjacent_blocks(state, x, y, z, block_dark_oak_fence_gate) | check_adjacent_blocks(state, x, y, z, block_acacia_fence_gate); - } else if (state->block == 55) { /* redstone */ + } else if (state->block == block_redstone_wire) { /* redstone */ /* three addiotional bit are added, one for on/off state, and * another two for going-up redstone wire in the same block * (connection with the level y+1) */ @@ -341,7 +316,7 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { } return final_data; - } else if (state->block == 54 || state->block == 146) { /* normal chests and trapped chests */ + } else if (block_class_is_subset(state->block, (mc_block_t[]){block_chest,block_trapped_chest}, 2)) { /* Orientation is given by ancilData, pseudo data needed to * choose from single or double chest and the correct half of * the chest. */ @@ -378,7 +353,7 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { } return final_data; - } else if ((state->block == 101) || (state->block == 102) || (state->block == 160)) { + } else if (block_class_is_subset(state->block, (mc_block_t[]){block_iron_bars,block_glass_pane, block_stained_glass_pane},3)) { /* iron bars and glass panes: * they seem to stick to almost everything but air, * not sure yet! Still a TODO! */ @@ -387,13 +362,11 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { data = (check_adjacent_blocks(state, x, y, z, 0) ^ 0x0f); return (data << 4) | (ancilData & 0xf); - } else if ((state->block == 90) || (state->block == 113)) { + } else if (block_class_is_subset(state->block, (mc_block_t[]){block_portal,block_nether_brick_fence}, 2)) { /* portal and nether brick fences */ return check_adjacent_blocks(state, x, y, z, state->block); - } else if ((state->block == 64) || (state->block == 71) || (state->block == 193) || - (state->block == 194) || (state->block == 195) || (state->block == 196) || - (state->block ==197)) { + } else if (block_class_is_subset(state->block, block_class_door, block_class_door_len)) { /* use bottom block data format plus one bit for top/down * block (0x8) and one bit for hinge position (0x10) */ @@ -419,14 +392,14 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { } return data; - } else if (state->block == 139) { /* cobblestone and mossy cobbleston wall */ + } else if (state->block == block_cobblestone_wall) { /* check for walls and add one bit with the type of wall (mossy or cobblestone)*/ if (ancilData == 0x1) { return check_adjacent_blocks(state, x, y, z, state->block) | 0x10; } else { return check_adjacent_blocks(state, x, y, z, state->block); } - } else if (state->block == 111) { /* lilypads */ + } else if (state->block == block_waterlily) { int wx,wz,wy,rotation; long pr; /* calculate the global block coordinates of this position */ @@ -440,7 +413,7 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { pr = pr * pr * 42317861 + pr * 11; rotation = 3 & (pr >> 16); return rotation; - } else if (is_stairs(state->block)) { /* stairs */ + } else if (block_class_is_subset(state->block, block_class_stair, block_class_stair_len)) { /* stairs */ /* 4 ancillary bits will be added to indicate which quarters of the block contain the * upper step. Regular stairs will have 2 bits set & corner stairs will have 1 or 3. * Southwest quarter is part of the upper step - 0x40 @@ -497,10 +470,10 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { /* get block & data for neighbors in this order: east, north, west, south */ /* so we can rotate things easily */ - stairs[0] = stairs[4] = is_stairs(get_data(state, BLOCKS, x+1, y, z)); - stairs[1] = stairs[5] = is_stairs(get_data(state, BLOCKS, x, y, z-1)); - stairs[2] = stairs[6] = is_stairs(get_data(state, BLOCKS, x-1, y, z)); - stairs[3] = stairs[7] = is_stairs(get_data(state, BLOCKS, x, y, z+1)); + stairs[0] = stairs[4] = block_class_is_subset(get_data(state, BLOCKS, x+1, y, z), block_class_stair, block_class_stair_len); + stairs[1] = stairs[5] = block_class_is_subset(get_data(state, BLOCKS, x, y, z-1), block_class_stair, block_class_stair_len); + stairs[2] = stairs[6] = block_class_is_subset(get_data(state, BLOCKS, x-1, y, z), block_class_stair, block_class_stair_len); + stairs[3] = stairs[7] = block_class_is_subset(get_data(state, BLOCKS, x, y, z+1), block_class_stair, block_class_stair_len); neigh[0] = neigh[4] = FIX_ROT(get_data(state, DATA, x+1, y, z)); neigh[1] = neigh[5] = FIX_ROT(get_data(state, DATA, x, y, z-1)); neigh[2] = neigh[6] = FIX_ROT(get_data(state, DATA, x-1, y, z)); @@ -546,11 +519,11 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) { } return ancilData; - } else if (state->block == 175) { /* doublePlants */ + } else if (state->block == block_double_plant) { /* doublePlants */ /* use bottom block data format plus one bit for top * block (0x8) */ - if( get_data(state, BLOCKS, x, y-1, z) == 175 ) { + if( get_data(state, BLOCKS, x, y-1, z) == block_double_plant ) { data = get_data(state, DATA, x, y-1, z) | 0x8; } else { data = ancilData; @@ -662,10 +635,9 @@ chunk_render(PyObject *self, PyObject *args) { unsigned short ancilData; state.imgy -= 12; - /* get blockid */ state.block = getArrayShort3D(blocks_py, state.x, state.y, state.z); - if (state.block == 0 || render_mode_hidden(rendermode, state.x, state.y, state.z)) { + if (state.block == block_air || render_mode_hidden(rendermode, state.x, state.y, state.z)) { continue; } @@ -697,25 +669,7 @@ chunk_render(PyObject *self, PyObject *args) { * grass, water, glass, chest, restone wire, * ice, fence, portal, iron bars, glass panes, * trapped chests, stairs */ - if ((state.block == 2) || - (state.block == 8) || (state.block == 9) || - (state.block == 20) || (state.block == 54) || - (state.block == 55) || - /* doors */ - (state.block == 64) || (state.block == 193) || - (state.block == 194) || (state.block == 195) || - (state.block == 196) || (state.block == 197) || - (state.block == 71) || /* end doors */ - (state.block == 79) || - (state.block == 85) || (state.block == 90) || - (state.block == 101) || (state.block == 102) || - (state.block == 111) || (state.block == 113) || - (state.block == 139) || (state.block == 175) || - (state.block == 160) || (state.block == 95) || - (state.block == 146) || (state.block == 188) || - (state.block == 189) || (state.block == 190) || - (state.block == 191) || (state.block == 192) || - is_stairs(state.block)) { + 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 { @@ -737,7 +691,7 @@ chunk_render(PyObject *self, PyObject *args) { if (t != NULL && t != Py_None) { PyObject *src, *mask, *mask_light; - int do_rand = (state.block == 31 /*|| state.block == 38 || state.block == 175*/); + int do_rand = (state.block == block_tallgrass /*|| state.block == block_red_flower || state.block == block_double_plant*/); int randx = 0, randy = 0; src = PyTuple_GetItem(t, 0); mask = PyTuple_GetItem(t, 0); @@ -761,7 +715,7 @@ chunk_render(PyObject *self, PyObject *args) { state.imgx -= randx; state.imgy -= randy; } - } + } } } } diff --git a/overviewer_core/src/mc_id.h b/overviewer_core/src/mc_id.h new file mode 100644 index 0000000..fb46e8d --- /dev/null +++ b/overviewer_core/src/mc_id.h @@ -0,0 +1,502 @@ +#ifndef __MC_ID_H_INCLUDED__ +#define __MC_ID_H_INCLUDED__ + +#include + +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, + block_log = 17, + block_leaves = 18, + block_sponge = 19, + block_glass = 20, + 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, + block_sticky_piston = 29, + block_web = 30, + block_tallgrass = 31, + 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, + block_red_mushroom = 40, + block_gold_block = 41, + 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, + block_oak_stairs = 53, + block_chest = 54, + 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, + block_lit_furnace = 62, + block_standing_sign = 63, + block_wooden_door = 64, + block_ladder = 65, + block_rail = 66, + block_stone_stairs = 67, + block_wall_sign = 68, + block_lever = 69, + block_stone_pressure_plate = 70, + 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, + block_unpowered_repeater = 93, + block_powered_repeater = 94, + block_stained_glass = 95, + block_trapdoor = 96, + block_monster_egg = 97, + block_stonebrick = 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, + block_enchanting_table = 116, + block_brewing_stand = 117, + 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, + block_sandstone_stairs = 128, + block_emerald_ore = 129, + 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_cobblestone_wall = 139, + block_flower_pot = 140, + block_carrots = 141, + block_potatoes = 142, + block_wooden_button = 143, + block_skull = 144, + block_anvil = 145, + block_trapped_chest = 146, + block_light_weighted_pressure_plate = 147, + block_heavy_weighted_pressure_plate = 148, + 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, + block_acacia_stairs = 163, + block_dark_oak_stairs = 164, + 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_double_stone_slab2 = 181, + block_stone_slab2 = 182, + block_spruce_fence_gate = 183, + block_birch_fence_gate = 184, + block_jungle_fence_gate = 185, + block_dark_oak_fence_gate = 186, + block_acacia_fence_gate = 187, + block_spruce_fence = 188, + block_birch_fence = 189, + block_jungle_fence = 190, + block_dark_oak_fence = 191, + block_acacia_fence = 192, + block_spruce_door = 193, + block_birch_door = 194, + block_jungle_door = 195, + block_acacia_door = 196, + 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, + block_purpur_slab = 205, + block_end_bricks = 206, + block_beetroots = 207, + block_grass_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, + block_white_shulker_box = 219, + block_orange_shulker_box = 220, + block_magenta_shulker_box = 221, + block_light_blue_shulker_box = 222, + block_yellow_shulker_box = 223, + block_lime_shulker_box = 224, + block_pink_shulker_box = 225, + block_gray_shulker_box = 226, + block_silver_shulker_box = 227, + block_cyan_shulker_box = 228, + block_purple_shulker_box = 229, + block_blue_shulker_box = 230, + block_brown_shulker_box = 231, + block_green_shulker_box = 232, + block_red_shulker_box = 233, + block_black_shulker_box = 234, + block_white_glazed_terracotta = 235, + block_orange_glazed_terracotta = 236, + block_magenta_glazed_terracotta = 237, + block_light_blue_glazed_terracotta = 238, + block_yellow_glazed_terracotta = 239, + block_lime_glazed_terracotta = 240, + block_pink_glazed_terracotta = 241, + block_gray_glazed_terracotta = 242, + block_light_gray_glazed_terracotta = 243, + block_cyan_glazed_terracotta = 244, + block_purple_glazed_terracotta = 245, + block_blue_glazed_terracotta = 246, + block_brown_glazed_terracotta = 247, + 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_prismarine_stairs = 11337, + block_dark_prismarine_stairs = 11338, + block_prismarine_brick_stairs = 11339, + block_prismarine_slab = 11340, + block_dark_prismarine_slab = 11341, + block_prismarine_brick_slab = 11342, + block_andesite_slab = 11343, + block_diorite_slab = 11344, + block_granite_slab = 11345, + block_polished_andesite_slab = 11346, + block_polished_diorite_slab = 11347, + block_polished_granite_slab = 11348, + block_red_nether_brick_slab = 11349, + block_smooth_sandstone_slab = 11350, + block_cut_sandstone_slab = 11351, + block_smooth_red_sandstone_slab = 11352, + block_cut_red_sandstone_slab = 11353, + block_end_stone_brick_slab = 11354, + block_mossy_cobblestone_slab = 11355, + block_mossy_stone_brick_slab = 11356, + block_smooth_quartz_slab = 11357, + block_smooth_stone_slab = 11358, +}; + +typedef uint16_t mc_block_t; + + +enum mc_item_id +{ + item_iron_shovel = 256, + item_iron_pickaxe = 257, + item_iron_axe = 258, + item_flint_and_steel = 259, + item_apple = 260, + item_bow = 261, + item_arrow = 262, + item_coal = 263, + item_diamond = 264, + item_iron_ingot = 265, + item_gold_ingot = 266, + item_iron_sword = 267, + item_wooden_sword = 268, + item_wooden_shovel = 269, + item_wooden_pickaxe = 270, + item_wooden_axe = 271, + item_stone_sword = 272, + item_stone_shovel = 273, + item_stone_pickaxe = 274, + item_stone_axe = 275, + item_diamond_sword = 276, + item_diamond_shovel = 277, + item_diamond_pickaxe = 278, + item_diamond_axe = 279, + item_stick = 280, + item_bowl = 281, + item_mushroom_stew = 282, + item_golden_sword = 283, + item_golden_shovel = 284, + item_golden_pickaxe = 285, + item_golden_axe = 286, + item_string = 287, + item_feather = 288, + item_gunpowder = 289, + item_wooden_hoe = 290, + item_stone_hoe = 291, + item_iron_hoe = 292, + item_diamond_hoe = 293, + item_golden_hoe = 294, + item_wheat_seeds = 295, + item_wheat = 296, + item_bread = 297, + item_leather_helmet = 298, + item_leather_chestplate = 299, + item_leather_leggings = 300, + item_leather_boots = 301, + item_chainmail_helmet = 302, + item_chainmail_chestplate = 303, + item_chainmail_leggings = 304, + item_chainmail_boots = 305, + item_iron_helmet = 306, + item_iron_chestplate = 307, + item_iron_leggings = 308, + item_iron_boots = 309, + item_diamond_helmet = 310, + item_diamond_chestplate = 311, + item_diamond_leggings = 312, + item_diamond_boots = 313, + item_golden_helmet = 314, + item_golden_chestplate = 315, + item_golden_leggings = 316, + item_golden_boots = 317, + item_flint = 318, + item_porkchop = 319, + item_cooked_porkchop = 320, + item_painting = 321, + item_golden_apple = 322, + item_sign = 323, + item_wooden_door = 324, + item_bucket = 325, + item_water_bucket = 326, + item_lava_bucket = 327, + item_minecart = 328, + item_saddle = 329, + item_iron_door = 330, + item_redstone = 331, + item_snowball = 332, + item_boat = 333, + item_leather = 334, + item_milk_bucket = 335, + item_brick = 336, + item_clay_ball = 337, + item_reeds = 338, + item_paper = 339, + item_book = 340, + item_slime_ball = 341, + item_chest_minecart = 342, + item_furnace_minecart = 343, + item_egg = 344, + item_compass = 345, + item_fishing_rod = 346, + item_clock = 347, + item_glowstone_dust = 348, + item_fish = 349, + item_cooked_fish = 350, + item_dye = 351, + item_bone = 352, + item_sugar = 353, + item_cake = 354, + item_bed = 355, + item_repeater = 356, + item_cookie = 357, + item_filled_map = 358, + item_shears = 359, + item_melon = 360, + item_pumpkin_seeds = 361, + item_melon_seeds = 362, + item_beef = 363, + item_cooked_beef = 364, + item_chicken = 365, + item_cooked_chicken = 366, + item_rotten_flesh = 367, + item_ender_pearl = 368, + item_blaze_rod = 369, + item_ghast_tear = 370, + item_gold_nugget = 371, + item_nether_wart = 372, + item_potion = 373, + item_glass_bottle = 374, + item_spider_eye = 375, + item_fermented_spider_eye = 376, + item_blaze_powder = 377, + item_magma_cream = 378, + item_brewing_stand = 379, + item_cauldron = 380, + item_ender_eye = 381, + item_speckled_melon = 382, + item_spawn_egg = 383, + item_experience_bottle = 384, + item_fire_charge = 385, + item_writable_book = 386, + item_written_book = 387, + item_emerald = 388, + item_item_frame = 389, + item_flower_pot = 390, + item_carrot = 391, + item_potato = 392, + item_baked_potato = 393, + item_poisonous_potato = 394, + item_map = 395, + item_golden_carrot = 396, + item_skull = 397, + item_carrot_on_a_stick = 398, + item_nether_star = 399, + item_pumpkin_pie = 400, + item_fireworks = 401, + item_firework_charge = 402, + item_enchanted_book = 403, + item_comparator = 404, + item_netherbrick = 405, + item_quartz = 406, + item_tnt_minecart = 407, + item_hopper_minecart = 408, + item_prismarine_shard = 409, + item_prismarine_crystals = 410, + item_rabbit = 411, + item_cooked_rabbit = 412, + item_rabbit_stew = 413, + item_rabbit_foot = 414, + item_rabbit_hide = 415, + item_armor_stand = 416, + item_iron_horse_armor = 417, + item_golden_horse_armor = 418, + item_diamond_horse_armor = 419, + item_lead = 420, + item_name_tag = 421, + item_command_block_minecart = 422, + item_mutton = 423, + item_cooked_mutton = 424, + item_banner = 425, + item_end_crystal = 426, + item_spruce_door = 427, + item_birch_door = 428, + item_jungle_door = 429, + item_acacia_door = 430, + item_dark_oak_door = 431, + item_chorus_fruit = 432, + item_popped_chorus_fruit = 433, + item_beetroot = 434, + item_beetroot_seeds = 435, + item_beetroot_soup = 436, + item_dragon_breath = 437, + item_splash_potion = 438, + item_spectral_arrow = 439, + item_tipped_arrow = 440, + item_lingering_potion = 441, + item_shield = 442, + item_elytra = 443, + item_spruce_boat = 444, + item_birch_boat = 445, + item_jungle_boat = 446, + item_acacia_boat = 447, + item_dark_oak_boat = 448, + item_totem_of_undying = 449, + item_shulker_shell = 450, + item_iron_nugget = 452, + item_knowledge_book = 453, + item_record_13 = 2256, + item_record_cat = 2257, + item_record_blocks = 2258, + item_record_chirp = 2259, + item_record_far = 2260, + item_record_mall = 2261, + item_record_mellohi = 2262, + item_record_stal = 2263, + item_record_strad = 2264, + item_record_ward = 2265, + item_record_11 = 2266, + item_record_wait = 2267 +}; + +typedef uint16_t mc_item_t; +#endif diff --git a/overviewer_core/src/overviewer.h b/overviewer_core/src/overviewer.h index 5f8001b..85e0793 100644 --- a/overviewer_core/src/overviewer.h +++ b/overviewer_core/src/overviewer.h @@ -33,7 +33,7 @@ // increment this value if you've made a change to the c extesion // and want to force users to rebuild -#define OVERVIEWER_EXTENSION_VERSION 57 +#define OVERVIEWER_EXTENSION_VERSION 62 /* Python PIL, and numpy headers */ #include diff --git a/overviewer_core/src/primitives/base.c b/overviewer_core/src/primitives/base.c index 7e24d0f..d7207d4 100644 --- a/overviewer_core/src/primitives/base.c +++ b/overviewer_core/src/primitives/base.c @@ -16,6 +16,8 @@ */ #include "../overviewer.h" +#include "../mc_id.h" +#include "../block_class.h" #include "biomes.h" typedef struct { @@ -75,7 +77,7 @@ base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObjec PrimitiveBase *self = (PrimitiveBase *)data; /* in order to detect top parts of doublePlant grass & ferns */ - unsigned char below_block = get_data(state, BLOCKS, state->x, state->y-1, state->z); + unsigned short below_block = get_data(state, BLOCKS, state->x, state->y-1, state->z); unsigned char below_data = get_data(state, DATA, state->x, state->y-1, state->z); /* draw the block! */ @@ -93,24 +95,25 @@ 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 == 2 && get_data(state, BLOCKS, state->x, state->y+1, state->z) != 78) || - /* water */ - state->block == 8 || state->block == 9 || - /* leaves */ - state->block == 18 || state->block == 161 || + (state->block == block_grass && get_data(state, BLOCKS, state->x, state->y+1, state->z) != 78) || + 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 */ - (state->block == 31 && state->block_data != 0) || + (state->block == block_tallgrass && state->block_data != 0) || /* pumpkin/melon stem, not fully grown. Fully grown stems * get constant brown color (see textures.py) */ - (((state->block == 104) || (state->block == 105)) && (state->block_data != 7)) || - /* vines */ - state->block == 106 || - /* lily pads */ - state->block == 111 || + (((state->block == block_pumpkin_stem) || (state->block == block_melon_stem)) && (state->block_data != 7)) || /* doublePlant grass & ferns */ - (state->block == 175 && (state->block_data == 2 || state->block_data == 3)) || + (state->block == block_double_plant && (state->block_data == 2 || state->block_data == 3)) || /* doublePlant grass & ferns tops */ - (state->block == 175 && below_block == 175 && (below_data == 2 || below_data == 3)) ) + (state->block == block_double_plant && below_block == block_double_plant && (below_data == 2 || below_data == 3)) ) { /* do the biome stuff! */ PyObject *facemask = mask; @@ -118,24 +121,29 @@ base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObjec PyObject *color_table = NULL; unsigned char flip_xy = 0; - if (state->block == 2) { + if (state->block == block_grass) { /* grass needs a special facemask */ facemask = self->grass_texture; } - - switch (state->block) { - case 2: - /* grass */ + if(block_class_is_subset(state->block, (mc_block_t[]){ + block_grass, + block_tallgrass, + block_pumpkin_stem, + block_melon_stem, + block_vine, + block_waterlily, + block_double_plant + },7)) { color_table = self->grasscolor; - break; - case 8: - case 9: - /* water */ + } + else if(block_class_is_subset(state->block, (mc_block_t[]){ + block_flowing_water,block_water + },2)) { color_table = self->watercolor; - break; - case 18: - case 161: - /* leaves */ + } + else if(block_class_is_subset(state->block, (mc_block_t[]){ + block_leaves,block_leaves2 + },2)) { color_table = self->foliagecolor; if (state->block_data == 2) { @@ -143,34 +151,7 @@ base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObjec birch foliage color is flipped XY-ways */ flip_xy = 1; } - break; - case 31: - /* tall grass */ - color_table = self->grasscolor; - break; - case 104: - /* pumpkin stem */ - color_table = self->grasscolor; - break; - case 105: - /* melon stem */ - color_table = self->grasscolor; - break; - case 106: - /* vines */ - color_table = self->grasscolor; - break; - case 111: - /* lily pads */ - color_table = self->grasscolor; - break; - case 175: - /* doublePlant grass & ferns */ - color_table = self->grasscolor; - break; - default: - break; - }; + } if (color_table) { unsigned char biome; diff --git a/overviewer_core/src/primitives/edge-lines.c b/overviewer_core/src/primitives/edge-lines.c index a82624f..0b5d18a 100644 --- a/overviewer_core/src/primitives/edge-lines.c +++ b/overviewer_core/src/primitives/edge-lines.c @@ -16,6 +16,8 @@ */ #include "../overviewer.h" +#include "../mc_id.h" +#include "../block_class.h" typedef struct { float opacity; @@ -34,16 +36,17 @@ edge_lines_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, P PrimitiveEdgeLines *self = (PrimitiveEdgeLines *)data; /* Draw some edge lines! */ - if (state->block == 44 || state->block == 78 || !is_transparent(state->block)) { + if (block_class_is_subset(state->block, (mc_block_t[]){block_stone_slab,block_snow_layer}, 2) + || !is_transparent(state->block)) { Imaging img_i = imaging_python_to_c(state->img); unsigned char ink[] = {0, 0, 0, 255 * self->opacity}; unsigned short side_block; int x = state->x, y = state->y, z = state->z; int increment=0; - if ((state->block == 44 || state->block == 126) && ((state->block_data & 0x8) == 0 )) // half-steps BUT no upsidown half-steps + if (block_class_is_subset(state->block, (mc_block_t[]){block_wooden_slab,block_stone_slab}, 2) && ((state->block_data & 0x8) == 0 )) // half-steps BUT no upsidown half-steps increment=6; - else if ((state->block == 78) || (state->block == 93) || (state->block == 94)) // snow, redstone repeaters (on and off) + else if (block_class_is_subset(state->block, (mc_block_t[]){block_snow_layer,block_unpowered_repeater,block_powered_repeater}, 3)) // snow, redstone repeaters (on and off) increment=9; /* +X side */ @@ -51,9 +54,9 @@ edge_lines_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, P if (side_block != state->block && (is_transparent(side_block) || render_mode_hidden(state->rendermode, x+1, y, z)) && /* WARNING: ugly special case approaching */ /* if the block is a slab and the side block is a stair don't draw anything, it can give very ugly results */ - !((state->block == 44 || state->block == 126) && ((side_block == 53) || (side_block == 67) || (side_block == 108) || - (side_block == 109) || (side_block == 114) || (side_block == 128) || (side_block == 134) || (side_block == 135) || - (side_block == 136)))) { + !(block_class_is_subset(state->block, (mc_block_t[]){block_wooden_slab, block_stone_slab}, 2) + && (block_class_is_subset(side_block, block_class_stair, block_class_stair_len)) + )) { ImagingDrawLine(img_i, state->imgx+12, state->imgy+1+increment, state->imgx+22+1, state->imgy+5+1+increment, &ink, 1); ImagingDrawLine(img_i, state->imgx+12, state->imgy+increment, state->imgx+22+1, state->imgy+5+increment, &ink, 1); } @@ -63,9 +66,10 @@ edge_lines_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, P if (side_block != state->block && (is_transparent(side_block) || render_mode_hidden(state->rendermode, x, y, z-1)) && /* WARNING: ugly special case approaching */ /* if the block is a slab and the side block is a stair don't draw anything, it can give very ugly results */ - !((state->block == 44 || state->block == 126) && ((side_block == 53) || (side_block == 67) || (side_block == 108) || - (side_block == 109) || (side_block == 114) || (side_block == 128) || (side_block == 134) || (side_block == 135) || - (side_block == 136)))) { + !( + block_class_is_subset(state->block, (mc_block_t[]){block_stone_slab,block_wooden_slab}, 2) + && (block_class_is_subset(side_block, block_class_stair, block_class_stair_len)) + )) { ImagingDrawLine(img_i, state->imgx, state->imgy+6+1+increment, state->imgx+12+1, state->imgy+1+increment, &ink, 1); ImagingDrawLine(img_i, state->imgx, state->imgy+6+increment, state->imgx+12+1, state->imgy+increment, &ink, 1); } diff --git a/overviewer_core/src/primitives/hide.c b/overviewer_core/src/primitives/hide.c index 6f06c8b..86d4def 100644 --- a/overviewer_core/src/primitives/hide.c +++ b/overviewer_core/src/primitives/hide.c @@ -16,6 +16,7 @@ */ #include "../overviewer.h" +#include "../mc_id.h" struct HideRule { unsigned short blockid; @@ -90,7 +91,7 @@ hide_hidden(void *data, RenderState *state, int x, int y, int z) { return 0; block = get_data(state, BLOCKS, x, y, z); - for (i = 0; self->rules[i].blockid != 0; i++) { + for (i = 0; self->rules[i].blockid != block_air; i++) { if (block == self->rules[i].blockid) { unsigned char data; diff --git a/overviewer_core/src/primitives/lighting.c b/overviewer_core/src/primitives/lighting.c index 40257a2..f332ce3 100644 --- a/overviewer_core/src/primitives/lighting.c +++ b/overviewer_core/src/primitives/lighting.c @@ -16,6 +16,8 @@ */ #include "../overviewer.h" +#include "../mc_id.h" +#include "../block_class.h" #include "lighting.h" #include @@ -100,7 +102,8 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state, int x, int y, int z, int *authoratative) { /* placeholders for later data arrays, coordinates */ - unsigned char block, blocklevel; + unsigned short block; + unsigned char blocklevel; unsigned int average_count = 0, average_gather = 0, coeff = 0; /* defaults to "guess" until told otherwise */ @@ -138,7 +141,7 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state, blocklevel = get_data(state, BLOCKLIGHT, x, y, z); /* no longer a guess */ - if (!(block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 180 || block == 182 || block == 205) && authoratative) { + if (!block_class_is_subset(block, block_class_alt_height, block_class_alt_height_len) && authoratative) { *authoratative = 1; } @@ -151,7 +154,8 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state, unsigned char *r, unsigned char *g, unsigned char *b) { /* placeholders for later data arrays, coordinates */ - unsigned char block, skylevel, blocklevel; + unsigned short block; + unsigned char skylevel, blocklevel; block = get_data(state, BLOCKS, x, y, z); skylevel = get_data(state, SKYLIGHT, x, y, z); @@ -159,9 +163,7 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state, /* special half-step handling, stairs handling */ /* Anvil also needs to be here, blockid 145 */ - if (block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 114 || - block == 128 || block == 134 || block == 135 || block == 136 || block == 145 || block == 156 || - block == 163 || block == 164 || block == 180 || block == 182 || block == 203 || block == 205) { + if ( block_class_is_subset(block, block_class_alt_height, block_class_alt_height_len) || block == block_anvil) { unsigned int upper_block; /* stairs and half-blocks take the skylevel from the upper block if it's transparent */ @@ -170,10 +172,7 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state, do { upper_counter++; upper_block = get_data(state, BLOCKS, x, y + upper_counter, z); - } while (upper_block == 44 || upper_block == 53 || upper_block == 67 || upper_block == 108 || - upper_block == 109 || upper_block == 114 || upper_block == 128 || upper_block == 134 || - upper_block == 135 || upper_block == 136 || upper_block == 156 || upper_block == 163 || - upper_block == 164 || upper_block == 180 || upper_block == 182 || upper_block == 203 || upper_block == 205); + } while (block_class_is_subset(upper_block, block_class_alt_height, block_class_alt_height_len)); if (is_transparent(upper_block)) { skylevel = get_data(state, SKYLIGHT, x, y + upper_counter, z); } else { @@ -186,7 +185,7 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state, } - if (block == 10 || block == 11) { + if (block_class_is_subset(block, (mc_block_t[]){block_flowing_lava,block_lava}, 2)) { /* lava blocks should always be lit! */ *r = 255; *g = 255; @@ -305,7 +304,7 @@ lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyO self = (RenderPrimitiveLighting *)data; x = state->x, y = state->y, z = state->z; - if ((state->block == 8) || (state->block == 9)) { /* special case for water */ + if (block_class_is_subset(state->block, (mc_block_t[]){block_flowing_water,block_water}, 2)) { /* special case for water */ /* looks like we need a new case for lighting, there are * blocks that are transparent for occlusion calculations and * need per-face shading if the face is drawn. */ diff --git a/overviewer_core/src/primitives/nether.c b/overviewer_core/src/primitives/nether.c index c086dd8..50acf1a 100644 --- a/overviewer_core/src/primitives/nether.c +++ b/overviewer_core/src/primitives/nether.c @@ -16,6 +16,8 @@ */ #include "../overviewer.h" +#include "../mc_id.h" +#include "../block_class.h" #include "nether.h" static void @@ -26,16 +28,16 @@ walk_chunk(RenderState *state, RenderPrimitiveNether *data) { for (x = -1; x < WIDTH + 1; x++) { for (z = -1; z < DEPTH + 1; z++) { id = get_data(state, BLOCKS, x, NETHER_ROOF - (state->chunky * 16), z); - if (id == 7) { + if (id == block_bedrock) { data->remove_block[x+1][NETHER_ROOF][z+1] = 1; id = get_data(state, BLOCKS, x, (NETHER_ROOF + 1) - (state->chunky * 16), z); - if (id == 39 || id == 40) + if (id == block_brown_mushroom || id == block_red_mushroom) data->remove_block[x+1][NETHER_ROOF + 1][z+1] = 1; } for (y = NETHER_ROOF-1; y>=0; y--) { id = get_data(state, BLOCKS, x, y - (state->chunky * 16), z); - if (id == 7 || id == 87 || id == 153 || id == 11) + if (block_class_is_subset(id, (mc_block_t[]){block_bedrock,block_netherrack,block_quartz_ore,block_lava}, 4)) data->remove_block[x+1][y][z+1] = 1; else break; diff --git a/overviewer_core/src/primitives/overlay-mineral.c b/overviewer_core/src/primitives/overlay-mineral.c index d831419..e7cd203 100644 --- a/overviewer_core/src/primitives/overlay-mineral.c +++ b/overviewer_core/src/primitives/overlay-mineral.c @@ -16,6 +16,7 @@ */ #include "overlay.h" +#include "../mc_id.h" typedef struct { /* inherits from overlay */ @@ -31,17 +32,17 @@ struct MineralColor { /* put more valuable ores first -- they take precedence */ static struct MineralColor default_minerals[] = { - {48 /* Mossy Stone */, 31, 153, 9}, + {block_mossy_cobblestone, 31, 153, 9}, - {56 /* Diamond Ore */, 32, 230, 220}, + {block_diamond_ore, 32, 230, 220}, - {21 /* Lapis Lazuli */, 0, 23, 176}, - {14 /* Gold Ore */, 255, 234, 0}, + {block_lapis_ore, 0, 23, 176}, + {block_gold_ore, 255, 234, 0}, - {15 /* Iron Ore */, 204, 204, 204}, - {73 /* Redstone */, 186, 0, 0}, - {74 /* Lit Redstone */, 186, 0, 0}, - {16 /* Coal Ore */, 54, 54, 54}, + {block_iron_ore, 204, 204, 204}, + {block_redstone_ore, 186, 0, 0}, + {block_lit_redstone_ore, 186, 0, 0}, + {block_coal_ore, 54, 54, 54}, /* end of list marker */ {0, 0, 0, 0} @@ -61,7 +62,7 @@ static void get_color(void *data, RenderState *state, int i, tmp; unsigned short blockid = get_data(state, BLOCKS, x, y, z); - for (i = 0; (max_i == -1 || i < max_i) && minerals[i].blockid != 0; i++) { + for (i = 0; (max_i == -1 || i < max_i) && minerals[i].blockid != block_air; i++) { if (minerals[i].blockid == blockid) { *r = minerals[i].r; *g = minerals[i].g; diff --git a/overviewer_core/src/primitives/overlay-structure.c b/overviewer_core/src/primitives/overlay-structure.c index b0292cb..2c40607 100644 --- a/overviewer_core/src/primitives/overlay-structure.c +++ b/overviewer_core/src/primitives/overlay-structure.c @@ -16,6 +16,7 @@ */ #include "overlay.h" +#include "../mc_id.h" typedef enum { false, true } bool; @@ -28,7 +29,7 @@ typedef struct { struct Condition{ int relx, rely, relz; - unsigned char block; + unsigned short block; }; struct Color { diff --git a/overviewer_core/src/primitives/overlay.c b/overviewer_core/src/primitives/overlay.c index ff7ce75..8fce0bc 100644 --- a/overviewer_core/src/primitives/overlay.c +++ b/overviewer_core/src/primitives/overlay.c @@ -16,6 +16,7 @@ */ #include "overlay.h" +#include "../mc_id.h" static void get_color(void *data, RenderState *state, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a) { @@ -85,9 +86,9 @@ overlay_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyOb // exactly analogous to edge-line code for these special blocks int increment=0; - if (state->block == 44) // half-step + if (state->block == block_stone_slab) // half-step increment=6; - else if (state->block == 78) // snow + else if (state->block == block_snow_layer) // snow increment=9; /* skip rendering the overlay if we can't see it */ diff --git a/overviewer_core/src/primitives/smooth-lighting.c b/overviewer_core/src/primitives/smooth-lighting.c index e8cd369..f024b0d 100644 --- a/overviewer_core/src/primitives/smooth-lighting.c +++ b/overviewer_core/src/primitives/smooth-lighting.c @@ -16,6 +16,8 @@ */ #include "../overviewer.h" +#include "../mc_id.h" +#include "../block_class.h" #include "lighting.h" #include @@ -218,7 +220,9 @@ smooth_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *ma /* special case for leaves, water 8, water 9, ice 79 -- these are also smooth-lit! */ - if (state->block != 18 && state->block != 8 && state->block != 9 && state->block != 79 && is_transparent(state->block)) + if (!block_class_is_subset(state->block, (mc_block_t[]){ + block_leaves,block_flowing_water,block_water,block_ice + }, 4) && is_transparent(state->block)) { /* transparent blocks are rendered as usual, with flat lighting */ primitive_lighting.draw(data, state, src, mask, mask_light); @@ -228,7 +232,7 @@ smooth_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *ma /* non-transparent blocks get the special smooth treatment */ /* special code for water */ - if (state->block == 9) + if (state->block == block_water) { if (!(state->block_pdata & (1 << 4))) light_top = 0; diff --git a/overviewer_core/src/utils.h b/overviewer_core/src/utils.h index 02108b5..431fcf3 100644 --- a/overviewer_core/src/utils.h +++ b/overviewer_core/src/utils.h @@ -14,4 +14,7 @@ #define OV_BLEND(mask, in1, in2, tmp1, tmp2)\ (OV_MULDIV255(in1, 255 - mask, tmp1) + OV_MULDIV255(in2, mask, tmp2)) +#define COUNT_OF(array) \ + (sizeof(array) / sizeof(array[0])) + #endif diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 01a04eb..114afd1 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -336,7 +336,7 @@ class Textures(object): if verbose: logging.info("Found %s in '%s'", filename, path) return open(path, mode) - 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.13-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)) + 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.14-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 load_image_texture(self, filename): # Textures may be animated or in a different resolution than 16x16. @@ -1720,8 +1720,9 @@ block(blockid=42, top_image="assets/minecraft/textures/block/iron_block.png") # double slabs and slabs # these wooden slabs are unobtainable without cheating, they are still -# here because lots of pre-1.3 worlds use this blocks -@material(blockid=[43, 44, 181, 182, 204, 205], data=list(range(16)), transparent=(44,182,205), solid=True) +# here because lots of pre-1.3 worlds use this blocks, add prismarine slabs +@material(blockid=[43, 44, 181, 182, 204, 205] + list(range(11340,11359)), data=list(range(16)), + transparent=[44, 182, 205] + list(range(11340,11359)), solid=True) def slabs(self, blockid, data): if blockid == 44 or blockid == 182: texture = data & 7 @@ -1730,8 +1731,8 @@ def slabs(self, blockid, data): if blockid == 44 or blockid == 43: if texture== 0: # stone slab - top = self.load_image_texture("assets/minecraft/textures/block/stone_slab_top.png") - side = self.load_image_texture("assets/minecraft/textures/block/stone_slab_side.png") + top = self.load_image_texture("assets/minecraft/textures/block/smooth_stone.png") + side = self.load_image_texture("assets/minecraft/textures/block/smooth_stone_slab_side.png") elif texture== 1: # sandstone slab top = self.load_image_texture("assets/minecraft/textures/block/sandstone_top.png") side = self.load_image_texture("assets/minecraft/textures/block/sandstone.png") @@ -1748,7 +1749,7 @@ def slabs(self, blockid, data): elif texture== 7: #quartz top = side = self.load_image_texture("assets/minecraft/textures/block/quartz_block_side.png") elif texture== 8: # special stone double slab with top texture only - top = side = self.load_image_texture("assets/minecraft/textures/block/stone_slab_top.png") + top = side = self.load_image_texture("assets/minecraft/textures/block/smooth_stone.png") elif texture== 9: # special sandstone double slab with top texture only top = side = self.load_image_texture("assets/minecraft/textures/block/sandstone_top.png") else: @@ -1772,7 +1773,46 @@ def slabs(self, blockid, data): elif blockid == 204 or blockid == 205: # purpur slab (single=205 double=204) top = side = self.load_image_texture("assets/minecraft/textures/block/purpur_block.png"); - + elif blockid == 11340: # prismarine slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/prismarine.png").copy() + elif blockid == 11341: # dark prismarine slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/dark_prismarine.png").copy() + elif blockid == 11342: # prismarine brick slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/prismarine_bricks.png").copy() + elif blockid == 11343: # andesite slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/andesite.png").copy() + elif blockid == 11344: # diorite slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/diorite.png").copy() + elif blockid == 11345: # granite slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/granite.png").copy() + elif blockid == 11346: # polished andesite slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/polished_andesite.png").copy() + elif blockid == 11347: # polished diorite slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/polished_diorite.png").copy() + elif blockid == 11348: # polished granite slabs + top = side = self.load_image_texture("assets/minecraft/textures/block/polished_granite.png").copy() + elif blockid == 11349: # red nether brick slab + top = side = self.load_image_texture("assets/minecraft/textures/block/red_nether_bricks.png").copy() + elif blockid == 11350: # smooth sandstone slab + top = side = self.load_image_texture("assets/minecraft/textures/block/sandstone_top.png").copy() + elif blockid == 11351: # cut sandstone slab + top = side = self.load_image_texture("assets/minecraft/textures/block/cut_sandstone.png").copy() + elif blockid == 11352: # smooth red sandstone slab + top = side = self.load_image_texture("assets/minecraft/textures/block/red_sandstone_top.png").copy() + elif blockid == 11353: # cut red sandstone slab + top = side = self.load_image_texture("assets/minecraft/textures/block/cut_red_sandstone.png").copy() + elif blockid == 11354: # end_stone_brick_slab + top = side = self.load_image_texture("assets/minecraft/textures/block/end_stone_bricks.png").copy() + elif blockid == 11355: # mossy_cobblestone_slab + top = side = self.load_image_texture("assets/minecraft/textures/block/mossy_cobblestone.png").copy() + elif blockid == 11356: # mossy_stone_brick_slab + top = side = self.load_image_texture("assets/minecraft/textures/block/mossy_stone_bricks.png").copy() + elif blockid == 11357: # smooth_quartz_slab + top = side = self.load_image_texture("assets/minecraft/textures/block/quartz_block_bottom.png").copy() + elif blockid == 11358: # smooth_stone_slab + top = self.load_image_texture("assets/minecraft/textures/block/smooth_stone.png").copy() + side = self.load_image_texture("assets/minecraft/textures/block/smooth_stone_slab_side.png").copy() + if blockid == 43 or blockid == 181 or blockid == 204: # double slab return self.build_block(top, side) @@ -1879,8 +1919,8 @@ def fire(self, blockid, data): # monster spawner block(blockid=52, top_image="assets/minecraft/textures/block/spawner.png", transparent=True) -# wooden, cobblestone, red brick, stone brick, netherbrick, sandstone, spruce, birch, jungle, quartz, and red sandstone stairs. -@material(blockid=[53,67,108,109,114,128,134,135,136,156,163,164,180,203], data=list(range(128)), transparent=True, solid=True, nospawn=True) +# wooden, cobblestone, red brick, stone brick, netherbrick, sandstone, spruce, birch, jungle, quartz, red sandstone and (dark) prismarine stairs. +@material(blockid=[53,67,108,109,114,128,134,135,136,156,163,164,180,203,11337,11338,11339], data=list(range(128)), transparent=True, solid=True, nospawn=True) def stairs(self, blockid, data): # preserve the upside-down bit upside_down = data & 0x4 @@ -1921,6 +1961,12 @@ def stairs(self, blockid, data): texture = self.load_image_texture("assets/minecraft/textures/block/red_sandstone.png").copy() elif blockid == 203: # purpur stairs texture = self.load_image_texture("assets/minecraft/textures/block/purpur_block.png").copy() + elif blockid == 11337: # prismarine stairs + texture = self.load_image_texture("assets/minecraft/textures/block/prismarine.png").copy() + elif blockid == 11338: # dark prismarine stairs + texture = self.load_image_texture("assets/minecraft/textures/block/dark_prismarine.png").copy() + elif blockid == 11339: # prismarine brick stairs + texture = self.load_image_texture("assets/minecraft/textures/block/prismarine_bricks.png").copy() outside_l = texture.copy() outside_r = texture.copy() @@ -2293,6 +2339,38 @@ def crafting_table(self, blockid, data): img = self.build_full_block(top, None, None, side3, side4, None) return img +# fletching table +@material(blockid=11359, solid=True, nodata=True) +def fletching_table(self, blockid, data): + top = self.load_image_texture("assets/minecraft/textures/block/fletching_table_top.png") + side3 = self.load_image_texture("assets/minecraft/textures/block/fletching_table_side.png") + side4 = self.load_image_texture("assets/minecraft/textures/block/fletching_table_front.png") + + img = self.build_full_block(top, None, None, side3, side4, None) + return img + +# cartography table +@material(blockid=11360, solid=True, nodata=True) +def cartography_table(self, blockid, data): + top = self.load_image_texture("assets/minecraft/textures/block/cartography_table_top.png") + side1 = self.load_image_texture("assets/minecraft/textures/block/cartography_table_side3.png") + side2 = side1 + side3 = self.load_image_texture("assets/minecraft/textures/block/cartography_table_side2.png") + side4 = self.load_image_texture("assets/minecraft/textures/block/cartography_table_side1.png").transpose(Image.FLIP_LEFT_RIGHT) + + img = self.build_full_block(top, side1, side2, side3, side4, None) + return img + +# smithing table +@material(blockid=11361, solid=True, nodata=True) +def smithing_table(self, blockid, data): + top = self.load_image_texture("assets/minecraft/textures/block/smithing_table_top.png") + side3 = self.load_image_texture("assets/minecraft/textures/block/smithing_table_side.png") + side4 = self.load_image_texture("assets/minecraft/textures/block/smithing_table_front.png") + + img = self.build_full_block(top, None, None, side3, side4, None) + return img + # crops with 8 data values (like wheat) @material(blockid=59, data=list(range(8)), transparent=True, nospawn=True) def crops8(self, blockid, data): @@ -3308,7 +3386,7 @@ def repeater(self, blockid, data): # generate the diode top = self.load_image_texture("assets/minecraft/textures/block/repeater.png") if blockid == 93 else self.load_image_texture("assets/minecraft/textures/block/repeater_on.png") - side = self.load_image_texture("assets/minecraft/textures/block/stone_slab_side.png") + side = self.load_image_texture("assets/minecraft/textures/block/smooth_stone_slab_side.png") increment = 13 if (data & 0x3) == 0: # pointing east @@ -3440,7 +3518,7 @@ def comparator(self, blockid, data): top = self.load_image_texture("assets/minecraft/textures/block/comparator.png") if blockid == 149 else self.load_image_texture("assets/minecraft/textures/block/comparator_on.png") - side = self.load_image_texture("assets/minecraft/textures/block/stone_slab_side.png") + side = self.load_image_texture("assets/minecraft/textures/block/smooth_stone_slab_side.png") increment = 13 if (data & 0x3) == 0: # pointing north @@ -4581,7 +4659,7 @@ block(blockid=174, top_image="assets/minecraft/textures/block/packed_ice.png") block(blockid=11312, top_image="assets/minecraft/textures/block/blue_ice.png") #smooth stones -block(blockid=11313, top_image="assets/minecraft/textures/block/stone_slab_top.png") # stone +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 diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 7f180b6..30ec225 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -134,11 +134,12 @@ class World(object): if mcas: # construct a regionset object for this rel = os.path.relpath(root, self.worlddir) - rset = RegionSet(root, rel) - if root == os.path.join(self.worlddir, "region"): - self.regionsets.insert(0, rset) - else: - self.regionsets.append(rset) + if rel != "poi": + rset = RegionSet(root, rel) + if root == os.path.join(self.worlddir, "region"): + self.regionsets.insert(0, rset) + else: + self.regionsets.append(rset) # TODO move a lot of the following code into the RegionSet @@ -272,7 +273,7 @@ class RegionSet(object): # this is the main world self.type = None else: - logging.warning("Unkown region type in %r", regiondir) + logging.warning("Unknown region type in %r", regiondir) self.type = "__unknown" logging.debug("Scanning regions. Type is %r" % self.type) @@ -623,7 +624,10 @@ class RegionSet(object): 'minecraft:standing_banner': (176, 0), 'minecraft:wall_banner': (177, 0), 'minecraft:red_sandstone': (179, 0), + 'minecraft:cut_red_sandstone': (179, 2), + 'minecraft:chiseled_red_sandstone': (179, 3), 'minecraft:red_sandstone_stairs': (180, 0), + 'minecraft:red_sandstone_slab': (182,0), 'minecraft:spruce_fence_gate': (183, 0), 'minecraft:birch_fence_gate': (184, 0), 'minecraft:jungle_fence_gate': (185, 0), @@ -770,6 +774,31 @@ class RegionSet(object): 'minecraft:acacia_trapdoor': (11335, 0), 'minecraft:dark_oak_trapdoor': (11336, 0), 'minecraft:petrified_oak_slab': (126, 0), + 'minecraft:prismarine_stairs': (11337, 0), + 'minecraft:dark_prismarine_stairs': (11338, 0), + 'minecraft:prismarine_brick_stairs': (11339,0), + 'minecraft:prismarine_slab': (11340, 0), + 'minecraft:dark_prismarine_slab': (11341, 0), + 'minecraft:prismarine_brick_slab': (11342, 0), + "minecraft:andesite_slab": (11343, 0), + "minecraft:diorite_slab": (11344, 0), + "minecraft:granite_slab": (11345, 0), + "minecraft:polished_andesite_slab": (11346, 0), + "minecraft:polished_diorite_slab": (11347, 0), + "minecraft:polished_granite_slab": (11348, 0), + "minecraft:red_nether_brick_slab": (11349, 0), + "minecraft:smooth_sandstone_slab": (11350, 0), + "minecraft:cut_sandstone_slab": (11351, 0), + "minecraft:smooth_red_sandstone_slab": (11352, 0), + "minecraft:cut_red_sandstone_slab": (11353, 0), + "minecraft:end_stone_brick_slab": (11354, 0), + "minecraft:mossy_cobblestone_slab": (11355, 0), + "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), } colors = [ 'white', 'orange', 'magenta', 'light_blue', @@ -795,6 +824,22 @@ class RegionSet(object): return "" % self.regiondir def _get_block(self, palette_entry): + wood_slabs = ('minecraft:oak_slab','minecraft:spruce_slab','minecraft:birch_slab','minecraft:jungle_slab', + 'minecraft:acacia_slab','minecraft:dark_oak_slab','minecraft:petrified_oak_slab') + stone_slabs = ('minecraft:stone_slab', 'minecraft:sandstone_slab','minecraft:red_sandstone_slab', + 'minecraft:cobblestone_slab', 'minecraft:brick_slab','minecraft:purpur_slab', + 'minecraft:stone_brick_slab', 'minecraft:nether_brick_slab', + 'minecraft:quartz_slab', "minecraft:andesite_slab", 'minecraft:diorite_slab', + 'minecraft:granite_slab', 'minecraft:polished_andesite_slab', + 'minecraft:polished_diorite_slab','minecraft:polished_granite_slab', + 'minecraft:red_nether_brick_slab','minecraft:smooth_sandstone_slab', + 'minecraft:cut_sandstone_slab','minecraft:smooth_red_sandstone_slab', + 'minecraft:cut_red_sandstone_slab','minecraft:end_stone_brick_slab', + 'minecraft:mossy_cobblestone_slab','minecraft:mossy_stone_brick_slab', + 'minecraft:smooth_quartz_slab','minecraft:smooth_stone_slab' + ) + prismarine_slabs = ('minecraft:prismarine_slab','minecraft:dark_prismarine_slab','minecraft:prismarine_brick_slab') + key = palette_entry['Name'] (block, data) = self._blockmap[key] if key in ['minecraft:redstone_ore', 'minecraft:redstone_lamp']: @@ -821,19 +866,95 @@ class RegionSet(object): elif key == 'minecraft:redstone_wire': data = palette_entry['Properties']['power'] elif key == 'minecraft:grass_block': - if palette_entry['Properties']['snowy']: - data = 0x10 + if palette_entry['Properties']['snowy'] == 'true': + data |= 0x10 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 ['minecraft:stone_slab', 'minecraft:sandstone_slab', 'minecraft:oak_slab', - 'minecraft:cobblestone_slab', 'minecraft:brick_slab', - 'minecraft:stone_brick_slab', 'minecraft:nether_brick_slab', - 'minecraft:quartz_slab', 'minecraft:petrified_oak_slab']: + elif key in wood_slabs + stone_slabs + prismarine_slabs: + # handle double slabs if palette_entry['Properties']['type'] == 'top': - data += 8 + data |= 0x08 elif palette_entry['Properties']['type'] == 'double': - block = 125 + if key in wood_slabs: + block = 125 # block_double_wooden_slab + elif key in stone_slabs: + if key == 'minecraft:stone_brick_slab': + block = 98 + elif key == 'minecraft:stone_slab': + block = 43 # block_double_stone_slab + elif key == 'minecraft:cobblestone_slab': + block = 4 # cobblestone + elif key == 'minecraft:sandstone_slab': + block = 24 # minecraft:sandstone + elif key == 'minecraft:red_sandstone_slab': + block = 179 # minecraft:red_sandstone + elif key == 'minecraft:nether_brick_slab': + block = 112 # minecraft:nether_bricks + elif key == 'minecraft:quartz_slab': + block = 155 # minecraft:quartz_block + elif key == 'minecraft:brick_slab': + block = 45 # minecraft:bricks + elif key == 'minecraft:purpur_slab': + block = 201 # minecraft:purpur_block + elif key == 'minecraft:andesite_slab': + block = 1 # minecraft:andesite + data = 5 + elif key == 'minecraft:diorite_slab': + block = 1 # minecraft:diorite + data = 3 + elif key == 'minecraft:granite_slab': + block = 1 # minecraft:granite + data = 1 + elif key == 'minecraft:polished_andesite_slab': + block = 1 # minecraft: polished_andesite + data = 6 + elif key == 'minecraft:polished_diorite_slab': + block = 1 # minecraft: polished_diorite + data = 4 + elif key == 'minecraft:polished_granite_slab': + block = 1 # minecraft: polished_granite + data = 2 + elif key == 'minecraft:red_nether_brick_slab': + block = 215 # minecraft: red_nether_brick + data = 0 + elif key == 'minecraft:smooth_sandstone_slab': + block = 11314 # minecraft: smooth_sandstone + data = 0 + elif key == 'minecraft:cut_sandstone_slab': + block = 24 # minecraft: cut_sandstone + data = 2 + elif key == 'minecraft:smooth_red_sandstone_slab': + block = 11315 # minecraft: smooth_red_sandstone + data = 0 + elif key == 'minecraft:cut_red_sandstone_slab': + block = 179 # minecraft: cut_red_sandstone + data = 2 + elif key == 'minecraft:end_stone_brick_slab': + block = 206 # minecraft:end_stone_bricks + data = 0 + elif key == 'minecraft:mossy_cobblestone_slab': + block = 48 # minecraft:mossy_cobblestone + data = 0 + elif key == 'minecraft:mossy_stone_brick_slab': + block = 98 # minecraft:mossy_stone_bricks + data = 1 + elif key == 'minecraft:smooth_quartz_slab': + block = 155 # minecraft:smooth_quartz + data = 0 + elif key == 'minecraft:smooth_stone_slab': + block = 11313 # minecraft:smooth_stone + data = 0 + + elif key in prismarine_slabs: + block = 168 # minecraft:prismarine variants + if key == 'minecraft:prismarine_slab': + data = 0 + elif key == 'minecraft:prismarine_brick_slab': + data = 1 + elif key == 'minecraft:dark_prismarine_slab': + data = 2 + elif key in ['minecraft:ladder', 'minecraft:chest', 'minecraft:ender_chest', 'minecraft:trapped_chest', 'minecraft:furnace']: facing = palette_entry['Properties']['facing'] data = {'north': 2, 'south': 3, 'west': 4, 'east': 5}[facing] @@ -920,10 +1041,12 @@ class RegionSet(object): if p['east'] == 'true': data |= 8 elif key.endswith('_stairs'): facing = palette_entry['Properties']['facing'] - if facing == 'south': data |= 0x60 - elif facing == 'east': data |= 0x30 - elif facing == 'north': data |= 0x18 - elif facing == 'west': data |= 0x48 + if facing == 'south': data = 2 + elif facing == 'east': data = 0 + elif facing == 'north': data = 3 + elif facing == 'west': data = 1 + if palette_entry['Properties']['half'] == 'top': + data |= 0x4 elif key.endswith('_door'): p = palette_entry['Properties'] if p['hinge'] == 'left': data |= 0x10 @@ -942,7 +1065,6 @@ class RegionSet(object): elif key in ['minecraft:beetroots', 'minecraft:melon_stem', 'minecraft:wheat', 'minecraft:pumpkin_stem', 'minecraft:potatoes', 'minecraft:carrots']: data = palette_entry['Properties']['age'] - return (block, data) def get_type(self): @@ -1185,11 +1307,12 @@ class RegionSet(object): # Empty is self-explanatory, and liquid_carved and carved seem to correspond # to SkyLight not being calculated, which results in mostly-black chunks, # so we'll just pretend they aren't there. - if chunk_data.get("Status", "") in ("empty", "carved", "liquid_carved", "decorated"): + if chunk_data.get("Status", "") not in ("full", "postprocessed", "fullchunk", + "mobs_spawned", ""): raise ChunkDoesntExist("Chunk %s,%s doesn't exist" % (x,z)) # Turn the Biomes array into a 16x16 numpy array - if 'Biomes' in chunk_data: + if 'Biomes' in chunk_data and len(chunk_data['Biomes']) > 0: biomes = chunk_data['Biomes'] if isinstance(biomes, bytes): biomes = numpy.frombuffer(biomes, dtype=numpy.uint8) @@ -1197,7 +1320,9 @@ class RegionSet(object): biomes = numpy.asarray(biomes) biomes = biomes.reshape((16,16)) else: - # worlds converted by Jeb's program may be missing the Biomes key + # Worlds converted by Jeb's program may be missing the Biomes key. + # Additionally, 19w09a worlds have an empty array as biomes key + # in some cases. biomes = numpy.zeros((16, 16), dtype=numpy.uint8) chunk_data['Biomes'] = biomes @@ -1207,8 +1332,11 @@ class RegionSet(object): # Turn the skylight array into a 16x16x16 matrix. The array comes # packed 2 elements per byte, so we need to expand it. try: - skylight = numpy.frombuffer(section['SkyLight'], dtype=numpy.uint8) - skylight = skylight.reshape((16,16,8)) + if 'SkyLight' in section: + skylight = numpy.frombuffer(section['SkyLight'], dtype=numpy.uint8) + skylight = skylight.reshape((16,16,8)) + else: # Special case introduced with 1.14 + skylight = numpy.zeros((16,16,8), dtype=numpy.uint8) skylight_expanded = numpy.empty((16,16,16), dtype=numpy.uint8) skylight_expanded[:,:,::2] = skylight & 0x0F skylight_expanded[:,:,1::2] = (skylight & 0xF0) >> 4 @@ -1216,8 +1344,11 @@ class RegionSet(object): section['SkyLight'] = skylight_expanded # Turn the BlockLight array into a 16x16x16 matrix, same as SkyLight - blocklight = numpy.frombuffer(section['BlockLight'], dtype=numpy.uint8) - blocklight = blocklight.reshape((16,16,8)) + if 'BlockLight' in section: + blocklight = numpy.frombuffer(section['BlockLight'], dtype=numpy.uint8) + blocklight = blocklight.reshape((16,16,8)) + else: # Special case introduced with 1.14 + blocklight = numpy.zeros((16,16,8), dtype=numpy.uint8) blocklight_expanded = numpy.empty((16,16,16), dtype=numpy.uint8) blocklight_expanded[:,:,::2] = blocklight & 0x0F blocklight_expanded[:,:,1::2] = (blocklight & 0xF0) >> 4 @@ -1226,8 +1357,11 @@ class RegionSet(object): if 'Palette' in section: (blocks, data) = self._get_blockdata_v113(section, unrecognized_block_types) - else: + elif 'Data' in section: (blocks, data) = self._get_blockdata_v112(section) + else: # Special case introduced with 1.14 + blocks = numpy.zeros((16,16,16), dtype=numpy.uint16) + data = numpy.zeros((16,16,16), dtype=numpy.uint8) (section['Blocks'], section['Data']) = (blocks, data) except ValueError: diff --git a/setup.py b/setup.py index e0274e8..3c98998 100755 --- a/setup.py +++ b/setup.py @@ -175,7 +175,7 @@ for name in glob.glob("overviewer_core/src/primitives/*.c"): name = os.path.splitext(name)[0] primitives.append(name) -c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c'] +c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c', 'block_class.c'] c_overviewer_files += ['primitives/%s.c' % (mode) for mode in primitives] c_overviewer_files += ['Draw.c'] c_overviewer_includes = ['overviewer.h', 'rendermodes.h']