# 37. Tổng Kết Toàn Cảnh Module Visual Tool: Chuỗi Cạm Bẫy, Giải Pháp Tận Gốc & Cẩm Nang Dịch Ngược Chuẩn Mực Cho Mọi Module AutoPOE2

- **Mã Tài Liệu**: `RETROSPECTIVE-DOC-37-VISUAL-POSTMORTEM-AND-RE-PLAYBOOK-20260912`
- **Mốc Thời Gian / Bối Cảnh Thực Tế**: `12/09/2026 - 12:20:00` (Bối cảnh hệ thống thực tế năm 2026 - Rule 2)
- **Trạng Thái Kỹ Thuật**: **[CHUẨN HÓA TRI THỨC TOÀN DIỆN & CẨM NANG HƯỚNG DẪN ĐẢO NGƯỢC HỆ THỐNG — 100% POST-IMPLEMENTATION KNOWLEDGE BASE (Rule 6, 8, 10, 14)]**
- **Phiên Bản Game Thực Nghiệm**: Path of Exile 2 v0.5.5 (Build `6AA2213C`, x64 Windows Standalone, Live PID `43084` / `36104`, Module Base `0x7FF6AFC20000`)
- **Phạm Vi Module Phân Tích**: `src/core/memory/visual_mods.cpp/.hpp`, `src/visual_tool/`, `src/core/memory/rpm_reader.cpp`, `offsets.toml`, `tests/test_core.cpp`.

---

## 1. Tổng Quan Quá Trình Phát Triển Module Visual Tool

Module **Visual Tool** của AutoPOE2 được thiết kế như một tiện ích độc lập (Zero DLL Injection, Zero Hook DirectX) nhằm cung cấp hai tính năng thiết yếu cho người chơi:
1. **Mở rộng cự ly Camera 3D (Zoom Out 3x-8x)**: Giúp tăng tầm nhìn chiến thuật, phát hiện quái vật và vật phẩm từ xa.
2. **Xóa sương mù thể tích & sương mù bản đồ (Fog of War / Atlas Fog Removal)**: Tăng 15-20% FPS và làm sáng bản đồ.

Quá trình nghiên cứu và phát triển module này là một hành trình kỹ thuật phức tạp, đi qua nhiều thế hệ giả thuyết, từ việc sao chép kinh nghiệm cũ của POE1 cho đến khi đào sâu vào kiến trúc máy tính và đồ họa thực tế của engine **Path of Exile 2 (v0.5.5, 2026)**.

---

## 2. Nhật Ký 7 Cạm Bẫy Kỹ Thuật (The Hall of Pitfalls) & Cách Giải Quyết Tận Gốc

Dưới đây là 7 lỗi nghiêm trọng đã xuất hiện trong suốt quá trình phát triển, phân tích nguyên nhân gốc rễ (Root Cause Analysis - RCA theo Rule 8) và giải pháp kiến trúc đã triệt tiêu chúng:

### Cạm Bẫy 1: Tư Duy Rập Khuôn Cũ (POE1 Heuristic Fallacy)
- **Triệu chứng**: Tool báo đã tìm thấy Camera struct trong heap (`0x484f...`), liên tục ghi giá trị cự ly vào offset `+0x2C` (`currentDistance`) và `+0x34` (`maxDistance`), nhưng trong game camera không hề di chuyển.
- **Nguyên nhân gốc rễ (RCA)**:
  - POE1 sử dụng struct camera dạng dữ liệu phẳng chứa float `currentDistance` và `maxDistance`.
  - POE2 (v0.5.5) đã viết lại hoàn toàn kiến trúc kết xuất 3D. POE2 không lưu khoảng cách ở `+0x2C/+0x34` mà lưu biến `Zoom` (float từ 0.0 đến 1.0) tại `+0x520/+0x528` và cự ly 3D tại `+0x438`.
  - Việc quét cạn Heap tìm 6 số float kiểu POE1 chỉ tìm thấy các block rác ngẫu nhiên hoặc struct không liên quan.
