Files
test/Docs/ServerTime_SunMoon_MiniMap.md
2026-05-25 10:33:40 +07:00

86 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Server time, SunMoon phase, và đồng hồ minimap (PC → Unity)
Tài liệu tóm tắt luồng thời gian server, `SetTimeOfTheDay`, đồng bộ main thread, và hiển thị canh giờ trên minimap — đối chiếu `CElementClient` (C++) với `perfect-world-unity` (C#).
---
## 1. `CECGame::SetServerTime` (PC — `EC_Game.cpp`)
- **`m_iTimeError = iSevTime - time(NULL)`** — lệch giây giữa Unix server và máy client.
- **`m_iTimeZoneBias`** — bias múi giờ theo **phút** (ví dụ Bắc Kinh thường **-480**).
- **`GetServerLocalTime()`** (không tham số):
`serverTime = GetServerGMTTime()` (= `time(NULL) + m_iTimeError`), rồi
`serverTime -= m_iTimeZoneBias * 60`, sau đó `gmtime` — tức “giờ địa phương server” dùng để lấy `tm_hour` / `tm_min` / `tm_sec`.
- **SunMoon:**
`nTimeInDay = hour*3600 + min*60 + sec`,
`SetTimeOfTheDay(nTimeInDay / (4.0f * 3600.0f))` — cùng công thức đã port sang Unity.
- **Lưu ý thiết kế PC:** chia `(4*3600)` + chuẩn hóa `[0,1)` làm **nhiều mốc giờ thật** có thể trùng cùng một phase (đã phân tích trong phiên làm việc); phần **UI canh giờ** trên PC lại dùng **`GetTimeOfTheDay()`** (không dùng trực tiếp `tm_hour` cho chuỗi minimap).
---
## 2. Unity — `EC_Game.Time.cs` (partial `EC_Game`)
- **`SetServerTime(int iSevTime, int iTimeZoneBias)`**
- Đồng bộ offset, tính phase giống PC (`iSevTime - bias*60` → giờ trong ngày → `/ (4f*3600f)`), gọi **`SetTimeOfTheDay`**.
- **`SetTimeOfTheDay(float vTime)`** — forward tới `CECSunMoon.Instance.SetTimeOfTheDay`.
- **`SyncSunMoonTimeOfDayFromServerClock()`** — giống cuối `CECGameRun::CreateWorld` / `CECWorld::InitNatureObjects`: lấy **`GetServerGMTTime()`** rồi áp dụng cùng công thức phase (helper nội bộ).
- Log debug có thể dùng tiền tố **`[Cuong]`** theo convention dự án.
---
## 3. Nơi gọi (đối chiếu PC)
| Nguồn (PC) | Unity đã nối |
|------------|----------------|
| Gói **`SERVER_TIME`** → `PostMessage(MSG_SERVERTIME)``SetServerTime` | `GameSession.cs`**`CommandID.SERVER_TIME`**: parse `cmd_server_time`, **`PostToUnityContext`** → `EC_Game.SetServerTime` + `EC_ManMessage.PostMessage` (queue không thread-safe). |
| Cuối **`CECGameRun::CreateWorld`** — set lại phase theo `GetServerLocalTime` | `LoginScreenUI.OnEnterWorldComplete` — gọi **`EC_Game.SyncSunMoonTimeOfDayFromServerClock()`**. |
**Lý do `PostToUnityContext`:** `NetworkManager` nhận socket trong **`Task.Run`**; gọi trực tiếp `SetServerTime` / `CECSunMoon` / `FindFirstObjectByType` trên luồng đó là **không an toàn** với Unity API và **race** với `EC_ManMessage` queue.
---
## 4. `CECSunMoon` (Unity)
- **`SetTimeOfTheDay`**: chuẩn hóa `[0,1)`, gán `m_vTimeOfTheDay`, gọi **`RefreshDayNightFactorsFromPhase()`**.
- **`Update`**: tăng phase theo `TIME_SCALE` (giống hướng PC), sau đó **`RefreshDayNightFactorsFromPhase()`**.
- **`RefreshDayNightFactorsFromPhase`**: port khối **`m_fDNFactor` / `m_fDNFactorDest`** từ `EC_SunMoon::UpdateWithTime` (PC), phục vụ logic minimap (ngày / sáng / hoàng hôn / đêm).
- Getter: **`GetTimeOfTheDay()`**, **`GetDNFactor()`**, **`GetDNFactorDest()`**.
---
## 5. Minimap — chuỗi canh giờ giống PC (`DlgMiniMap.cpp`)
Trên PC (trong `Render`), hint đồng hồ:
- `nTimeIndex = (int)(12 * GetTimeOfTheDay() + 0.5) % 12`
- `GetStringFromTable(1330 + nTimeIndex)` — tên **canh địa** (mười nhị canh).
- `int(GetTimeOfTheDay() * 24)` — số “giờ” hiển thị (theo phase game, không phải `tm_hour` server).
- `Format(GetStringFromTable(604), ...)` — template chuỗi (thường dạng `%s` + `%d` / tương đương).
- **`FixFrame(nTimeItem)`** — icon theo `fDNFactor` / `fDNFactorDest`: **TIME_DAY (0), TIME_MORNING (1), TIME_DUSK (2), TIME_NIGHT (3)**.
**Unity — `CDlgMiniMap.cs`:**
- **`UpdateSystemClockFromPcMiniMapLogic()`** mỗi `Update`, cùng công thức trên.
- SerializeField: **`_txtSystemTime`** (TMP), **`_imgSystemTime`** + **`_systemTimeSprites`** (4 sprite đúng thứ tự enum PC).
- Nếu chưa có `CECGameUIMan` / thiếu string: fallback tên **子…亥** và format **`{0}{1}时)`**.
**Editor:** gán TMP / Image / sprites trên prefab minimap để thấy chữ và icon; không gán thì không crash, chỉ không cập nhật UI tương ứng.
---
## 6. File chính liên quan
| Vai trò | Đường dẫn (Unity) |
|--------|---------------------|
| Thời gian server + phase | `Assets/PerfectWorld/Scripts/MainFiles/EC_Game.Time.cs` |
| SunMoon + DN factor | `Assets/PerfectWorld/Scripts/World/CECSunMoon.cs` |
| Nhận `SERVER_TIME` (main thread) | `Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs` |
| Vào world — sync lại phase | `Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs` (`OnEnterWorldComplete`) |
| UI canh giờ minimap | `Assets/PerfectWorld/Scripts/UI/MiniMap/CDlgMiniMap.cs` |
**PC tham chiếu:** `EC_Game.cpp` (`SetServerTime`, `GetServerLocalTime`), `EC_GameRun.cpp` (`MSG_SERVERTIME`, cuối `CreateWorld`), `Network/EC_GameDataPrtc.cpp` (`SERVER_TIME`), `DlgMiniMap.cpp` (đoạn `GetTimeOfTheDay` / string 604 / 1330), `EC_SunMoon.cpp` (`UpdateWithTime` — phần DN factor).
---
*Tài liệu được tạo để handoff nhanh; cập nhật khi đổi protocol bias (phút vs giây) hoặc khi marshal toàn bộ `HandleServerDataSend` lên main thread.*