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

Replace và Patch

Mọi bản update đều chạy qua đúng một đường ống. Chỗ khác nhau nằm ở thuộc tính PatchMode trên từng <Url> trong manifest, và nó chỉ nhận hai giá trị.

  1. Launcher tải GameUpdate/update.xml.
  2. So CurVersion trong manifest với version dưới máy. Lớn hơn thì mới chạy tiếp.
  3. Với mỗi block có SrcVer khớp, launcher tải từng <Url> về thành một file tạm, đặt tên theo PatchName.
  4. Applier nhận file tạm đó và xử lý theo PatchMode.

Bước 4 là chỗ hai chế độ tách nhau. Applier đọc mode ra rồi rẽ nhánh: Replace là 0, Patch là 1, giá trị nào khác thì entry bị bỏ qua và trả về -1.

Applier gọi CopyFileW(file_tạm, đích) rồi DeleteFileW(file_tạm). Hết, không có gì thêm. Đích lấy từ thuộc tính FileName, tính theo thư mục client, viết bằng \ cũng được, ví dụ avital\config.ini.

Chế độ này không quan tâm file là loại gì. .pde, .exe, .ini, .dat đối xử như nhau, vì nó chỉ là một lệnh copy.

Đơn vị là cả file. Sửa một dòng text trong pack tiếng Việt vẫn phải gửi đủ 33 MB, sửa một cái mesh trong base archive là 1,27 GB.

Bản full-install của nhà phát hành làm đúng kiểu này, SrcVer="*" và 38 <Url> toàn Replace:

<UpdateVersion SrcVer="*" DstVer="1.3.0.40458">
<Url PatchName="acdc.dat" FileName="acdc.dat" PatchMode="Replace">Update/Game/BaseVer/acdc.dat</Url>
<Url PatchName="AvatarStar.pde" FileName="AvatarStar.pde" PatchMode="Replace">Update/Game/BaseVer/AvatarStar.pde</Url>
...
</UpdateVersion>

Dùng Replace khi cài mới từ đầu, khi thay một file lẻ nằm ngoài archive, hoặc khi rebuild archive định kỳ để dọn page mồ côi.

Patch: mở file tạm ra như archive rồi thi hành danh sách lệnh

Phần tiêu đề “Patch: mở file tạm ra như archive rồi thi hành danh sách lệnh”

Applier mở file tạm PatchName như một container .pde, đọc /patch.lst ở trong đó ra, rồi thi hành từng dòng một.

Chỗ này hay làm người ta tắc: PatchName không phải một thư mục trên đĩa. Nó là đúng một file đã tải về, mà file đó tình cờ lại là archive .pde. Applier duyệt payload bằng chính VFS của engine, FindFirstFile trên %s/*.* chạy trên container chứ không phải trên filesystem.

Vì vậy FileName không được dùng tới ở chế độ này. Đích của từng file nằm sẵn trong patch.lst, nên nhà phát hành để FileName="".

Nhân tiện, đó cũng là lý do câu lỗi 0x4000005a bản tiếng Trung ghi 解包錯誤 nghĩa là lỗi giải nén: ở chế độ Patch có bước giải nén thật.

Đơn vị là một file nằm bên trong archive, không phải cả archive. Toàn bộ chỗ tiết kiệm nằm ở đây.

Replace Patch
Applier làm gì CopyFileW rồi xóa file tạm mở container, đọc patch.lst, thi hành từng op
Đơn vị gửi đi cả file từng file bên trong archive
FileName bắt buộc, là đường dẫn đích bỏ trống, đích nằm trong patch.lst
Sửa được gì trong .pde thay nguyên archive thêm, ghi đè, xóa từng entry
Sửa file ngoài archive được được, qua op không khớp archive nào
Kích thước điển hình 1.270.980.608 B cho base archive 45.056 B cho một file Lua 129 byte
Ai kiểm nội dung không ai không ai, xem delta.dat

Kênh Đài Loan đang chạy 61 block Patch so với 41 block Replace, mà 41 block Replace đó đều thuộc về đúng một bản full-install SrcVer="*". Tức là: Replace để cài lần đầu, Patch cho mọi thứ sau đó.

Con số đó cũng nói lên chuyện khác. Kênh này ship incremental nhiều năm nay rồi, chỉ là ta đọc nhầm PatchMode="Patch" nên suốt một thời gian dài bản release nào cũng đẩy nguyên archive 1,27 GB.

Chế độ nào cũng cần client.exe đã stamp mới dừng lại. Thứ chấm dứt một bản update là điều kiện CurVersion > local, không phải việc file đã copy xong. Payload không mang theo thứ gì làm version dưới máy nhích lên thì block đó chạy lại mỗi lần bấm ENTER. Chi tiết ở Ship một bản update.

Hỏng thì không ai báo. Applier có in lỗi, kiểu can not open file(%d): %s hay failed to write file '%s'., nhưng nó in ra stdout của CRT mà tiến trình GUI thì vứt stdout đi. Một bộ patch hỏng vẫn im như không có chuyện gì trên màn hình. Muốn biết chắc thì đi TOC của archive đích mà đối chiếu, đừng lấy việc không thấy dialog nào làm bằng chứng.

Bản nháp đang review. Nội dung nội bộ, đừng chia sẻ ra ngoài nhóm.