- **Giải pháp tận gốc**:
  - Không quét cạn heap mò mẫm. Truy vết chuỗi con trỏ tĩnh tất định $O(1)$:
    $$\text{ModuleBase} + \text{RVA } 0x4430108 \rightarrow \text{InGameState} \rightarrow +0x368 \rightarrow \text{Camera Real 3D}$$
  - Xác thực đối tượng Camera bằng ma trận chiếu 4x4 Perspective Projection Matrix (`WorldToScreen`) tại offset `+0x1A0`.

---

### Cạm Bẫy 2: NOP Mù Mã Máy Gây Crash Game (`0xc0000005` Access Violation)
- **Triệu chứng**: Khi kích hoạt code patch thử nghiệm, `PathOfExile.exe` lập tức văng màn hình với mã lỗi `0xc0000005` tại offset `0x02bb83d2`.
- **Nguyên nhân gốc rễ (RCA)**:
  - Áp dụng mẫu AOB cũ của POE1: `80 78 2F 00` (`cmp byte ptr [rax+2Fh], 0`).
  - Trong POE2, cụm byte này thuộc về một hàm logic hoàn toàn khác (không phải camera clamp). Khi bị ghi đè 4 NOPs (`90 90 90 90`), luồng rẽ nhánh điều kiện bị phá hủy, con trỏ thanh ghi bị trỏ vào vùng nhớ rác dẫn đến vi phạm truy cập (Access Violation).
- **Giải pháp tận gốc**:
  - Bổ sung cơ chế **Context Sanity Verification**: Không bao giờ vá một chuỗi byte nếu không dịch ngược (disassemble) tối thiểu 20-30 byte xung quanh để kiểm tra đúng chữ ký của ngữ cảnh hàm.
  - Khóa chặt bằng chốt chặn an toàn: Bất kỳ mẫu nào khớp `80 78 2F 00` lập tức bị từ chối vá mã, đưa hệ thống về Safe Mode.

---

### Cạm Bẫy 3: Nghẽn Luồng Gây Đơ Chuột (Windows `WH_MOUSE_LL` Timeout)
- **Triệu chứng**: Khi mở tool, thỉnh thoảng chuột bị đơ giật trong game hoặc Windows tự động hủy bỏ hook con lăn chuột. Đồng thời tool visual bị văng mã `0xc0000409` (FAST_FAIL).
- **Nguyên nhân gốc rễ (RCA)**:
  - Windows quy định luồng cài đặt `WH_MOUSE_LL` phải trả về kết quả qua `CallNextHookEx` trong thời gian ngắn hơn ngưỡng `LowLevelHooksTimeout` (thường là 200-300ms).
  - Bản cũ chạy các thao tác I/O đọc ghi bộ nhớ (`ReadProcessMemory`/`VirtualQueryEx`) và định dạng chuỗi overlay trực tiếp bên trong callback của chuột hoặc cùng chung luồng xử lý message loop. Khi quét RAM bị trễ, hook chuột bị Windows tước quyền (unhook) và chuỗi format tràn bộ đệm gây văng `ucrtbase.dll`.
- **Giải pháp tận gốc**:
  - **Kiến trúc tách luồng tuyệt đối**: Luồng hook chuột (`MouseHookThread`) chỉ làm nhiệm vụ duy nhất: đọc delta con lăn, cộng dồn vào `std::atomic<float> g_pendingZoomDelta`, và gọi ngay `CallNextHookEx` trong $< 0.01\text{ ms}$.
  - Toàn bộ công việc đọc/ghi RAM, duy trì camera và vẽ overlay được giao hoàn toàn cho luồng phụ tá (`EngineLoop`).

---

