Files
sasheg dev 00671e7c0d Звук в клиенте пропал из-за неверного каталога ассетов
Клиент запрашивал звук, движок его принимал и запускал, а на выходе было
тихо. Причина оказалась не в коде игры.

Minecraft 1.12.2 не умеет читать ассеты по индексу и объектному хранилищу.
Он ждёт обычное дерево: <assetsDir>/minecraft/<путь>. А лаунчер хранит
ассеты по-современному — indexes/1.12.json со ссылками на objects/<aa>/<sha1>.

Мы передавали лаунчеру корень этого хранилища как --assetsDir. Игре это не
выглядит как поломка: язык и текстуры берутся из самого jar, поэтому клиент
выглядит полностью рабочим. Но звуки с 1.7.3 лежат только в ассетах, и их
просто не было на диске. Движок поднимался, play() вызывался, ogg не
находился, а paulscode на это молчит.

- materialize_assets.py разворачивает дерево из индекса и хранилища,
  жёсткими ссылками где возможно, и идемпотентен
- run-game.ps1 материализует ассеты перед запуском и указывает клиенту на
  развёрнутое дерево; --assetIndex больше не нужен
- проверено: 1305 объектов, из них 1085 ogg, sounds.json на месте, ошибок
  загрузки в логе нет

Заодно убрана временная диагностика звука и движения, добавленная ради
поиска причины: она доказала, что запрос и воспроизведение доходят до
OpenAL, и свою задачу выполнила.

Полный prepare-game.ps1 после этого проходит целиком: 112 патчей,
FORK COMPILES CLEAN, 3268 классов, RsxDebug в дереве не осталось.
2026-10-19 00:04:51 +03:00

90 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Materialise a 1.12 asset tree out of a hash-addressed asset store.
Minecraft 1.12.2 does not read an index plus an object store. It reads
``<assetsDir>/minecraft/<path>`` directly. A launcher such as AstralRinth keeps
assets the modern way, as ``indexes/1.12.json`` pointing at
``objects/<aa>/<sha1>``, and a launcher that wants them for an old client is
responsible for laying them out.
Passing the store root as ``--assetsDir`` does not fail loudly. Texts and
textures still appear, because those live inside the client jar, so the game
looks correct while every sound is silently absent: nothing requested is ever
found on disk.
Usage:
materialize_assets.py <meta-assets-dir> <out-dir> [--index 1.12]
Hard links are used where the filesystem allows it, so the materialised tree
costs almost nothing and repeated runs are cheap.
"""
import argparse
import json
import os
import sys
def human(count):
return "{:,}".format(count).replace(",", " ")
def main(argv):
ap = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("meta_assets", help="store root holding indexes/ and objects/")
ap.add_argument("out", help="assets dir to create for the client")
ap.add_argument("--index", default="1.12", help="index file name (default: 1.12)")
args = ap.parse_args(argv)
meta = args.meta_assets
index_path = os.path.join(meta, "indexes", args.index + ".json")
if not os.path.isfile(index_path):
sys.exit("no asset index at " + index_path)
with open(index_path, "r", encoding="utf-8") as fh:
objects = json.load(fh)["objects"]
out = args.out
linked = copied = reused = 0
missing = []
for name, info in sorted(objects.items()):
digest = info["hash"]
src = os.path.join(meta, "objects", digest[:2], digest)
dst = os.path.join(out, *name.split("/"))
if os.path.isfile(src) and os.path.getsize(src) == info["size"]:
if os.path.exists(dst) and os.path.getsize(dst) == info["size"]:
reused += 1
continue
os.makedirs(os.path.dirname(dst), exist_ok=True)
if os.path.exists(dst):
os.remove(dst)
try:
os.link(src, dst)
linked += 1
except OSError:
with open(src, "rb") as r, open(dst, "wb") as w:
w.write(r.read())
copied += 1
else:
missing.append(name)
sounds = sum(1 for n in objects if n.endswith(".ogg"))
print("index : {} ({} objects, {} ogg)".format(
os.path.join("indexes", args.index + ".json"), human(len(objects)), human(sounds)))
print("output : {}".format(out))
print("hardlink: {} copy: {} reused: {}".format(
human(linked), human(copied), human(reused)))
if missing:
print("MISSING : {} object(s) not in the store".format(human(len(missing))))
for name in missing[:10]:
print(" " + name)
return 1
print("ok : every indexed object is present")
return 0
if __name__ == "__main__":
raise SystemExit(main(sys.argv[1:]))