mtschem
Python Library providing Input/Output for Minetest Schematics (.mts), converting them into a Numpy array. Code by Gaël de Sailly, loosely based on python-minetest by LeMagnesium. License: GPLv2.
Installation
Download from GitHub:
- using
git
:git clone https://github.com/Gael-de-Sailly/python-mtschem.git
- or download directly the zip archive.
Then, using the command line, place yourself in python-mtschem
directory.
Install:
python3 setup.py install
You may need the administrator rights.
Basic use
Import the library
import mtschem
Load a schematic
my_schem = Schem("path/to/my_schem.mts")
data
array
The data are stored in my_schem.data
in the form of a X×Y×Z array of structured elements.
To get the shape and the volume:
shape = my_schem.data.shape # 3-tuple
volume = my_schem.data.size
To get the element at position (3,5,7):
element = my_schem.data[3,5,7]
Each element has 4 fields:
node = element["node"] # node ID (rank on the node list, see below)
prob = element["prob"] # probability (0-127)
force = element["force"] # whether to force replacement of existing nodes when the schematic is placed (boolean)
param2 = element["param2"] # param2 of the node
To get an array of node IDs:
node_ids = my_schem.data["node"]
Also works for prob
, force
and param2
.
The data array can be freely modified, as long as you keep the structure with the 4 named fields. Values and array size can be changed.
Y-Slice probabilities
They are stored in my_schem.yprobs
in the form of a 1D list of size Y.
prob_at_6 = my_schem.yprobs[6] # is the probability to get slice at y=6 generated (0-127)
If you use specific values for yprobs, make sure the size of this array follows the Y size of the data schematic. If you always use 127, you can neglect this.
Node list
The node list is stored in myschem.nodes
. Their order define the node ID. To get the node name of element
:
node_name = my_schem.nodes[element["node"]]
To get the ID of a node:
c_lawn = my_schem.nodes.index("default:dirt_with_grass")
Keep the node name list up-to-date if you add new nodes to the data.
Saving
To export the modified schematic:
my_schem.save("path/to/output_schem.mts")
Useful tricks
Replacing a node
To replace every occurence of a node, you don't need to modify the data
array, just tweak the node list.
def replace_dirt_by_stone(schem):
c_dirt = schem.nodes.index("default:dirt")
schem.nodes[c_dirt] = "default:stone"
Of course this may introduce a duplicate in the node list. Duplicates are automatically fixed on saving, so you generally don't need to bother with that. However if you want to fix them manually, add this:
schem.cleanup_nodelist()
This removes duplicates and unused nodes in the node list, and updates the array if necessary.
Counting the quantity of a node
This needs to make use of Numpy's count_nonzero
function.
import numpy as np
def count_node(schem, nodename):
id = schem.nodes.index(nodename)
return np.count_nonzero(schem.data["node"] == id)
Create a schematic from a given part of another schematic
Schem
objects can be directly indexed by coordinates. This returns a new Schem
object representing the given part of the initial schematic. This is useful for dividing a large schematic into reasonably sized parts, or to prune a schematic containing unnecessary blank margins.
import mtschem
schem = mtschem.Schem("thing.mts")
bottom = schem[:,:10,:] # Here we take the 10 bottom lines of thing.mts
bottom.save("thing_bottom.mts")
middle = schem[:,10:20,:] # Then the 10 lines above
middle.save("thing_middle.mts")
top = schem[:,20:,:] # And finally, from line 20 to the end
top.save("thing_top.mts")
Find the list of nodes present in a given part of the schematic
Using the Numpy function unique
to give the list of existing values in an array.
import numpy as np
def list_nodes_in(schem, minp, maxp): # minp and maxp 3-tuples
subschem = schem[
minp[0]:maxp[0]+1,
minp[1]:maxp[1]+1,
minp[2]:maxp[2]+1,
]
id_list = np.unique(subschem.data["node"])
node_list = []
for id in id_list:
node_list.append(subschem.nodes[id])
return node_list