Files
RustNotMC/rsx-client/tools/fetch_missing.py
T
sasheg dev bdf0ae866a Форк клиента собирается из исходников, модзагрузчик встроен в игру
Проект начинается с двух вещей: клиент, который мы действительно собрали, и
загрузчик, который является его частью, а не чем-то рядом.

Форк
- prepare-game.ps1 пересобирает клиент целиком: ванильный jar, SRG и MCP,
  SpecialSource, FernFlower, патчи, автофиксеры, javac. Идемпотентен.
- Свой код игры лежит в src-overlay, потому что src пересоздаётся при каждой
  сборке и всё написанное вручную там погибает.
- 116 патчей в patches/decompiler-fixes.txt. Каждый сверялся с оригинальным
  байткодом через javap: компиляция не ловит ошибки декомпиляции.
- struct_diff.py сравнивает исходный байткод с нашей сборкой по классам,
  интерфейсам, суперклассам, методам и полям, и отдельно проверяет, что
  пропавшие классы действительно никому не нужны.

Загрузчик
- Собирается и тестируется без игры: build.ps1 не использует classpath
  вообще, поэтому SelfTest из 128 проверок проходит без запущенного форка.
- Клиентский API не содержит ни одного игрового типа, реализацию даёт игра.
- Политика: мод меняет то, что клиент показывает, но никогда то, что истинно
  в мире. Мир, предметы, игроки и сеть принадлежат серверу.
- Capability приведены в соответствие с этой политикой: осталось шесть, и
  за каждым стоит реальная проверка. Прежние WORLD, PLAYER, NETWORK, TEXT,
  INPUT и COMMAND выдавались, но ничего не проверяли.
- Команды модов имеют область CLIENT, SERVER или BOTH. Серверные не
  выполняются на клиенте никогда.
- Свой jar загрузчика лежит в classpath игры и сборки форка.

Инструменты
- add_patch.py, чтобы каждое исправление переживало передекомпиляцию
- find_self_comparisons.py, find_remove_index_bugs.py, find_callers.py
- stage_run.py и fetch_missing.py для запуска клиента
2026-10-18 21:31:27 +03:00

70 lines
2.4 KiB
Python

"""Fetch library files the local meta folder never downloaded.
The AstralRinth install has the 1.12.2 java libraries but not the
natives-windows classifiers, and the client cannot open a window without
lwjgl.dll. Rather than write into another application's cache, missing files go
into our own mirror of the same layout, which stage_run.py searches first.
python fetch_missing.py <dest-root> <meta-dir>
"""
import json
import os
import sys
import urllib.request
def wanted(manifest):
"""Every artifact and natives-windows path the manifest declares."""
out = []
for entry in manifest['libraries']:
downloads = entry.get('downloads') or {}
artifact = (downloads.get('artifact') or {}).get('path')
if artifact:
out.append(artifact)
classifiers = downloads.get('classifiers') or {}
for key, value in classifiers.items():
if key.startswith('natives-windows') and value and value.get('path'):
out.append(value['path'])
return sorted(set(out))
def main():
dest_root, meta = sys.argv[1], sys.argv[2]
manifest_path = os.path.join(meta, 'versions', '1.12.2', '1.12.2.json')
with open(manifest_path, encoding='utf-8') as handle:
manifest = json.load(handle)
meta_lib = os.path.join(meta, 'libraries')
base = 'https://libraries.minecraft.net/'
fetched, present, failed = [], 0, []
for rel in wanted(manifest):
if os.path.isfile(os.path.join(meta_lib, rel.replace('/', os.sep))):
present += 1
continue
target = os.path.join(dest_root, rel.replace('/', os.sep))
url = base + rel
try:
os.makedirs(os.path.dirname(target), exist_ok=True)
with urllib.request.urlopen(url, timeout=60) as response:
blob = response.read()
with open(target, 'wb') as handle:
handle.write(blob)
fetched.append('%s (%d bytes)' % (os.path.basename(rel), len(blob)))
except Exception as error: # noqa: BLE001
failed.append('%s -> %s' % (rel, error))
print('already present: %d' % present)
print('fetched: %d' % len(fetched))
for line in fetched:
print(' %s' % line)
if failed:
print('failed: %d' % len(failed))
for line in failed:
print(' %s' % line)
return 1 if failed else 0
if __name__ == '__main__':
raise SystemExit(main())