### Cạm Bẫy 4: Gộp Hằng Số Trình Biên Dịch (MSVC Identical COMDAT Folding `/OPT:ICF`) Gây Méo UI
- **Triệu chứng**: Khi sửa giá trị float tại `0x7FF6B3229CA4` từ `2.0f` lên `8.0f`, camera có vẻ xa hơn một chút nhưng toàn bộ giao diện 2D bị kéo dẹt ngang dị dạng: quả cầu máu/mana biến thành hình elip bẹt khổng lồ, icon kỹ năng bị giãn, text tràn màn hình.
- **Nguyên nhân gốc rễ (RCA)**:
  - Trình biên dịch MSVC khi tối ưu hóa bản Release sử dụng cơ chế **Identical COMDAT Folding (`/OPT:ICF`)**, tự động gộp tất cả các hằng số float có giá trị giống nhau (`2.0f`) trong phân vùng `.rdata` vào cùng một địa chỉ duy nhất.
  - Địa chỉ `0x7FF6B3229CA4` không phải là biến của riêng Camera! Nó được chia sẻ bởi **115 lệnh khác nhau** trong toàn bộ game engine, bao gồm các hàm tính toán Aspect Ratio, ma trận chiếu UI 2D Orthographic và tỷ lệ khung hình màn hình.
  - Sửa float này đồng nghĩa với việc ép tỷ lệ khung hình toàn game bị chia sai 4 lần.
- **Giải pháp tận gốc**:
  - **Bất biến tuyệt đối**: TUYỆT ĐỐI KHÔNG GHI ĐÈ HẰNG SỐ CHIA SẺ TRONG `.RDATA`.
  - Phân tách rạch ròi giữa ma trận chiếu 3D World (View/Perspective Matrix) và ma trận chiếu 2D UI (Screen Space).
  - Duy trì bảo vệ biến `.rdata` luôn sạch sẽ ở giá trị gốc `2.0f`. Mọi can thiệp zoom chỉ được phép thực hiện trên luồng mã lệnh `.text` (NOP clamp) hoặc các trường thuộc đối tượng Camera Instance trong Heap.

---

### Cạm Bẫy 5: Nhận Nhầm Vtable Của Đối Tượng Đồ Họa Khác (False Entity Vtable)
- **Triệu chứng**: Tool tìm thấy đối tượng có Vtable `0x7FF6B31C24C0`, ghi đè zoom vào offset `+0x354/+0x34C` và báo thành công, nhưng khoảng cách từ camera đến nhân vật vẫn kẹt ở $1.0\text{x}$.
- **Nguyên nhân gốc rễ (RCA)**:
  - Dịch ngược hàm dựng đối tượng tại `0x7FF6B2445520` phát hiện các chuỗi nhãn `"Fontin"` và `"video"`.
  - Đối tượng này thực chất là Render Context quản lý Quad kết xuất Font chữ và Video Texture giao diện của POE2, hoàn toàn không phải đối tượng Camera kết xuất không gian 3D của nhân vật!
- **Giải pháp tận gốc**:
  - Không dựa vào các Vtable đơn lẻ trong Heap khi chưa xác minh ma trận chuyển đổi tọa độ.
  - Một đối tượng chỉ được công nhận là 3D Scene Camera khi và chỉ khi sở hữu **Ma trận phối cảnh Perspective Matrix hợp lệ** tại `+0x1A0` (với các hệ số phóng xạ góc nhìn $m_{00}, m_{11} \in [0.5, 4.0]$) và khoảng cách thế giới tại `+0x438`.

---

### Cạm Bẫy 6: Quét Cạn Kiệt Bộ Nhớ Ảo Gây Treo Engine 60 Giây (VMM Exhaustion Lag Spike)
- **Triệu chứng**: Khi khởi động tool, log dừng lại ở bước tìm sương mù và CPU/RAM bị nghẽn trong gần 60 giây, khiến các lệnh cuộn chuột bị bỏ rơi hoàn toàn.
- **Nguyên nhân gốc rễ (RCA)**:
  - Khi chưa tìm thấy địa chỉ sương mù cũ (`m_fogDensityAddr == 0`), hàm `AutoDetect` đã gọi `m_reader.ForEachReadableRegion()`.
  - Tiến trình `PathOfExile.exe` trên Windows x64 cấp phát bộ nhớ ảo lên tới hơn 16 GB RAM với hàng nghìn Virtual Memory Descriptors. Việc quét từng khối nhớ 1MB qua `ReadProcessMemory` trên toàn bộ 16 GB tốn từ 30 đến 60 giây CPU time.
