Files
agentmc/scaffold/build.sh
JianFeeeee a1ce560c05 修复渲染联测的两个阻断缺陷(之前 5/7 → 现 7/7)
## ① natives 必须平铺,不能保留包路径

natives-linux jar 里的路径是 `linux/x64/org/lwjgl/<module>/lib*.so`,
而 LWJGL 经 java.library.path / LD_LIBRARY_PATH 按**文件名**找库 ——
嵌套一层的目录它找不到。实测:

  UnsatisfiedLinkError: Failed to locate library: liblwjgl.so
    at RenderSystem.<clinit> → Tesselator.<clinit>

build.sh 原来直接 `unzip -d $OUT/natives`(保留包路径)⇒ 产物不可用。
改为解到临时目录再 `find -name '*.so' -exec cp` 平铺。
(已用新逻辑重铺 store/vanilla-1.20.1/.mcfold/natives,7 个 .so 在根下。)

## ② api_notes 应为 staticmethod

35534b1 把世代分派改成类级调用后,`api_notes` 仍是实例方法,
测试里 `Gen_1_20.api_notes()` 直接 TypeError。它不读 self ⇒ 一律 staticmethod。
这也是它能"不启动后端就做世代对照"的前提。

## ③ classpath.txt 的语义写进注释

它**只含第三方 libraries**;client-named.jar 与 classes/ 由使用方拼接
(build.sh:88 自己拼,测试/后端从各自路径取)。
在 build.sh 里注明,避免下一个人以为它是"完整运行 classpath"。

## 验证

  ./run_tests.sh                    → 62 项全绿
  .mcfold classpath + 平铺 natives  → 渲染联测 **7/7 全绿**
    (injected=49 chunks=31 colors=11714 / placed=1003716 chunks=25 colors=4540)
2026-09-26 06:53:30 +08:00

