==FILE== mods/dumpnodes/init.lua local function nd_get_tiles(nd) return nd.tiles or nd.tile_images end local function nd_get_tile(nd, n) local tile = nd_get_tiles(nd)[n] if type(tile) == 'table' then tile = tile.name end return tile end local function pairs_s(dict) local keys = {} for k in pairs(dict) do table.insert(keys, k) end table.sort(keys) return ipairs(keys) end minetest.register_chatcommand("dumpnodes", { params = "", description = "", func = function(player, param) local n = 0 local ntbl = {} for _, nn in pairs_s(minetest.registered_nodes) do local nd = minetest.registered_nodes[nn] local prefix, name = nn:match('(.*):(.*)') if prefix == nil or name == nil then print("ignored(1): " .. nn) else if ntbl[prefix] == nil then ntbl[prefix] = {} end ntbl[prefix][name] = true end end local out, err = io.open('nodes.txt', 'wb') if not out then return true, "io.open(): " .. err end for _, prefix in pairs_s(ntbl) do out:write('# ' .. prefix .. '\n') for _, name in pairs_s(ntbl[prefix]) do local nn = prefix .. ":" .. name local nd = minetest.registered_nodes[nn] if nd.drawtype == 'airlike' or nd_get_tiles(nd) == nil then print("ignored(2): " .. nn) else local tl = nd_get_tile(nd, 1) tl = (tl .. '^'):match('(.-)^') -- strip modifiers out:write(nn .. ' ' .. tl .. '\n') n = n + 1 end end out:write('\n') end out:close() return true, n .. " nodes dumped." end, }) ==FILE== avgcolor.py #!/usr/bin/env python import sys from PIL import Image def tadd(a, b): return tuple(sum(e) for e in zip(a, b)) if len(sys.argv) < 2: print("Prints average color (RGB) of input image") print("Usage: %s " % sys.argv[0]) exit(1) inp = Image.open(sys.argv[1]).convert('RGBA') ind = inp.load() cl = (0, 0, 0) counted = 0 for x in range(inp.size[0]): for y in range(inp.size[1]): px = ind[x, y] if px[3] < 128: continue # alpha cl = tadd(cl, px[:3]) counted += 1 if counted == 0: sys.stderr.write("did not find avg color for %s\n" % sys.argv[1]) print("0 0 0") else: cl = tuple(int(n / counted) for n in cl) print("%d %d %d" % cl) ==SCRIPT== #!/bin/bash -e AVGCOLOR_PATH=/path/to/avgcolor.py GAME_PATH=/path/to/minetest_game MODS_PATH= # path to "mods" folder, only set if you have loaded mods NODESTXT_PATH=./nodes.txt COLORSTXT_PATH=./colors.txt while read -r line; do set -- junk $line; shift if [[ -z "$1" || $1 == "#" ]]; then echo "$line"; continue fi tex=$(find $GAME_PATH -type f -name "$2") [[ -z "$tex" && -n "$MODS_PATH" ]] && tex=$(find $MODS_PATH -type f -name "$2") if [ -z "$tex" ]; then echo "skip $1: texture not found" >&2 continue fi echo "$1" $(python $AVGCOLOR_PATH "$tex") echo "ok $1" >&2 done < $NODESTXT_PATH > $COLORSTXT_PATH # Use nicer colors for water and lava: sed -re 's/^default:((river_)?water_(flowing|source)) [0-9 ]+$/default:\1 39 66 106 128 224/g' $COLORSTXT_PATH -i sed -re 's/^default:(lava_(flowing|source)) [0-9 ]+$/default:\1 255 100 0/g' $COLORSTXT_PATH -i # Add transparency to glass nodes and xpanes: sed -re 's/^default:(.*glass) ([0-9 ]+)$/default:\1 \2 64 16/g' $COLORSTXT_PATH -i sed -re 's/^doors:(.*glass[^ ]*) ([0-9 ]+)$/doors:\1 \2 64 16/g' $COLORSTXT_PATH -i sed -re 's/^xpanes:(.*(pane|bar)[^ ]*) ([0-9 ]+)$/xpanes:\1 \3 64 16/g' $COLORSTXT_PATH -i # Delete some usually hidden nodes: sed '/^doors:hidden /d' $COLORSTXT_PATH -i sed '/^fireflies:firefly /d' $COLORSTXT_PATH -i sed '/^butterflies:butterfly_/d' $COLORSTXT_PATH -i ==INSTRUCTIONS== 1) Make sure avgcolors.py works (outputs the usage instructions when run) 2) Add the dumpnodes mod to Minetest 3) Create a world and load dumpnodes & all mods you want to generate colors for 4) Execute /dumpnodes ingame 5) Run the script to generate colors.txt (make sure to adjust the PATH variables at the top)