A usecase to demonstrate a possible application of the extended functionality:
**"Rails Overlay that draws only the rails that are on Cobblestone for a subway map."**
With this patch it is very easy to achive that:
```python
MineralOverlay(minerals=[(((0, 0, 0, 66), (0, -1, 0, 4)), (255, 0, 0, 255)),
(((0, 0, 0, 27), (0, -1, 0, 4)), (0, 255, 0, 255))])
```
In this case the overlay will be red for rails on cobblestone and green for powerrails on cobblestone.
The syntax is `(<tuple of conditions>, <target color>)`
* where `<target color>` is a 4 tuple with a `(r, g, b, a)` color
* and `<tuple of conditions>` is a tuple with an arbitrary number of conditions with the following syntax:
`((relx, rely, relz, blkid), ...)` where the `rel<>` parameters specify the relative coordinates to the block that is checked if it matches bklid.
In the example the fist tuple `(0,0,0,66)` checks if at the current position is a
rail while `(0,-1,0,4)` checks if at one below the current position is a cobblestone.
If both are true then the color `(255, 0, 0, 255)` is used.
A Sample Config file exploiting the capabilities:
``` python
worlds['My World'] = "~/.minecraft/saves/test/"
outputdir = "/tmp/test_render"
rendermode = "lighting"
renders["render1"] = {
'world': 'My World',
'title': 'A regular render',
}
renders["render_overlay_dafault_rails"] = {
'world': 'My World',
'title': 'Default Rails',
'rendermode': [ClearBase(), StructureOverlay()],
'overlay': ['render1'],
}
renders["render_overlay_cust_rails"] = {
'world': 'My World',
'title': 'Custom Rails',
#relative coordinates [[(relx, rely, relz, mineral)], (red, green, blue, alpha)]
'rendermode': [ClearBase(), StructureOverlay(structures=[(((0, 0, 0, 66), (0, -1, 0, 4)), (255, 0, 0, 255)),
(((0, 0, 0, 27), (0, -1, 0, 4)), (0, 255, 0, 255))])],
'overlay': ['render1'],
}
```
The "Default Rails" overlay uses default coloring of the structures overlay. "Custom Rails" uses some custom coloring.
fixesoverviewer/Minecraft-Overviewer#556 and fixesoverviewer/Minecraft-Overviewer#787
Instead of reading all Players and especially Entities and TileEntities
into RAM and than applying the filter functions onto them, filter
functions are used after each parsed chunk to get only the markers of
this chunk and not all Entities.
This reduced the RAM usage dramatically:
On a 233 MB map over 200 MB of RAM was used before.
Using these changes (and only having two filter functions for signs) not
more than 36 MB of RAM was used.
Since all the POIs are created from different lists, multiple for loops
were used. With itertools.chain these lists can be looped over with only
one for loop thus removing doubled code.
The code creating the actual marker dict out of the entity and the
result of the filter function was almost the same for every set of
entities. Thus it is now a function.
Instead of doing the UUID->name resolution for all players in every
case, only do it when EntityId is accessed and the name hasn't been
retrieved this run already. This makes genPOI usable for people who
have many players on their servers but don't wish to use player POI
while still using other genPOI features.
To do this, a PlayerDict has been created, which contains a dirty
hack to see if the requested item is EntityId and whether it hasn't
been set already.
The validator will now warn if it detects that a crushed output
is fed into something that is not a crusher.
The is_crusher method of an optimizer shall return True if the
optimisation process is lossless, and does try to find optimal
encoding parameters as opposed to only removing unneeded channels
or reducing palettes.
Before someone says this is incorrect because it only ever uses
pngcrush: The old code always used pngcrush and nothing else
anyway. This is absolutely correct and the old behaviour.
I also added a check to make sure it's a list, as some people might
forget the whole list thing.