118 lines
6.0 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# mcfold 构建脚本 —— 把官方客户端 jar 变成「可直接调用的渲染库」。
#
# ★ 版本隔离策略(用户 2026-09-25 强调)
# 产物写入**内容根** store/<loader>-<version>/.mcfold/,不写 /tmp:
# 内容根/.mcfold/client-named.jar 反混淆后的客户端(可只读共享)
# 内容根/.mcfold/classes/ 我们的渲染服务
# 内容根/.mcfold/natives/ LWJGL .so
# 理由:这些都由该版本的 client jar 派生,属「可共享内容」;
# /tmp 是 tmpfs,重启即丢(实测踩过)。实例独占的东西(mods/config/options)
# 一律不进这里。
#
# 用法: ./build.sh <内容根|实例名> <MC版本> [java模式目录]
# ./build.sh /home/newqqagent/mcview/store/vanilla-1.20.1 1.20.1
# ./build.sh /home/newqqagent/mcview/store/vanilla-1.21.1 1.21.1 java/gen_1_21
set -euo pipefail
STORE="${1:?用法: build.sh <内容根> <MC版本> [java目录]}"
MCVER="${2:?需要 MC 版本}"
JAVA_SUB="${3:-}"
HERE="$(cd "$(dirname "$0")" && pwd)"
# 按版本挑世代目录(除非显式指定)
if [ -z "$JAVA_SUB" ]; then
case "$MCVER" in
1.21*) JAVA_SUB="java/gen_1_21" ;;
*) JAVA_SUB="java/gen_1_20" ;;
esac
fi
OUT="$STORE/.mcfold"
WORK="${MCFOLD_BUILD_WORK:-$(mktemp -d /tmp/mcfold-build-XXXXXX)}"
CLIENT_JAR="$STORE/versions/$MCVER/$MCVER.jar"
[ -f "$CLIENT_JAR" ] || { echo "找不到客户端 jar: $CLIENT_JAR"; exit 1; }
mkdir -p "$OUT/classes" "$OUT/natives" "$WORK"
echo "[build] 版本 $MCVER 世代 $JAVA_SUB"
echo "[build] 输出 → $OUT"
# ── 1. 官方映射 ────────────────────────────────────────────────
if [ ! -s "$WORK/client_mappings.txt" ]; then
URL=$(python3 - "$STORE/versions/$MCVER/$MCVER.json" <<'PY'
import json,sys
print(json.load(open(sys.argv[1]))['downloads']['client_mappings']['url'])
PY
)
echo "[1/5] 下载官方映射..."
curl -sL -o "$WORK/client_mappings.txt" "$URL"
fi
echo "[1/5] 映射 $(wc -l < "$WORK/client_mappings.txt") 行"
# ── 2. ProGuard → SRG ─────────────────────────────────────────
echo "[2/5] 转换映射格式..."
python3 "$HERE/pg2srg.py" "$WORK/client_mappings.txt" "$WORK/mappings.srg"
# ── 3. 重映射客户端 jar ───────────────────────────────────────
NAMED="$OUT/client-named.jar"
if [ ! -f "$NAMED" ] || [ "$CLIENT_JAR" -nt "$NAMED" ]; then
echo "[3/5] 重映射(1-3 分钟)..."
SS=$(find /home/minecraft/libraries -name "SpecialSource-*.jar" 2>/dev/null | head -1)
GUAVA=$(find /home/minecraft/libraries -name "guava-*.jar" ! -name "*sources*" 2>/dev/null | head -1)
[ -n "$SS" ] || { echo "找不到 SpecialSource"; exit 1; }
for a in asm asm-commons asm-tree; do
[ -f "$WORK/$a.jar" ] || curl -sL -o "$WORK/$a.jar" \
"https://repo1.maven.org/maven2/org/ow2/asm/$a/9.7/$a-9.7.jar"
done
[ -f "$WORK/joptsimple.jar" ] || curl -sL -o "$WORK/joptsimple.jar" \
"https://repo1.maven.org/maven2/net/sf/jopt-simple/jopt-simple/5.0.4/joptsimple-5.0.4.jar"
java -Xmx3G -cp "$SS:$WORK/joptsimple.jar:$WORK/asm.jar:$WORK/asm-commons.jar:$WORK/asm-tree.jar:$GUAVA" \
net.md_5.specialsource.SpecialSource \
-i "$CLIENT_JAR" -o "$NAMED" -m "$WORK/mappings.srg"
else
echo "[3/5] client-named.jar 已是最新"
fi
# ── 4. classpath(去 asm 重复,Fabric 需要) + natives ────────
# classpath.txt **只含第三方 libraries** —— client-named.jar 与 classes/ 由使用方拼接
# (build.sh 自己在下面拼,测试/后端则从各自路径取)。
# ★ 别在这里把 named/classes 也写进去:那会让「libraries 清单」与「运行 classpath」
# 两个概念混成一列,而 Fabric 路线需要把 asm 从 libraries 里剔掉后**另行**拼 8 个库。
find "$STORE/libraries" -name "*.jar" ! -name "*-sources.jar" ! -name "*natives*" 2>/dev/null \
| grep -vE "minecraftforge|neoforge" > "$OUT/classpath.txt"
NATLIST=$(find "$STORE/libraries" -name "*natives-linux*.jar" 2>/dev/null)
if [ -n "$NATLIST" ]; then
rm -rf "$OUT/natives"; mkdir -p "$OUT/natives"
# ★ 必须**平铺**。natives jar 里的路径是 linux/x64/org/lwjgl/<module>/lib*.so,
# 而 LWJGL 是经 java.library.path/LD_LIBRARY_PATH 按**文件名**找库的 ——
# 嵌套一层的目录它**找不到**(实测 UnsatisfiedLinkError: Failed to locate library: liblwjgl.so)。
while read -r j; do
[ -f "$j" ] || continue
unzip -o -q "$j" -d "$OUT/natives.tmp" 2>/dev/null || true
done <<< "$NATLIST"
find "$OUT/natives.tmp" -name '*.so' -exec cp {} "$OUT/natives/" \; 2>/dev/null
rm -rf "$OUT/natives.tmp"
fi
echo "[4/5] 库 $(wc -l < "$OUT/classpath.txt") 个, natives $(find "$OUT/natives" -name '*.so' | wc -l) 个"
# ── 5. 编译渲染服务 ───────────────────────────────────────────
echo "[5/5] 编译 $JAVA_SUB ..."
CP="$(paste -sd: "$OUT/classpath.txt"):$NAMED:$OUT/classes"
find "$HERE/$JAVA_SUB" -name "*.java" > "$WORK/srcs.txt"
javac -nowarn -proc:none -cp "$CP" -d "$OUT/classes" @"$WORK/srcs.txt"
echo
echo "✅ 构建完成(产物在内容根,不是 /tmp)"
echo " 内容根 : $STORE"
echo " 产物 : $OUT"
echo " named : $OUT/client-named.jar"
echo " classes: $OUT/classes"
echo
echo "运行(渲染服务从 stdin 读 NDJSON):"
echo " DISPLAY=:98 java -cp \"\$(paste -sd: $OUT/classpath.txt):$NAMED:$OUT/classes\" \\"
echo " -Djava.library.path=$OUT/natives McfoldRenderServer \\"
echo " --gameDir <实例目录> --assets $STORE/assets --assetIndex $MCVER"
echo
echo "★ 实例目录必须是**实例独占**的那个(mods/config/options 的边界),"
echo " 不要指向别的版本或别的加载器的实例 —— 那正是「多实例共用 mods」的崩因。"