Add logic update time and show time in minimap
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using BrewMonster.Scripts;
|
||||
|
||||
|
||||
//TODO: [DUCK] EC_Game shouldn't be in BrewMonster.Network namespace, it should be in BrewMonster.Scripts namespace.
|
||||
@@ -16,20 +17,52 @@ namespace BrewMonster.Network
|
||||
private static float m_dwRealTickTime; // Real tick time
|
||||
|
||||
public static int GetTimeZoneBias() { return m_iTimeZoneBias; }
|
||||
|
||||
/// <summary>
|
||||
/// 与 PC CECGameRun::CreateWorld / CECWorld::InitNatureObjects 末尾一致:按当前服务器钟面刷新昼夜相位 // Match PC after world load / nature init
|
||||
/// </summary>
|
||||
public static void SyncSunMoonTimeOfDayFromServerClock()
|
||||
{
|
||||
int serverGmt = GetServerGMTTime();
|
||||
ApplySunMoonPhaseFromServerGmtUnix(serverGmt);
|
||||
}
|
||||
|
||||
static void ApplySunMoonPhaseFromServerGmtUnix(int serverGmtUnixSeconds)
|
||||
{
|
||||
long shiftedUnix = (long)serverGmtUnixSeconds - (long)m_iTimeZoneBias * 60L;
|
||||
if (shiftedUnix < 0L)
|
||||
shiftedUnix = 0L;
|
||||
var serverLocalUtc = DateTimeOffset.FromUnixTimeSeconds(shiftedUnix).UtcDateTime;
|
||||
int nTimeInDay = serverLocalUtc.Hour * 3600 + serverLocalUtc.Minute * 60 + serverLocalUtc.Second;
|
||||
float phase = nTimeInDay / (4f * 3600f);
|
||||
SetTimeOfTheDay(phase);
|
||||
BMLogger.Log($"[Cuong] SyncSunMoon server-local {serverLocalUtc.Hour:D2}:{serverLocalUtc.Minute:D2}:{serverLocalUtc.Second:D2}, phase={phase}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将昼夜相位写入 SunMoon(与 PC GetWorld()->GetSunMoon()->SetTimeOfTheDay 用法一致) // Push day/night phase to SunMoon (same role as PC)
|
||||
/// </summary>
|
||||
public static void SetTimeOfTheDay(float vTime)
|
||||
{
|
||||
var sunMoon = CECSunMoon.Instance;
|
||||
if (sunMoon == null)
|
||||
{
|
||||
BMLogger.LogWarning("[Cuong] EC_Game.SetTimeOfTheDay: CECSunMoon.Instance is null.");
|
||||
return;
|
||||
}
|
||||
sunMoon.SetTimeOfTheDay(vTime);
|
||||
BMLogger.Log($"[Cuong] EC_Game.SetTimeOfTheDay vTime(in)={vTime}, m_vTimeOfTheDay={sunMoon.m_vTimeOfTheDay}");
|
||||
}
|
||||
|
||||
// 设置时间误差 // Set time error
|
||||
public static void SetServerTime(int iSevTime, int iTimeZoneBias)
|
||||
{
|
||||
Debug.Log($"SetServerTime, iSevTime = {iSevTime}, iTimeZoneBias = {iTimeZoneBias}");
|
||||
int iOldTimeError = m_iTimeError;
|
||||
BMLogger.Log($"[Cuong] SetServerTime iSevTime={iSevTime}, iTimeZoneBias={iTimeZoneBias}");
|
||||
int nowUnix = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
m_iTimeError = iSevTime - nowUnix; // 记录与本机的时间差 // store delta with local
|
||||
m_iTimeZoneBias = iTimeZoneBias; // 记录服务器时区偏移 // store server timezone bias
|
||||
|
||||
// 计算服务器本地时间并设置昼夜 // Compute server local time and set time of day
|
||||
var serverLocal = DateTimeOffset.FromUnixTimeSeconds((long)iSevTime + iTimeZoneBias);
|
||||
int nTimeInDay = serverLocal.Hour * 3600 + serverLocal.Minute * 60 + serverLocal.Second;
|
||||
// GetGameRun()->GetWorld()->GetSunMoon()->SetTimeOfTheDay(nTimeInDay / (4.0f * 3600.0f));
|
||||
// 设置昼夜时间(原逻辑保留为注释) // Set time of day (original call left commented)
|
||||
ApplySunMoonPhaseFromServerGmtUnix(iSevTime);
|
||||
|
||||
// 防沉迷时长修正 // Anti-wallow playtime adjust
|
||||
// S2C::player_wallow_info wallowinfo = GetGameRun()->GetWallowInfo();
|
||||
@@ -43,7 +76,7 @@ namespace BrewMonster.Network
|
||||
m_AbsTimeStart = iSevTime;
|
||||
m_AbsTickStart = (uint)(Time.realtimeSinceStartup * 1000.0f);
|
||||
m_bServerTimeInited = true;
|
||||
Debug.Log($"timeGetTime(), TickStart = {m_AbsTickStart}");
|
||||
BMLogger.Log($"[Cuong] SetServerTime TickStart (ms) = {m_AbsTickStart}");
|
||||
}
|
||||
|
||||
public static int GetServerAbsTime()
|
||||
|
||||
@@ -92,4 +92,4 @@ namespace CSNetwork
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1290,8 +1290,15 @@ namespace CSNetwork
|
||||
break;
|
||||
case CommandID.SERVER_TIME:
|
||||
{
|
||||
// NetworkManager receives on a background Task (ProcessReceivedData); never touch Unity / EC_ManMessage queue here.
|
||||
cmd_server_time pcmd_server_time = GPDataTypeHelper.FromBytes<cmd_server_time>(pDataBuf);
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_SERVERTIME, -1, 0, pcmd_server_time.time, pcmd_server_time.timebias);
|
||||
int st = pcmd_server_time.time;
|
||||
int sb = pcmd_server_time.timebias;
|
||||
PostToUnityContext(() =>
|
||||
{
|
||||
EC_Game.SetServerTime(st, sb);
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_SERVERTIME, -1, 0, st, sb);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case CommandID.SCENE_SERVICE_NPC_LIST:
|
||||
|
||||
@@ -391,6 +391,9 @@ namespace BrewMonster.UI
|
||||
|
||||
private async void OnEnterWorldComplete()
|
||||
{
|
||||
// PC CECGameRun::CreateWorld: SunMoon phase from GetServerLocalTime after map load
|
||||
EC_Game.SyncSunMoonTimeOfDayFromServerClock();
|
||||
|
||||
// initialize the mini map
|
||||
CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan();
|
||||
if (pGameUI != null)
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace PerfectWorld.UI.MiniMap
|
||||
this.mapID = mapID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[SerializeField] private Vector3 _debugHostPlayerPos;
|
||||
[SerializeField] private RectTransform _hostPlayerIcon;
|
||||
@@ -62,6 +62,30 @@ namespace PerfectWorld.UI.MiniMap
|
||||
|
||||
private int m_nMode; // TODO: currently, there is only get logic, not set logic
|
||||
|
||||
// PC DlgMiniMap.cpp: GetStringFromTable(604), GetStringFromTable(1330 + nTimeIndex), FixFrame(nTimeItem)
|
||||
private const int StrIdSystemTimeFormat = 604;
|
||||
private const int StrIdShichenBase = 1330;
|
||||
|
||||
private enum MinimapTimeSprite
|
||||
{
|
||||
TIME_DAY = 0,
|
||||
TIME_MORNING,
|
||||
TIME_DUSK,
|
||||
TIME_NIGHT,
|
||||
}
|
||||
|
||||
/// <summary>十二时辰名(表缺失时回退,与 PC 1330+i 顺序一致:子丑寅…) // Fallback 12 double-hours if string table missing (same order as PC 1330+i)</summary>
|
||||
static readonly string[] s_FallbackShichenNames =
|
||||
{
|
||||
"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥", // Zi, Chou, ...
|
||||
};
|
||||
|
||||
[Header("Set data show time in mini map")]
|
||||
[SerializeField] private TMP_Text _txtSystemTime;
|
||||
[SerializeField] private Image _imgSystemTime;
|
||||
[Tooltip("PC order: TIME_DAY, TIME_MORNING, TIME_DUSK, TIME_NIGHT (DlgMiniMap enum)")]
|
||||
[SerializeField] private Sprite[] _systemTimeSprites;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// LoadAllMiniMapTextures();
|
||||
@@ -72,6 +96,7 @@ namespace PerfectWorld.UI.MiniMap
|
||||
void Update()
|
||||
{
|
||||
UpdateMiniMap();
|
||||
UpdateSystemClockFromPcMiniMapLogic();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -97,14 +122,58 @@ namespace PerfectWorld.UI.MiniMap
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Host Player instance.
|
||||
/// PC DlgMiniMap.cpp Render: nTimeIndex, Format(604,...), int(v*24), FixFrame(nTimeItem).
|
||||
/// </summary>
|
||||
void UpdateSystemClockFromPcMiniMapLogic()
|
||||
{
|
||||
var sun = CECSunMoon.Instance;
|
||||
if (sun == null)
|
||||
return;
|
||||
|
||||
var inGame = EC_Game.GetGameRun()?.GetUIManager()?.GetInGameUIMan();
|
||||
|
||||
float fDNFactor = sun.GetDNFactor();
|
||||
float fDNFactorDest = sun.GetDNFactorDest();
|
||||
float v = sun.GetTimeOfTheDay();
|
||||
int nTimeIndex = (int)(12.0f * v + 0.5f) % 12;
|
||||
|
||||
MinimapTimeSprite nTimeItem;
|
||||
if (fDNFactor == 0.0f)
|
||||
nTimeItem = MinimapTimeSprite.TIME_DAY;
|
||||
else if (fDNFactor == 1.0f)
|
||||
nTimeItem = MinimapTimeSprite.TIME_NIGHT;
|
||||
else
|
||||
nTimeItem = fDNFactorDest == 1.0f ? MinimapTimeSprite.TIME_DUSK : MinimapTimeSprite.TIME_MORNING;
|
||||
|
||||
if (_imgSystemTime != null && _systemTimeSprites != null &&
|
||||
_systemTimeSprites.Length > (int)nTimeItem && _systemTimeSprites[(int)nTimeItem] != null)
|
||||
_imgSystemTime.sprite = _systemTimeSprites[(int)nTimeItem];
|
||||
|
||||
string shichen = inGame != null ? GetStringFromTable(StrIdShichenBase + nTimeIndex) : null;
|
||||
if (string.IsNullOrEmpty(shichen))
|
||||
shichen = s_FallbackShichenNames[nTimeIndex];
|
||||
|
||||
int hour = (int)(v * 24.0f);
|
||||
string fmt = inGame != null ? GetStringFromTable(StrIdSystemTimeFormat) : null;
|
||||
if (string.IsNullOrEmpty(fmt))
|
||||
fmt = "{0}({1}时)"; // 与常见 PC 客户端格式一致 // Typical PC client style: name (hour)
|
||||
|
||||
string strText = FormatPrintf(fmt, shichen, hour);
|
||||
if (_txtSystemTime != null)
|
||||
_txtSystemTime.text = strText;
|
||||
|
||||
BMLogger.Log($"[Cuong] {strText}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Host Player instance.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private CECHostPlayer GetHostPlayer()
|
||||
{
|
||||
return CECGameRun.Instance.GetHostPlayer();
|
||||
}
|
||||
|
||||
|
||||
// change radar mode
|
||||
public int GetMode() { return m_nMode; }
|
||||
|
||||
@@ -185,8 +254,8 @@ namespace PerfectWorld.UI.MiniMap
|
||||
{
|
||||
Vector2 hostPlayerPos = new Vector2(_debugHostPlayerPos.x / 2, _debugHostPlayerPos.z / 2);
|
||||
_transformMiniMapParent.anchoredPosition = -hostPlayerPos;
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,10 @@ namespace BrewMonster.Scripts
|
||||
{
|
||||
private const float TIME_SCALE = 6f;
|
||||
private const float NIGHT_DAY_START = (3.0f / 24.0f);
|
||||
private const float NIGHT_SUN_RISE_MIN = (4.0f / 24.0f);
|
||||
private const float NIGHT_DAY_END = (7.0f / 24.0f);
|
||||
private const float DAY_NIGHT_START = (18.0f / 24.0f);
|
||||
private const float DAY_SUN_SET_MAX = (19.5f / 24.0f);
|
||||
private const float DAY_NIGHT_END = (21.0f / 24.0f);
|
||||
|
||||
|
||||
public double m_vTimeOfTheDay; // time of the day 0.0f means 00:00, 1.0f means 24:00
|
||||
public float m_fDNFactor; // day or night factor
|
||||
public float m_fDNFactorDest; // day or night factor dest
|
||||
@@ -23,13 +21,69 @@ namespace BrewMonster.Scripts
|
||||
|
||||
// keep this alive when scene is loaded
|
||||
DontDestroyOnLoad(gameObject);
|
||||
RefreshDayNightFactorsFromPhase();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
m_vTimeOfTheDay += Time.deltaTime / 3600.0 / 24.0 * TIME_SCALE;
|
||||
while( m_vTimeOfTheDay > 1.0 )
|
||||
m_vTimeOfTheDay -= 1.0;
|
||||
while (m_vTimeOfTheDay > 1.0)
|
||||
m_vTimeOfTheDay -= 1.0;
|
||||
RefreshDayNightFactorsFromPhase();
|
||||
}
|
||||
|
||||
public float GetTimeOfTheDay() => (float)m_vTimeOfTheDay;
|
||||
public float GetDNFactor() => m_fDNFactor;
|
||||
public float GetDNFactorDest() => m_fDNFactorDest;
|
||||
|
||||
/// <summary>
|
||||
/// 设置一天中的时刻(与 PC 版 CECSunMoon::SetTimeOfTheDay 对齐) // Set time-of-day phase [0,1), aligned with PC CECSunMoon::SetTimeOfTheDay
|
||||
/// </summary>
|
||||
public bool SetTimeOfTheDay(float vTime)
|
||||
{
|
||||
while (vTime < 0f)
|
||||
vTime += 1f;
|
||||
while (vTime > 1f)
|
||||
vTime -= 1f;
|
||||
m_vTimeOfTheDay = vTime;
|
||||
RefreshDayNightFactorsFromPhase();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PC EC_SunMoon::UpdateWithTime 中昼夜因子段(供 minimap 与场景一致) // DN factor block from PC EC_SunMoon::UpdateWithTime
|
||||
/// </summary>
|
||||
void RefreshDayNightFactorsFromPhase()
|
||||
{
|
||||
float v = (float)m_vTimeOfTheDay;
|
||||
|
||||
// update day night factor — same branches as PC EC_SunMoon.cpp UpdateWithTime (lines 894–918)
|
||||
if (v < NIGHT_DAY_START)
|
||||
{
|
||||
m_fDNFactor = 1.0f;
|
||||
m_fDNFactorDest = 1.0f;
|
||||
}
|
||||
else if (v < NIGHT_DAY_END)
|
||||
{
|
||||
m_fDNFactor = 1.0f - (v - NIGHT_DAY_START) / (NIGHT_DAY_END - NIGHT_DAY_START);
|
||||
m_fDNFactorDest = 0.0f;
|
||||
}
|
||||
else if (m_vTimeOfTheDay < DAY_NIGHT_START)
|
||||
{
|
||||
// PC 使用 m_vTimeOfTheDay 与 DAY_NIGHT_START 比较 // PC compares m_vTimeOfTheDay to DAY_NIGHT_START (see EC_SunMoon.cpp)
|
||||
m_fDNFactor = 0.0f;
|
||||
m_fDNFactorDest = 0.0f;
|
||||
}
|
||||
else if (v < DAY_NIGHT_END)
|
||||
{
|
||||
m_fDNFactor = (v - DAY_NIGHT_START) / (DAY_NIGHT_END - DAY_NIGHT_START);
|
||||
m_fDNFactorDest = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fDNFactor = 1.0f;
|
||||
m_fDNFactorDest = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using BrewMonster;
|
||||
using BrewMonster.Network;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
@@ -7,7 +8,7 @@ using CSNetwork.GPDataType;
|
||||
partial class CECGameRun : IMsgHandler
|
||||
{
|
||||
private readonly Dictionary<int, int> m_CommonDataTab = new Dictionary<int, int>();
|
||||
|
||||
|
||||
public int GetCommonData(int key)
|
||||
{
|
||||
// Lookup a common data value by key
|
||||
@@ -17,9 +18,9 @@ partial class CECGameRun : IMsgHandler
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private CECCounter l_QueryServerTime = new CECCounter(); // ��ѯ��������ǰʱ��
|
||||
|
||||
|
||||
public int HandlerId => -1;
|
||||
public bool ProcessMessage(ECMSG Msg)
|
||||
{
|
||||
@@ -30,9 +31,9 @@ partial class CECGameRun : IMsgHandler
|
||||
EC_Game.SetServerTime((int)Msg.dwParam1, (int)Msg.dwParam2);
|
||||
l_QueryServerTime.Reset();
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user