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

5.4 KiB
Raw Permalink Blame History

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_TIMEPostMessage(MSG_SERVERTIME)SetServerTime GameSession.csCommandID.SERVER_TIME: parse cmd_server_time, PostToUnityContextEC_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.