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 для запуска клиента
51 lines
1.7 KiB
PowerShell
51 lines
1.7 KiB
PowerShell
# Builds a mod jar from source.
|
|
#
|
|
# build-mod.ps1 [-Source <dir>] [-Output <jar>]
|
|
#
|
|
# Mods are ordinary jars with a descriptor at META-INF/rsxmod.properties. There
|
|
# is no annotation processor and no gradle: javac against the loader jar, then
|
|
# jar, then done.
|
|
|
|
param(
|
|
[string]$Source = 'G:\RustNotMC\rsx-mods\rsxm-demo',
|
|
[string]$Output = ''
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
if (-not $Output) { $Output = Join-Path $Source 'dist' }
|
|
$Loader = 'G:\RustNotMC\rsx-client\dist\rsx-loader.jar'
|
|
if (-not (Test-Path $Loader)) { throw "loader jar missing: $Loader" }
|
|
|
|
$Name = Split-Path -Leaf $Source
|
|
$build = Join-Path $Source 'build'
|
|
$classes = Join-Path $build 'classes'
|
|
$jarPath = Join-Path $Output "$Name.jar"
|
|
|
|
Remove-Item $classes -Recurse -Force -ErrorAction SilentlyContinue
|
|
New-Item -ItemType Directory -Force -Path $classes | Out-Null
|
|
|
|
$mainSrc = Join-Path $Source 'src\main\java'
|
|
$mainRes = Join-Path $Source 'resources'
|
|
|
|
$mainFiles = @(Get-ChildItem $mainSrc -Recurse -Filter '*.java' | ForEach-Object { $_.FullName })
|
|
Write-Host " sources: $($mainFiles.Count)"
|
|
|
|
& javac -encoding UTF-8 -nowarn -proc:none --release 17 -cp $Loader -d $classes @mainFiles
|
|
if ($LASTEXITCODE -ne 0) { throw "javac failed" }
|
|
|
|
if (Test-Path $mainRes) { Copy-Item -Recurse -Force (Join-Path $mainRes '*') $classes }
|
|
|
|
New-Item -ItemType Directory -Force -Path $Output | Out-Null
|
|
Remove-Item $jarPath -Force -ErrorAction SilentlyContinue
|
|
|
|
# a mod is a library, never an executable, so there is no main class here
|
|
Push-Location $classes
|
|
& jar --create --file $jarPath -C $classes .
|
|
$jarExit = $LASTEXITCODE
|
|
Pop-Location
|
|
if ($jarExit -ne 0) { throw "jar failed with exit code $jarExit" }
|
|
|
|
Write-Host ''
|
|
Write-Host " $jarPath ($((Get-Item $jarPath).Length) bytes)"
|
|
exit 0 |