Ship một bản update
Trước khi bắt đầu
Phần tiêu đề “Trước khi bắt đầu”Cần hai bản build của archive để đem so, quyền ghi vào patch root, và một máy đích để thử. Chưa rõ delta.dat là gì thì đọc trang đó trước.
Lấy version của client ngay trên máy đích, đừng lấy trong manifest cũ:
(Get-Item 'D:\AvatarStarDev\client.exe').VersionInfo.FileVersionManifest cũ chỉ ghi bản ta rao ra lần trước, không phải bản client đang chạy. Lần release trước mà bị
từ chối, do sai SrcVer hoặc do game còn mở nên CopyFileW chết, thì version dưới máy vẫn nằm im.
Từ đó trở đi hai con số lệch nhau một bản và không tự khớp lại được.
Ngày 2026-08-22 đã dính đúng chuyện này. SrcVer="1.4.0.64569" chép từ manifest cũ, client thật ra
đang ở 1.4.0.64568, thế là block bị bỏ qua và launcher không hề hỏi tới payload. Log chỉ có bốn
dòng GET /GameUpdate/update.xml trả 200 rồi thôi. Client không báo lỗi, server cũng không. Publish
lại với --src-version 1.4.0.64568 là chạy.
Các bước
Phần tiêu đề “Các bước”1. Dựng bản build mới của archive
Phần tiêu đề “1. Dựng bản build mới của archive”python3 research/01_pde_archive/pde_pack.py pack ~/as_build/tree_vi ~/as_build/vi_vn.new.pde \ ~/as_build/manifest_vi.jsonpython3 research/16_add_content/fix_idhash_pde.py --fix ~/as_build/vi_vn.new.pdepython3 research/17_localized_art/verify_pack.py ~/as_build/vi_vn.new.pde2. So với archive đang nằm trên máy đích
Phần tiêu đề “2. So với archive đang nằm trên máy đích”Bản cũ đem so phải là archive thật sự đang cài trên máy đó, đã đối chiếu md5. Chỉ có vậy mới chắc
mỗi dòng A trỏ vào path client chưa có và mỗi dòng U trỏ vào path nó đã có.
python3 research/69_patch_channel/diff_pde.py OLD.pde NEW.pde \ --archive AvatarStar_vi_vn.pde \ --out-dir /tmp/payload_vi --ops-file /tmp/ops_vi.txtMỗi archive một --out-dir riêng. Xài chung một thư mục thì file trùng đường dẫn tương đối giữa
các archive sẽ đè lên nhau, và game_text.lua của cả năm pack chỉ còn lại đúng một bản.
3. Đóng gói delta
Phần tiêu đề “3. Đóng gói delta”python3 research/69_patch_channel/make_delta.py delta.dat \ --ops-file /tmp/ops_vi.txt --check--check đối chiếu idHash của mọi payload .cache với đường dẫn đích. Luôn bật nó lên. Hash sai thì
client lặng lẽ bỏ qua tài nguyên đó, không log một dòng nào.
Riêng .physx.cache thì --check bỏ qua, và bắt buộc phải bỏ qua: đây là họ file duy nhất chưa giải
được công thức idHash, 89 trên 20.000 container ship kèm game đều fail và tất cả đều là .physx. Byte
copy nguyên xi nên khoảng trống đó vô hại, file mang sẵn hash của nhà phát hành. Với một file .physx
tự tạo thì không vô hại.
4. Đóng dấu version vào client.exe
Phần tiêu đề “4. Đóng dấu version vào client.exe”python3 server/patch/stamp_version.py client.exe --version 1.4.0.64581Quên bước này thì block chạy lại mỗi lần bấm ENTER, không bao giờ dứt. Lý do ở ngay bên dưới.
client.exe đã stamp đi bên trong delta.dat, dưới dạng một op ghi ra ổ đĩa (U client.exe),
chứ không phải một <Url> thứ hai. Nhà phát hành làm đúng như vậy.
5. Đưa lên patch root và cập nhật manifest
Phần tiêu đề “5. Đưa lên patch root và cập nhật manifest”cp delta.dat server/patch/root/Update/Game/1.4.0.64580-1.4.0.64581/delta.datManifest thêm một block:
<CurVersion>1.4.0.64581</CurVersion><UpdateVersion SrcVer="1.4.0.64580" DstVer="1.4.0.64581"> <Url PatchName="delta.dat" FileName="" PatchMode="Patch">Update/Game/1.4.0.64580-1.4.0.64581/delta.dat</Url></UpdateVersion>Đoạn này phải gõ tay. Hai script publish.py hiện có đều chỉ nhận một --mode chung cho cả block
và luôn ghi FileName=<PatchName>, trong khi bản delta cần FileName="" và cần chọn mode riêng cho
từng <Url>.
6. Chạy thử và xác minh
Phần tiêu đề “6. Chạy thử và xác minh”Bật server rồi mở launcher: LOGIN, chọn server, ENTER.
Xác minh bằng hash và bằng màn hình game, đừng tin access log. Dòng 200 chỉ chứng minh file đã
được gửi đi, không chứng minh nó đã cài vào. Hai lần chạy thật đều xác nhận theo ba đường: md5
dưới máy khớp bản build local, [Ver] game nhảy lên, và đoạn text vừa sửa hiện ra trong tooltip vũ
khí.
Ba chỗ hỏng mà không ai báo
Phần tiêu đề “Ba chỗ hỏng mà không ai báo”<Url> không có text thì tải về đúng 0 byte
Phần tiêu đề “<Url> không có text thì tải về đúng 0 byte”<!-- SAI: parse trôi, báo thành công, tải về đúng 0 byte --><Url PatchName="delta.dat" FileName="" PatchMode="Patch"/>
<!-- ĐÚNG: đường dẫn nằm ở phần text của element --><Url PatchName="delta.dat" FileName="" PatchMode="Patch">Update/Game/.../delta.dat</Url>Manifest chạy được đầu tiên của dự án này có đủ attribute mà thiếu text. Launcher tải update.xml,
kết luận là có update, rồi ngồi im. Không chỗ nào báo lỗi.
Thiếu client.exe đã stamp thì block chạy lại mãi
Phần tiêu đề “Thiếu client.exe đã stamp thì block chạy lại mãi”Thứ làm update dừng lại là điều kiện CurVersion > local. SrcVer không phải cái cổng đó.
Payload không mang theo thứ gì làm version dưới máy nhích lên thì CurVersion > local lúc nào cũng
đúng, và launcher tải lại đúng bản đó mỗi lần bấm ENTER.
Version dưới máy nằm ở version resource của client.exe, không phải [Ver] game trong
launch.ini. [Ver] game có nhảy lên sau khi vá vì asup.exe ghi nó, nhưng launcher không đọc
dòng đó lúc quyết định. Tin nhầm chỗ này thì kênh patch tải lại 1,45 GB mỗi lần khởi động.
Error Code=0x4000005a gần như luôn là do game còn chạy
Phần tiêu đề “Error Code=0x4000005a gần như luôn là do game còn chạy”Con số đó không phải status code, nó là id của chính câu thông báo đang hiện, và nhánh code hiện nó truyền hằng 0 vào tham số format. Tức là con số không nói thêm được gì.
Ý nghĩa thật: tải về thì xong, CopyFileW đè lên file đang sống thì chết. Nguyên nhân gần như
luôn là không thay được client.exe khi vẫn còn một process client.exe map nó. ApexProtect chạy
double_mode nên để lại một process thứ hai, đóng cửa sổ rồi không có nghĩa là process đã chết.
Get-Process | Where-Object { $_.Path -like 'D:\AvatarStarDev\*' }Kiểm cái đó trước khi đổ cho bản release. Kênh patch không phát hiện được tình huống này và cũng không nói gì: lần sau launcher vẫn rao đúng bản update ấy rồi hỏng y hệt, chừng nào process còn sống.
Muốn đọc thông báo lỗi cho đúng thì đọc bản tiếng Trung. Text tiếng Anh là bản cẩu thả nhất trong
năm thứ tiếng. Cùng id 0x4000005a, tiếng Anh ghi Auto patch Error, Error Code=0x%%x, tiếng Trung
ghi 解包錯誤, nghĩa là lỗi giải nén. Dev viết tiếng Trung trước rồi mới dịch ra.
Thời điểm launcher gọi mạng
Phần tiêu đề “Thời điểm launcher gọi mạng”Launcher không kiểm tra update lúc khởi động. Mở lên rồi ngồi ở màn hình login thì không có một request HTTP nào.
| Thao tác | Launcher tải gì |
|---|---|
| launcher mở lên | không gì cả |
| bấm LOGIN | ServerList/recommend.xml (×2) |
| bấm ENTER ở chọn server | GameUpdate/update.xml (×4), rồi từng <Url>, rồi update.xml lần nữa |
Payload bị tải hai lần. Nhiều khả năng là đo kích thước trước rồi mới GET thật, nhưng chưa xác nhận. Cứ tính gấp đôi băng thông cho chắc.
asup.exe không phải cái tải file. Bảng import của nó chỉ có KERNEL32 với SHELL32, không có hàm
mạng nào. Nó là công cụ copy file local, launcher gọi ra để áp phần đã tải xong. Cái tải file là
chính AvatarStar.exe.
Rollback
Phần tiêu đề “Rollback”Rollback đi qua đúng kênh đó: publish nội dung cũ như một bản release mới, version cao hơn. Vòng đầy đủ gồm publish, launcher cài, text đổi trong game, rồi rollback qua cùng kênh và text đổi lại, đã chạy thật trên client thật.
Không có cơ chế gỡ patch. Client không giữ bản cũ.
Bản nháp đang review. Nội dung nội bộ, đừng chia sẻ ra ngoài nhóm.