// pvfdigesttestending 把指定段(默认段9)的 [ending] 改成 900(blackBoardScene 占位)。 // // 用途:**隔离测试** —— 判断「等级到某段时进图就播该段影片」到底是不是 // story digest 触发的。若改成黑屏后仍然播出原影片,说明另有来源 // (n_quest/connectquestlist.etc 或 etc/townmovielist.etc)。 // // 只改指定段的 [ending] 整数值;其余 token 全部不动。 package main import ( "encoding/binary" "flag" "fmt" "os" "path/filepath" platformpvf "longheng.io/server/internal/platform/pvf" ) const ( refScene = uint32(0x025138C6) refEnding = uint32(0x025138D6) refLevel = uint32(0x003566E2) ) func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } func tok5(typ byte, ref uint32) []byte { b := make([]byte, 5) b[0] = typ binary.LittleEndian.PutUint32(b[1:], ref) return b } func main() { input := flag.String("pvf", "", "input PVF") dir := flag.String("dir", "", "raw patch dir") seg := flag.Int("seg", 9, "要改的段序号") ending := flag.Uint("ending", 900, "新的 [ending] 值") flag.Parse() archive, err := platformpvf.Open(*input) if err != nil { panic(err) } raw, err := archive.ReadRaw("etc/storydigest/digest.etc") if err != nil { panic(err) } toks := len(raw) / 5 isSec := func(i int, ref uint32) bool { return i < toks && raw[i*5] == 3 && u32(raw[i*5+1:i*5+5]) == ref } out := append([]byte(nil), raw...) n := 0 changed := false for k := 0; k+1 < toks; k++ { if isSec(k, refLevel) { n++ } if n == *seg && isSec(k, refEnding) { old := u32(raw[(k+1)*5+1 : (k+1)*5+5]) copy(out[(k+1)*5:(k+1)*5+5], tok5(0, uint32(*ending))) fmt.Printf(" 段 %d: [ending] %d → %d\n", *seg, old, *ending) changed = true } } if !changed { panic(fmt.Sprintf("未找到段 %d 的 [ending]", *seg)) } full := filepath.Join(*dir, "etc", "storydigest", "digest.etc") if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil { panic(err) } if err := os.WriteFile(full, out, 0o644); err != nil { panic(err) } fmt.Println("已写出", full, len(out), "字节") }