Bỏ qua để đến nội dung

Ship một bản update

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ũ:

Terminal window
(Get-Item 'D:\AvatarStarDev\client.exe').VersionInfo.FileVersion

Manifest 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.

Terminal window
python3 research/01_pde_archive/pde_pack.py pack ~/as_build/tree_vi ~/as_build/vi_vn.new.pde \
~/as_build/manifest_vi.json
python3 research/16_add_content/fix_idhash_pde.py --fix ~/as_build/vi_vn.new.pde
python3 research/17_localized_art/verify_pack.py ~/as_build/vi_vn.new.pde

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ó.

Terminal window
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.txt

Mỗ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.

Terminal window
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.

Terminal window
python3 server/patch/stamp_version.py client.exe --version 1.4.0.64581

Quê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”
Terminal window
cp delta.dat server/patch/root/Update/Game/1.4.0.64580-1.4.0.64581/delta.dat

Manifest 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>.

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í.

<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 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.

Terminal window
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.

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 đ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.