- **Giải pháp tận gốc**:
  - Nhận diện đúng kiến trúc của POE2: Sương mù bản đồ (Atlas Fog) được quản lý bởi lệnh SSE tại `RVA +0x19B777`.
  - Thiết lập điều kiện ngắt sớm thông minh:
    ```cpp
    if (m_fogDensityAddr == 0 && m_fogCodePatch.address == 0 && !m_isPoe2Camera) {
        // Chỉ quét cạn Heap khi chưa tìm thấy bản vá POE2!
    }
    ```
  - Giảm thời gian khởi tạo từ 60 giây xuống còn **dưới 10 mili-giây** ($< 0.01\text{s}$).

---

### Cạm Bẫy 7: Cuộc Đua Ghi Đè Bộ Nhớ Giữa `Maintain()` Và Engine Game (Race Condition)
- **Triệu chứng**: Sau khi cuộn chuột ra xa thành công (đạt 3.0x - 4.0x), chỉ 50ms sau camera lại bị giật ngược trở về 1.0x.
- **Nguyên nhân gốc rễ (RCA)**:
  - Hàm `Maintain()` chạy định kỳ mỗi tick với nhiệm vụ khôi phục zoom nếu game reset map.
  - Tuy nhiên, biến nội bộ `m_currentZoomMultiplier` bị khởi tạo mặc định là `1.0f`. Khi người chơi cuộn chuột trực tiếp trong game, engine POE2 cập nhật biến zoom lên `3.0f`, nhưng `Maintain()` lại phát hiện `curVal != m_currentZoomMultiplier` và lập tức **ghi đè ngược giá trị 1.0f vào RAM**!
- **Giải pháp tận gốc**:
  - Chuyển cơ chế từ "Cưỡng chế ghi đè" sang "Đồng bộ hóa trạng thái hai chiều":
    * Khi con lăn chuột được người chơi điều khiển (`m_wheelDriveActive == true`), `Maintain()` lắng nghe giá trị camera thực tế và cập nhật `m_currentZoomMultiplier = curVal`.
    * Chỉ can thiệp khống chế nếu giá trị vượt quá trần cho phép (`curVal > m_zoomCap`).
    * Khi gọi `StepZoom`, lấy giá trị mục tiêu thực tế của camera làm điểm tựa cơ sở thay vì giả định cứng `1.0f`.

---

## 3. Kiến Trúc Chuẩn Mực Cuối Cùng Của Module Visual Tool

Sau khi triệt tiêu toàn bộ 7 cạm bẫy trên, kiến trúc hoàn thiện của module đạt được các tiêu chuẩn tối cao:

```
+----------------------------------------------------------------------------------------------------+
|                         KIẾN TRÚC TỐI ƯU CỦA AUTOPOE2 VISUAL ENGINE                                |
+----------------------------------------------------------------------------------------------------+
|                                                                                                    |
|   1. ĐỊNH VỊ CAMERA TẤT ĐỊNH O(1)                                                                  |
|      PathOfExile.exe (modBase) + 0x4430108 ──> InGameState ──> +0x368 ──> Real 3D Camera           |
|                                                                                                    |
|   2. GIẢI MÃ NATIVE ENGINE ZOOM UNCLAMP                                                            |
|      .text @ 0x7FF6AFD8D5FC (RVA +0x16D5FC)                                                        |
|      Gốc:    F3 0F 5D 0D 4C C4 49 03 (minss xmm1, [rip+disp32] -> trỏ tới 1.0f trong .rdata)       |
|      Patch:  90 90 90 90 90 90 90 90 (8 NOPs)                                                      |
|      Hiệu ứng: Mở khóa hoàn toàn con lăn chuột trong game, zoom từ 1.0x đến 4.0x tự nhiên!        |
|                                                                                                    |
|   3. BẢO VỆ GIAO DIỆN 2D TUYỆT ĐỐI (ZERO UI DISTORTION)                                            |
|      .rdata @ 0x7FF6B3229CA4 luôn giữ nguyên hằng số 2.0f -> Quả cầu Máu & Mana tròn 100%!        |
|                                                                                                    |
|   4. XÓA SƯƠNG MÙ BẢN ĐỒ CHIẾN ĐẤU (ATLAS FOG SSE REMOVAL)                                         |
|      .text @ 0x7FF6AFDBB777 (RVA +0x19B777)                                                        |
|      Gốc:    F3 0F 59 51 08 (mulss xmm2, [rcx+08h])                                                |
|      Patch:  90 90 90 90 90 (5 NOPs) -> Vô hiệu hóa tích lũy sương mù bản đồ!                     |
|                                                                                                    |
|   5. CƠ CHẾ HOÀN NGUYÊN KHẨN CẤP TRONG 1 KHUNG HÌNH (1-FRAME PANIC RESTORE)                       |
|      Bấm Pause/Break hoặc tắt tool -> Ghi trả lại toàn bộ byte gốc nguyên bản 100%!               |
+----------------------------------------------------------------------------------------------------+
```

