Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read models and add 1.19 blocks that can't be dynamically rendered yet #2054

Open
wants to merge 39 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
dc449cb
read json file
Jun 28, 2022
0f86fb3
rad textures and succesfully render stone and cobblestone
Jun 28, 2022
107829f
eod commit
Jun 28, 2022
8c4b8dd
focus on full blocks for now
Jun 29, 2022
37953c4
proper rotation for loom block
Jun 29, 2022
fdb6356
modelblock method
Jun 29, 2022
cb2d5b8
added blocks to new texture build method
Jun 29, 2022
fdda6d3
added few blocks to generic rendering
Jul 4, 2022
ffa786c
added axis rotation
Jul 4, 2022
7598fd4
removed nodata
Jul 5, 2022
de3fcb6
observer
Jul 6, 2022
af51000
structure blocks
Jul 6, 2022
c1e4992
glazed
Jul 6, 2022
2ee681c
load simple blocks by model name instead of texture
Jul 7, 2022
5a172e3
referenced more blocks by enum
Jul 8, 2022
ea35d57
passed list of loaded models to worldpy
Jul 8, 2022
42aaf72
removes all simple blocks from textures.py
Jul 9, 2022
34081bf
modiefied docs to reflect new textures.py setup
Jul 9, 2022
6f7911e
slabs and minor fixes
Jul 11, 2022
ce0b607
process offset valies for north and west faces
Jul 15, 2022
3286d52
added mangrove slabs
Jul 17, 2022
ebdeefb
slabs and minor fixes
Jul 11, 2022
06b95a5
process offset valies for north and west faces
Jul 15, 2022
79bc83d
added mangrove slabs
Jul 17, 2022
62a6c37
element render order
Jul 18, 2022
c84c3c4
Revert "genpoi: ignore dat files with incomplete player info"
CounterPillow Jul 16, 2022
576fb7b
Revert "genpoi: ignore dat files with incomplete player info"
CounterPillow Jul 16, 2022
9ccd99a
Merge branch 'overviewer:master' into read_models
lieuwestra Jul 18, 2022
8981b2c
Merge branch 'overviewer:master' into transparent_blocks
lieuwestra Jul 18, 2022
b504822
Merge branch 'read_models' into transparent_blocks
lieuwestra Jul 18, 2022
63201fc
Merge pull request #4 from lieuwestra/transparent_blocks
lieuwestra Jul 18, 2022
4794e57
removed WIP comments
Jul 18, 2022
a3a3c7e
3.8 compatable
Jul 31, 2022
36136ec
optional axis
Aug 1, 2022
ca86e1e
double slab only if modelblocks have been loaded
Aug 2, 2022
3f78606
typo in variable name
Aug 2, 2022
cabcdf9
stone double slab
Aug 8, 2022
7343acf
mud brick stairs
Aug 16, 2022
2254311
Merge branch 'overviewer:master' into read_models
lieuwestra Aug 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 21 additions & 39 deletions docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,19 +127,21 @@ 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.

* ``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
----
Expand Down Expand Up @@ -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
Expand All @@ -202,46 +204,26 @@ 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 nospawn, or because you want to include them in an overview.
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.
solidmodelblock(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
Expand Down
20 changes: 15 additions & 5 deletions overviewer_core/src/block_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ 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,
block_mud_brick_stairs};
const size_t block_class_stair_len = COUNT_OF(block_class_stair);

const mc_block_t block_class_door[] = {
Expand All @@ -162,6 +164,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);

Expand All @@ -174,6 +177,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,
Expand Down Expand Up @@ -222,6 +226,8 @@ const mc_block_t block_class_ancil[] = {
block_polished_deepslate_stairs,
block_deepslate_brick_stairs,
block_deepslate_tile_stairs,
block_mangrove_stairs,
block_mud_brick_stairs,
block_grass,
block_flowing_water,
block_water,
Expand Down Expand Up @@ -252,7 +258,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[] = {
Expand Down Expand Up @@ -291,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,
Expand Down Expand Up @@ -337,12 +345,14 @@ 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,
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[] = {
Expand Down
53 changes: 22 additions & 31 deletions overviewer_core/src/iterate.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ 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;
static PyObject* nospawn_blocks = NULL;
static PyObject* nodata_blocks = NULL;

PyObject* init_chunk_render(void) {

Expand Down Expand Up @@ -64,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;
Expand All @@ -76,9 +79,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++) {
Expand All @@ -94,8 +94,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);
}
Expand Down Expand Up @@ -143,6 +141,8 @@ 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
Expand Down Expand Up @@ -269,7 +269,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;
Expand All @@ -284,15 +284,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);
Expand Down Expand Up @@ -601,27 +601,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 */
Expand All @@ -637,7 +628,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);
Expand Down
Loading