Phoenix
Dự án port 1:1

Dựng lại Block Blast sang Cocos Creator, giống bản gốc đến từng khối.

Port game puzzle com.block.juggle từ APK sang Cocos Creator 3.8.8 + TypeScript. Giữ nguyên thuật toán chọn khối, luồng màn và giao diện; đối chiếu từng màn bằng SSIM, từng thuật toán bằng chạy lại C++ trên máy thật.

Cocos Creator 3.8.8TypeScript strictClassic + AdventureReverse engineering
Lưới 8×8 · khay 3 khối SSIM mục tiêu ≥ 0.95
Quy mô mã nguồn

Dự án trong con số

Đếm trực tiếp từ repo (ngày 2026-10-05): thư mục game/, tools/ và lịch sử git.

90
file TypeScript trong game/assets/scripts
35
file trait chiến lược (độ khó / sinh khối)
102
skin trong resources/skin
96
level chapter Adventure
115
commit (2026-09-16 đến 2026-10-02)
30
file test tự động
4
scene: Boot, Home, ChapterMap, Game
642
thuật toán sinh khối đăng ký
Đo độ trung thực

Parity thuật toán với bản gốc

Engine sinh khối được port byte-verbatim từ bundle gốc (3.832.189 byte khớp tuyệt đối, 642 thuật toán đăng ký). Vì bản gốc có thể chạy WASM/C++, parity được kiểm bằng cách chạy lại C++ trên máy thật rồi so id khối với bản TypeScript.

525/528
id khớp where-C++-ran (99,4%)
28
thuật toán đối chiếu (mở rộng từ 13)
672
case: 24 bàn × 28 thuật toán
22
thuật toán C++ chạy thật trên máy

3 id lệch còn lại

Cả 3 thuộc thuật toán 16005 trên bàn dày, do ngân sách 100 ms của máy chậm chứ không phải lỗi logic.

6 thuật toán C++ không cài

10005, 12039, 14021, 29004, 29029, 291054 không có trong C++ nên rơi về TS, đúng như bản gốc.

Trạng thái REQ-001 vẫn là partial: parity đo thủ công, chưa có test tự động tương đương.

Kiến trúc

Logic thuần tách khỏi giao diện

Toàn bộ luật chơi nằm ở logic/ và không import cc; View chỉ gọi qua bridge theo hợp đồng createGame / applyInput / snapshot. Nhờ vậy replay chạy được trong Node mà không cần engine.