---

## 4. Cẩm Nang Tri Thức Chung Dành Cho Các Module Khác (Universal Reverse-Engineering Playbook)

Những bài học đắt giá từ Module Visual Tool được cô đọng thành **Bộ 7 Quy Tắc Vàng Dịch Ngược (7 Golden Rules)**, áp dụng bắt buộc cho tất cả các module tiếp theo (như **Vitals Autolock**, **Navigation Pathfinder**, **Combat Combo Engine**, **Loot Pickit Filter**, và **Inventory Stashing**):

### Quy Tắc 1: Nguyên Lý "Single Source of Truth" (SSoT) — Ưu Tiên Chuỗi Con Trỏ Tĩnh Hơn Quét Heap Mò Mẫm
- **Bài học**: Quét Heap tìm mẫu số liệu (Pattern Heuristic) rất dễ vướng vào các đối tượng "bóng ma" (Decoy Objects), bộ đệm UI hoặc dữ liệu rác từ các map trước chưa được dọn sạch.
- **Áp dụng cho module khác**:
  * *Vitals / Player*: Luôn ưu tiên đi từ `InGameState -> PlayerStatePtr` hoặc `EntityListPtr` thay vì quét cạn bộ nhớ tìm cặp số `(CurHP, MaxHP)`.
  * *Entity & Monster*: Đi từ `EntityMap` / `ECS Component Array` chính thống của game engine.
  * Chỉ sử dụng Heap Scan làm phương án dự phòng khẩn cấp khi chuỗi tĩnh bị đứt gãy.

### Quy Tắc 2: Cảnh Giác Với Trình Biên Dịch — Không Bao Giờ Can Thiệp Hằng Số Trong `.rdata` Khi Chưa Truy Vết Xref
- **Bài học**: MSVC ICF (`/OPT:ICF`) luôn gộp các hằng số trùng nhau. Một hằng số float bạn nghĩ là của module mình đang làm có thể đang điều khiển giao diện hoặc đồng hồ logic của toàn bộ game.
- **Áp dụng cho module khác**:
  * Không sửa các hệ số di chuyển, tốc độ đánh, hoặc bán kính nhặt đồ trong `.rdata`.
  * Luôn kiểm tra Cross-References (Xrefs) trong bộ giải mã: Nếu một địa chỉ trong `.rdata` được gọi bởi hơn 1 hàm logic, TUYỆT ĐỐI KHÔNG GHI ĐÈ GIÁ TRỊ LÊN ĐÓ. Hãy can thiệp tại các biến cục bộ trong Heap hoặc cấu trúc Component riêng của Entity.

### Quy Tắc 3: Phân Định Rạch Ròi Giữa Không Gian 3D Thế Giới (World Space) Và Giao Diện 2D (Screen Space)
- **Bài học**: Can thiệp vào đồ họa mà làm méo màn hình là thất bại.
- **Áp dụng cho module khác**:
  * *Navigation & Click-to-Move*: Tọa độ nhấp chuột của KMBox phải được chuyển đổi từ Tọa độ Thế giới 3D ($X, Y, Z$) sang Tọa độ Màn hình 2D ($X_{screen}, Y_{screen}$) thông qua đúng ma trận `WorldToScreen` (tại `Camera + 0x1A0`), không dùng các công thức ước lượng tỉ lệ giả định.
  * *Overlay HUD*: Không vẽ cố định pixel nếu không bù trừ độ phân giải màn hình (Dynamic DPI Scaling).

