Проект начинается с двух вещей: клиент, который мы действительно собрали, и загрузчик, который является его частью, а не чем-то рядом. Форк - 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 для запуска клиента
3.7 KiB
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:
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
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.