Boot / QA
app/Boot.ts, app/qa.ts, app/screens.ts. Điểm vào, đăng ký và mở màn theo id, chế độ QA (seed, settle, pause, ready).
gọi qua
View
HomeView, GameView, ChapterMapView, DailyStreak, NewPlayerIncentive, PressFx, NativeVibrator. Chỉ render, nhận input, vẽ ghost và khay.
gọi qua
Bridge
adapter/GameBridge.ts, adapter/ChapterBridge.ts. Nối View với core; view không giữ logic.
gọi
Core Classic / Chapter
logic/ClassicGame.ts, logic/board/Board.ts, logic/chapter/ChapterGame.ts. Khay, đặt khối, xoá hàng/cột, combo/miss, thua, điểm; Chapter kế thừa Classic theo mục tiêu màn.
dùng
Engine sinh khối
logic/algo/puzzleEngine.generated.ts, atomEngine.generated.ts, puzzleUtil.ts, ratioPool.ts. 642 thuật toán, byte-verbatim từ gốc.
Chiến lược
logic/strategy/ClassAlgorithmOrchestrator.ts, algorithmProcess.ts, OfferType.ts, traits/*. Tầng "sau OFFER", điều phối các trait chỉnh độ khó.
ML / cá nhân hoá
logic/ml/: lightgbm, policyTable, stateKey, abilityChurnProxy, applyOfferRec, mlPersonalize, gameRuleEngine… (10 file).
RNG & dữ liệu
logic/rng/FixedRandomUtil.ts (tái lập replay), logic/config, logic/data (init config, tuning, tập offer/shape, guide steps).
Luật chơi

Classic và Adventure

Mọi con số bên dưới port 1:1 từ ClassScoreInfo của bundle gốc và có test hồi quy.

Classic (vô tận)

  • Lưới 8×8, khay 3 khối mỗi lượt.
  • Đặt khối, xoá hàng/cột đầy, combo và miss.
  • Có điều kiện thua, khớp bundle gốc (REQ-002).
  • Khối do engine + các trait chọn, không phải ngẫu nhiên thuần.

Adventure / Chapter

  • Bản đồ 96 level, chapter "Graduation", nguồn LevelConfigGameL49 (giải mã HEK type03).
  • Hai kiểu mục tiêu: score (Way=0) và collect (Way=1).
  • Dữ liệu level ở resources/chapter/levels.json, đi qua level converter.

Công thức điểm

Điểm nền

Bằng số ô của khối vừa đặt.

Combo

1 dòng: 10·c. Từ 2 dòng: 10·c·lines·(lines−1).

Thưởng combo

combo > 10 nhân 2; combo > 5 nhân 1,5 (làm tròn lên). Xoá sạch màn: 300 điểm khi round > 5.

combo += max(0, eliminateCount − 1) // multi-clear tăng combo thêm: 2 dòng +1, 4 dòng +3

Combo sống lâu hơn

Trait ComboTimeTrait nới ngưỡng reset combo thành comboAllowNoContinuousTimes(3) + số khối còn lại trong khay. Đây là bản vá cho lỗi "điểm port chậm hơn game thật", xác nhận bằng probe trên máy thật (7/7 mẫu).

Dữ liệu và tài nguyên

Data-driven, trích từ APK gốc

Level, skin, hiệu ứng và âm thanh đều nằm ở game/assets/resources/. Bundle gốc mã hoá HEK nên được giải mã khi RE rồi mới nạp.

Thư mụcNội dungSố lượng quan sát
chapterLevel Adventure96 level
skin, skineffect, skinfontTheme, hiệu ứng, font theo skin102 skin
sfxÂm thanh27 file
mlBảng policy cá nhân hoápolicy.json
effect, effects, font, fonts, ui, prefabs, preview, newPlayerIncentiveHiệu ứng, UI, prefab, preview, khuyến khích người chơi mớicó trong repo

Bắt dữ liệu remote

Game tải bundle từ server về cache máy (/data/data/com.block.juggle/files/gamecaches/). File trên đĩa vẫn mã hoá HEK type01, app giải mã trong RAM; RE dùng Frida để dump hoặc copy PNG đã giải mã.

Thang nguồn bắt buộc

  • Dùng nguồn có sẵn, cite file/hàm gốc.
  • Thiếu thì tạo task cho RE lấy thêm.
  • RE cũng không lấy được thì lập ASM và chờ người dùng duyệt.
Quy trình

Từ APK tới bản chơi được

Mỗi vai bàn giao qua tài liệu và checklist; không bước nào tự dựng logic thiếu bằng chứng gốc.

P1 · RE
Decompile, giải mã bundle HEK, trích asset / level
P2 · Reference
Chụp màn thiết bị thật 1080×1920
GD
Chốt cơ chế và Replay contract
Dev
Core TS thuần + scene qua Cocos MCP
QA
Build, chụp, SSIM, replay 100%
VaiChạy ởViệc chính
POClaude CodeĐiều phối phase, tạo task, gác cổng, review
RECursorDecompile, giải mã, trích asset/level, bắt dữ liệu remote, chụp reference
GDsub-agentCơ chế, level, UX từ nguồn gốc và Replay contract
Devsub-agent + CodexCore TypeScript thuần, scene qua MCP, level converter
Artsub-agentImport asset gốc, reskin ở giai đoạn Polish
QAsub-agentBuild, chụp, so SSIM, replay test
Nghiệm thu

Màn đối chiếu và cách kiểm

Chụp từ Xiaomi Mi A1 (tissot), Android 14: 1080×1920, 440 dpi, DPR 2,75. Thư mục reference/ có 6 ảnh, 5 màn đầu nằm trong scope chính thức.

01HomeAdventure · Classic · More Games · Settings
02SettingsSound · BGM · Medal · More Settings · Daily Streak
03ClassicGameplay lưới 8×8, score và best
04AdventureBản đồ level 1 đến 96
05Adventure LevelGameplay theo mục tiêu màn

So ảnh

Chế độ QA mở màn theo ?screen=, dừng logic rồi báo ready để chụp. Đạt khi SSIM ≥ 0,95 so với reference/.

Replay

Seed cố định cho chuỗi khối xác định; harness ở tools/replay/. Mục tiêu replay pass 100%.

Test case theo nhóm

QA giữ checklist TC-<NHÓM>-xxx ở qa/cases/, gắn với mã yêu cầu.

Quyết định

Vì sao dự án đi theo hướng này

Cocos là bản chính

Bản Cocos Creator 3.8.8 (game/) tiếp tục phát triển; bản Phaser (phaser/) bị drop, giữ để tham khảo.

Không đoán

Mọi thay đổi thuật toán/gameplay phải có bằng chứng gốc, gắn nhãn SRC, ĐỐI-CHIẾU-GỐC, DEVICE hoặc TEST.

Tách artifact nặng

Dữ liệu decompile (2,6 GB) chuyển ra ref_src/ và đưa vào .gitignore; docs giữ phẳng theo vai trò.

Kick-off (2026-09-28)Giá trị
GoalPort 1:1, giống game gốc 100%
Phạm viClassic + Adventure; đối chiếu 1:1 màn hình và parity thuật toán
Ngưỡng SSIM0,95
AutopilotBật, chạy tới hết Polish, dừng trước Reskin; kế hoạch review luôn chờ người dùng duyệt
Chạy thử

Lệnh có sẵn trong package.json

npm testTest logic và replay (tools/, monitor/)
npm run build:webBuild bản web
npm run build:androidBuild bản Android
npm run qa:captureChụp màn để so ảnh
npm run qa:compareSo SSIM với reference/
npm run scene:bootTạo scene Boot
npm run mcp -- <tool> '<json>'Gọi Cocos Editor MCP khi không có MCP trực tiếp
npm run monitorWebsite giao việc, duyệt cổng: http://127.0.0.1:4700

Công nghệ

Cocos Creator3.8.8
TypeScriptstrict
Logic corekhông import cc
LevelJSON data-driven
RNGcố định, replay xác định
QASSIM + replay harness
REFrida, giải mã HEK
Chưa rõ

Câu hỏi còn mở

Version APK gốc

Chưa chốt version chính thức để làm chuẩn parity. Cần hỏi người dùng.

Link Play Store

Chưa có trong tài liệu. Cần hỏi người dùng.