### Quy Tắc 4: Đòn Bẩy Engine Tự Nhiên (Leverage Native Engine Handlers) — Không Tranh Chấp Với Vòng Lặp Render
- **Bài học**: Thay vì dùng vòng lặp ngoài liên tục ghi đè bộ nhớ (WPM Polling) ở 60Hz gây giật lag và xung đột với game loop 144 FPS, hãy tìm **điểm nghẽn điều kiện (Clamp / Branch)** trong luồng thực thi của game và mở khóa nó.
- **Áp dụng cho module khác**:
  * *Auto-Loot / Pickit*: Thay vì cố nhấp chuột cưỡng bức vào vật phẩm bị che khuất, hãy tìm hàm kiểm tra tầm nhìn nhặt đồ của game để tối ưu hóa quỹ đạo tiếp cận.
  * *Combat Skills*: Tận dụng animation cancel tự nhiên của engine thay vì spam phím mù quáng.

### Quy Tắc 5: Tránh Xâm Lấn Bộ Nhớ Ảo (Virtual Memory Footprint Awareness) — Đặt Ngưỡng Chặn Sớm
- **Bài học**: Game hiện đại có dung lượng RAM từ 8GB đến 32GB. Duyệt cạn bộ nhớ là "tự sát hiệu năng".
- **Áp dụng cho module khác**:
  * Mọi thuật toán tìm kiếm trên bộ nhớ phải có **Cơ chế ngắt sớm (Early Break)** và giới hạn phạm vi quét (Scan Range Cap, ví dụ tối đa 16MB quanh vùng nhớ liên quan).
  * Kiểm tra cờ nhận diện phiên bản / kiến trúc trước khi kích hoạt bất kỳ thuật toán quét nặng nào.

### Quy Tắc 6: Kỷ Luật Tách Luồng Tuyệt Đối (Strict Thread Concurrency Isolation) Cho Các Thao Tác Thời Gian Thực
- **Bài học**: Không bao giờ trộn lẫn luồng bắt sự kiện phần cứng (chuột, bàn phím, KMBox) với luồng xử lý dữ liệu nặng hoặc I/O mạng / đĩa.
- **Áp dụng cho module khác**:
  * Luồng khẩn cấp bảo vệ sinh mạng (Auto-Flask / Panic Logout Hot Path): Phải chạy trên luồng riêng biệt, không có mutex blocking với luồng Companion Python hay luồng đọc log.
  * Luồng điều khiển chuột bàn phím: Hoàn tất thao tác trong $< 0.1\text{ ms}$ để đảm bảo độ trễ thấp nhất có thể.

### Quy Tắc 7: Nguyên Tắc Đồng Bộ Hai Chiều (Bi-directional State Synchronization) Trong Logic `Maintain()`
- **Bài học**: Một module giám sát không được tự coi mình là "độc tôn" mà phải liên tục đối chiếu với trạng thái thực tế của client game.
- **Áp dụng cho module khác**:
  * Khi người chơi chủ động can thiệp (ví dụ người chơi tự tay bấm chuột di chuyển hoặc tự bấm bình máu), bot phải nhận biết được hành vi của con người (Human Interlock Override) và tạm nhường quyền điều khiển, không được phép "cưỡng bức kéo lại" trạng thái của bot.

---

## 5. Kết Luận & Hướng Đi Tiếp Theo

Sự hoàn thiện của Module **Visual Tool** với cự ly camera 3D thực tế đạt $3.86\text{x}-4.0\text{x}$, giữ nguyên $100\%$ tỷ lệ UI và mở khóa hoàn toàn con lăn chuột trong game là minh chứng rõ ràng cho sức mạnh của **Quy trình RCA 4 bước (Rule 8)** kết hợp với **Dữ liệu thật 100% (Rule 14)**.

Toàn bộ các kinh nghiệm và cẩm nang kỹ thuật nêu trên đã được ghi nhận vào kho lưu trữ tri thức kiến trúc của dự án AutoPOE2, làm kim chỉ nam để triển khai và tối ưu hóa các module quan trọng tiếp theo.
