Files
RustNotMC/README.md
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

101 lines
3.7 KiB
Markdown

# RustNotMC
A survival game built on a Minecraft 1.12.2 client as the rendering platform,
with its own server, its own protocol and its own accounts.
## Repositories
| Repository | License | What lives there |
|---|---|---|
| `rsx-client` | MIT | Loader, mod API, client hooks, deobfuscation tools |
| `rsx-protocol` | MIT | Wire format, packet schemas, shared simulation library |
| `rsx-plugin-api` | MIT | Interfaces for server-side content |
| `rsx-server-core` | proprietary | Tick loop, world, entities, scaling |
| `rsx-auth` | proprietary | Accounts, tokens, revocation |
## Target
Base platform is Minecraft 1.12.2, forked into our own source tree so the game
is moddable from the start rather than patched from outside.
- game fork: Java 17, compiled by `game-fork\scripts\prepare-game.ps1`
- loader and mod API: Java 17
- mods: Java only
Capacity target is 200 players on 4 cores and 8 GB of RAM, scaling to 500 on
larger hardware.
## The fork
The client is not wrapped around the game jar. `game-fork` rebuilds it from the
verified vanilla jar into readable source, and the loader is an ordinary part
of that game rather than an agent injected into someone else's process.
```
vanilla client-1.12.2.jar verified Mojang signature
-> mcp-1.12.2-srg.zip 3344 classes, 20817 members
-> merge with MCP CSVs 9991 fields, 18715 methods renamed
-> SpecialSource 3310 classes in MCP names
-> FernFlower 2050 source files
-> hand patches + rules 103 patches, one regex rule
-> javac 3261 classes, clean
```
`prepare-game.ps1` runs the whole thing and is idempotent. Hand fixes live in
`game-fork\patches\decompiler-fixes.txt` and are re-applied on every run, so
regenerating the tree never loses them.
The fork holds Mojang-derived code and is **not published**. What ships in the
open repository is the loader, the mod API and the build tools.
## Modding
Mods are jars with a descriptor at `META-INF/rsxmod.properties`:
```properties
id=rsxm-lib
name=RustNotMC Library
version=1.0.0
env=CLIENT
entrypoint=net.rustnotmc.lib.LibMod
access=hud, text, world, player
depends.core=>=1.0
```
`env` is `CLIENT`, `SERVER` or `BOTH`. The loader runs on the client today;
the field exists so a mod that targets both sides does not need a format
change when the loader moves to the server.
Each mod gets its own class loader. Mods declare the capabilities they need and
the loader grants them; `reflection` is never granted without explicit operator
consent.
Load order comes from the dependency graph, not from filenames. Shutdown runs
in reverse.
## Building
```powershell
rsx-client\scripts\build.ps1 # dist\rsx-loader.jar
rsx-client\scripts\test.ps1 # self test, 96 checks
game-fork\scripts\prepare-game.ps1 # rebuild the fork from the vanilla jar
game-fork\scripts\compile-game.ps1 # compile only, fast iteration
```
Only a JDK is required. No Gradle, no network once the mappings are cached.
## Tools
| Script | Purpose |
|---|---|
| `rsx-client\tools\merge_srg_mcp.py` | vanilla SRG plus MCP CSVs into one obf to MCP SRG |
| `rsx-client\tools\apply_patches.py` | re-applies the hand fixes, fails loudly if one misses |
| `rsx-client\tools\fix_stale_locals.py` | FernFlower's stale local references, scoped per method |
| `rsx-client\tools\fix_generic_casts.py` | inserts the cast where a generic loses its type parameter |
| `rsx-client\tools\fix_decompiler_rules.py` | systematic rewrites that would be hundreds of patches |
| `rsx-client\tools\show_errors.py` | javac errors next to the source line that caused them |
## Legal
Minecraft is a trademark of Mojang Studios. This project is not affiliated with
or endorsed by Mojang or Microsoft. Game assets are not redistributed here.