OverviewFilesCommitsIssuesDocsReleasesPeers

terrain-lookdev commits / 0d2c78e

tiles: default the store to user://tile_cache/<seed>, not ~/.cache
~/.cache WAS THE BUG. rsync-excludes.txt excludes ".cache/" -- a pattern with no internal slash, so it matches a directory of that name at ANY depth. So the generator was writing its only copy of every tile into the one tree the backup deliberately skips. Each tile is ~131 s of inference (measured 2026-09-03) and there are 971 of them. Verified both directions with the REAL exclude list, against a synthetic tree rooted the way the real job roots (/home/fleeky, --relative): the new path WOULD copy, the old one is excluded. My first check was invalid because I made ~/.cache the transfer root, which puts the pattern above the root where it can never match -- worth noting, because that mistake reads as a passing test. Tiles are GAME STATE, not a cache, so they belong under Godot's user:// for hyper-tps alongside everything else the game generates. Verified transparent: --list still reports 841 / 724 / 564 / 314 / 50 at the new path. THE SEED IS THE ONLY PARTITION AXIS, and the header now says why. A room is WHO MAY SEE a tile, not what it is: two rooms on one seed have byte-identical terrain, so nesting by room duplicates it -- the same reason hyper-tps keys user://content by hash, "two rooms asking for the same asset share one copy". A map SELECTS a seed and generator config; it is not an identity axis. Room and map scoping belong to KeetTileIndex and StateBase, not to directory names. bench_cpu_tile.py DID NOT READ LOOKDEV_TILE_CACHE at all -- it had the path hardcoded, so it silently benchmarked a different tile set than stitch_block.py and server.py were looking at. Now it reads the env var like the other two. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0d2c78e39afe188ae69442b2912c6ff435cb71e1
by plankatron <fleeky@gmail.com> · 2026-09-03T14:19:20.000Z

Changed files (3) +47 -3

bench_cpu_tile.py +5 -1
……@@ -27,7 +27,11 @@ import argparse, os, re, sys, time
2727import numpy as np
2828from server import fetch_diffusion
2929
30CACHE = os.path.expanduser("~/.cache/terrain-lookdev/tiles")
30# Reads LOOKDEV_TILE_CACHE like the other tools -- it did NOT before, so it
31# silently benchmarked a different tile set than stitch_block/server saw.
32CACHE = os.environ.get("LOOKDEV_TILE_CACHE",
33 os.path.expanduser(
34 "~/.local/share/godot/app_userdata/HyperTPS/tile_cache/1234"))
3135TILE_PX = 256
3236
3337
server.py +21 -1
……@@ -25,8 +25,28 @@ import numpy as np
2525from flask import Flask, Response, request, send_from_directory
2626
2727HERE = os.path.dirname(os.path.abspath(__file__))
28# WHERE TILES LIVE, and why it is not ~/.cache.
29#
30# Generated tiles are GAME STATE, not a cache: each is ~131 s of inference and
31# they are the only copy. They used to default under ~/.cache/, which
32# rsync-excludes.txt excludes (".cache/" matches any directory of that name at
33# any depth) -- so the generator was writing its only copy into the one tree the
34# backup deliberately skips. Verified both ways with the real exclude list.
35#
36# They now live under Godot's user:// for hyper-tps, which IS in the backup set
37# and is where every other thing the game generates already goes.
38#
39# THE SEED IS THE PARTITION AXIS -- and the only one. A room is WHO MAY SEE a
40# tile, not what it is: two rooms on one seed have byte-identical terrain, so
41# nesting by room would duplicate it (the same reason content_overlay.gd keys
42# user://content by hash: "two rooms asking for the same asset share one copy").
43# A map SELECTS a seed and generator config; it is not an identity axis.
44# Room/map scoping belongs to KeetTileIndex and StateBase, not the filesystem.
45#
46# LOOKDEV_TILE_CACHE overrides the whole path.
2847TILE_CACHE = os.environ.get("LOOKDEV_TILE_CACHE",
29 os.path.expanduser("~/.cache/terrain-lookdev/tiles"))
48 os.path.expanduser(
49 "~/.local/share/godot/app_userdata/HyperTPS/tile_cache/1234"))
3050DC_TERRAIN = os.path.abspath(os.path.join(HERE, "..", "dc-terrain"))
3151INC = os.path.abspath(os.path.join(HERE, "..", "proc-nodes", "src", "shared",
3252 "erosion_filter.inc"))
stitch_block.py +21 -1
……@@ -40,8 +40,28 @@ Usage:
4040import argparse, os, re, struct, sys
4141import numpy as np
4242
43# WHERE TILES LIVE, and why it is not ~/.cache.
44#
45# Generated tiles are GAME STATE, not a cache: each is ~131 s of inference and
46# they are the only copy. They used to default under ~/.cache/, which
47# rsync-excludes.txt excludes (".cache/" matches any directory of that name at
48# any depth) -- so the generator was writing its only copy into the one tree the
49# backup deliberately skips. Verified both ways with the real exclude list.
50#
51# They now live under Godot's user:// for hyper-tps, which IS in the backup set
52# and is where every other thing the game generates already goes.
53#
54# THE SEED IS THE PARTITION AXIS -- and the only one. A room is WHO MAY SEE a
55# tile, not what it is: two rooms on one seed have byte-identical terrain, so
56# nesting by room would duplicate it (the same reason content_overlay.gd keys
57# user://content by hash: "two rooms asking for the same asset share one copy").
58# A map SELECTS a seed and generator config; it is not an identity axis.
59# Room/map scoping belongs to KeetTileIndex and StateBase, not the filesystem.
60#
61# LOOKDEV_TILE_CACHE overrides the whole path.
4362CACHE = os.environ.get("LOOKDEV_TILE_CACHE",
44 os.path.expanduser("~/.cache/terrain-lookdev/tiles"))
63 os.path.expanduser(
64 "~/.local/share/godot/app_userdata/HyperTPS/tile_cache/1234"))
4565TILE_PX = 256
4666APRON = 1
4767MPP = 30.0