Files
test/Assets/Scripts/CECGameRun.cs
T

754 lines
26 KiB
C#
Raw 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.
using BrewMonster;
using BrewMonster.Managers;
using BrewMonster.Network;
using BrewMonster.Scripts;
using BrewMonster.Scripts.Managers;
using BrewMonster.Scripts.World;
using BrewMonster.UI;
using CSNetwork;
using CSNetwork.GPDataType;
using CSNetwork.Protocols.RPCData;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using Unity.Cinemachine;
using UnityEngine;
public partial class CECGameRun
{
private static CECGameRun instance;
private GameObject _playerPrefab;
private GameObject _monsterPrefab;//CECMonster
private GameObject _npcServerPrefab;//CECNPCServer
private GameObject _petServerPrefab;//CECPet
private GameObject _petMountServerPrefab;//CECPetRider
private CECTeamMan m_pTeamMan; // Team manager
private CECShortcutSet m_pNormalSCS; // Normal shortcut set
private CECShortcutSet m_pTeamSCS; // Team shortcut set
private CECShortcutSet m_pTradeSCS; // Trade shortcut set
private CECShortcutSet m_pPoseSCS; // Pose shortcut set
private CECShortcutSet m_pFactionSCS; // Faction shortcut set
// private GameRunConfig _gameRunConfig;
//[SerializeField] private Transform ground;
CECHostPlayer hostPlayer;
private CECWorld m_pWorld;
int m_iGameState; // Game state
protected CECUIManager m_pUIManager; // UI manager
public CECWorld GetWorld()
{
if(m_pWorld == null)
{
m_pWorld = CECWorld.Instance;
}
return m_pWorld;
}
public CECTeamMan GetTeamMan() { return m_pTeamMan; }
// Get shortcut sets
public CECShortcutSet GetGenCmdShortcuts() { return m_pNormalSCS; }
public CECShortcutSet GetTeamCmdShortcuts() { return m_pTeamSCS; }
public CECShortcutSet GetTradeCmdShortcuts() { return m_pTradeSCS; }
public CECShortcutSet GetPoseCmdShortcuts() { return m_pPoseSCS; }
public CECShortcutSet GetFactionCmdShortcuts() { return m_pFactionSCS; }
private static Dictionary<int, CECInstance> m_InstTab = new Dictionary<int, CECInstance>();
static RoleInfo l_SelRoleInfo; // Selected character's role info.
private int m_iDExpEndTime = 0;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void AfterSceneLoad()
{
l_SelRoleInfo = null;
m_InstTab = new Dictionary<int, CECInstance>();
}
public void Init()
{
#if !UNITY_EDITOR
Debug.unityLogger.logEnabled = false;
QualitySettings.vSyncCount = 0;
Application.targetFrameRate = 60;
#endif
instance = this;
// _gameRunConfig = Resources.Load<GameRunConfig>("GameRunConfig");
// _playerPrefab = _gameRunConfig.PlayerPrefab;
// _monsterPrefab = _gameRunConfig.MonsterPrefab;
// _npcServerPrefab = _gameRunConfig.NpcServerPrefab;
LoadPrefabs();
m_pTeamMan = new CECTeamMan();
// LoadPrefabs();
EC_ManMessage.RegisterHandler(this);
// Load instance information
//if (!LoadInstanceInfo("Configs\\instance.txt"))
//{
// glb_ErrorOutput(ECERR_FAILEDTOCALL, "CECGameRun::Init", __LINE__);
// return false;
//}
if (!m_InstTab.ContainsKey(161))
m_InstTab.Add(161, new CECInstance());
AddressableManager.Instance.OnDispose += Dispose;
m_pWorld = CECWorld.Instance;
StartGame(0, Vector3.zero);
}
private static void Dispose()
{
instance = null;
}
private void LoadPrefabs()
{
BMLogger.LogError("CECGameRun::LoadPrefabs, Loading prefabs from Resources. Consider using Addressables for better performance and memory management.");
_playerPrefab = Resources.Load<GameObject>(AddressResourceConfig.PlayerPrefab);
_monsterPrefab = Resources.Load<GameObject>(AddressResourceConfig.MonsterPrefab);
_npcServerPrefab = Resources.Load<GameObject>(AddressResourceConfig.NpcServerPrefab);
_petServerPrefab = Resources.Load<GameObject>(AddressResourceConfig.PetServerPrefab);
_petMountServerPrefab = Resources.Load<GameObject>(AddressResourceConfig.PetMountServerPrefab);
#if UNITY_EDITOR
if (_playerPrefab == null)
{
BMLogger.LogError("CECGameRun::LoadPrefabs, Failed to load player prefab.");
}
if (_monsterPrefab == null)
{
BMLogger.LogError("CECGameRun::LoadPrefabs, Failed to load _monsterPrefab prefab.");
}
if (_npcServerPrefab == null)
{
BMLogger.LogError("CECGameRun::LoadPrefabs, Failed to load _npcServerPrefab prefab.");
}
#endif
}
private bool init;
public bool StartGame(int idInst, Vector3 vHostPos)
{
if (init)
{
return false;
}
// Create shortcuts
if (!CreateShortcuts())
{
return false;
}
if (!JumpToInstance(idInst, vHostPos))
{
BMLogger.LogError("CECGameRun::StartGame, Failed to create game world.");
return false;
}
init = true;
return true;
}
private bool JumpToInstance(int idInst, Vector3 vHostPos, int iParallelWorldID = 0)
{
return true;
}
public static CECGameRun Instance
{
get
{
if (instance == null)
{
instance = new CECGameRun();
}
return instance;
}
}
public CECHostPlayer GetHostPlayer()
{
return hostPlayer;
}
public void InitCharacter(cmd_self_info_1 info)
{
if (_playerPrefab == null)
{
BMLogger.LogError("null _playerPrefab");
return;
}
// 同步世界/地图ID给任务系统(GetPos 返回的 worldId
// English: Sync map ID to task system (worldId returned by GetPos).
// We don't receive mapId in cmd_self_info_1, so use selected RoleInfo.worldtag as current map id.
var roleInfo = UnityGameSession.Instance != null ? UnityGameSession.Instance.GetRoleInfo() : null;
if (roleInfo != null)
{
int idInst = roleInfo.worldtag;
if (idInst > 0)
{
// Ensure instance exists in table (minimal stub instance is fine for now)
if (!m_InstTab.ContainsKey(idInst))
m_InstTab.Add(idInst, new CECInstance());
// Update global world instance id used by task checks
CECWorld.Instance?.SetInstanceID(idInst);
}
}
CECPlayer.InitStaticRes();
hostPlayer = ObjectSpawner.Instance.InstantiateObject(_playerPrefab, setThisAsParent: true).AddComponent<CECHostPlayer>();
hostPlayer.InitCharacter(info);
}
public CECMonster GetMonster()
{
return ObjectSpawner.Instance.InstantiateObject(_monsterPrefab, setThisAsParent: true)
.GetComponent<CECMonster>();
}
public RoleInfo GetSelectedRoleInfo()
{
return l_SelRoleInfo;
}
public void SetSelectedRoleInfo(RoleInfo Info)
{
l_SelRoleInfo = Info;
}
public CECNPCServer GetNPCServer()
{
return ObjectSpawner.Instance.InstantiateObject(_npcServerPrefab, setThisAsParent: true).GetComponent<CECNPCServer>();
}
public async void ShowVfx(string assetAddress, Vector3 position, Transform parent, float timeLife)
{
var prefab = await AddressableManager.Instance.LoadPrefabAsync(assetAddress);
if (prefab == null)
{
BMLogger.LogError("Failed to load prefab: " + assetAddress);
return;
}
BMLogger.Log($"[GFX Spawn] ShowVfx - Asset: {assetAddress}, Prefab Name: {prefab.name}, Position: {position}, Parent: {(parent != null ? parent.name : "null")}, LifeTime: {timeLife}s");
if (parent == null)
{
var obj = ObjectSpawner.Instance.InstantiateObject(prefab, setThisAsParent: true);
obj.transform.position = position;
BMLogger.Log($"[GFX Spawn] ShowVfx - Instantiated object (no parent): {obj.name}");
DestroyTestVfx(obj, timeLife);
}
else
{
var obj = ObjectSpawner.Instance.InstantiateObject(prefab, parent, false);
obj.transform.position = position;
BMLogger.Log($"[GFX Spawn] ShowVfx - Instantiated object (with parent): {obj.name}");
DestroyTestVfx(obj, timeLife);
}
}
public void DestroyTestVfx(GameObject go, float delayTime)
{
ObjectSpawner.Instance.DestroyGameObject(go, delayTime);
}
public GameObject InitCharacter(info_player_1 info)
{
if (_playerPrefab == null)
{
Debug.LogError("null prefab");
return null;
}
GameObject character = ObjectSpawner.Instance.InstantiateObject(_playerPrefab, setThisAsParent: true);
return character.gameObject;
}
//private void Update()
//{
// if (hostPlayer == null || hostPlayer.transform == null)
// return;
// bool rightClick = Input.GetMouseButton(1);
// if (rightClick)
// {
// // Bật khả năng xoay khi giữ chuột phải
// freeLookCam.m_XAxis.m_MaxSpeed = rotateSpeedX;
// freeLookCam.m_YAxis.m_MaxSpeed = rotateSpeedY;
// // Ghi giá trị chuột thủ công (nếu muốn override Input System cũ)
// float mouseX = Input.GetAxis("Mouse X");
// float mouseY = Input.GetAxis("Mouse Y");
// // Xoay camera theo hướng chuột
// freeLookCam.m_XAxis.Value += mouseX * Time.deltaTime * rotateSpeedX;
// freeLookCam.m_YAxis.Value -= mouseY * Time.deltaTime * (rotateSpeedY / 100f);
// }
// else
// {
// // Khi thả chuột thì khoá xoay
// freeLookCam.m_XAxis.m_MaxSpeed = 0;
// freeLookCam.m_YAxis.m_MaxSpeed = 0;
// }
//}
/// <summary>
/// Load necessary user configs (UI, shortcut, accelerate keys) from server
/// 从服务器加载必要的用户配置(UI、快捷键、加速键)
/// </summary>
/// <param name="pDataBuf">Config data buffer / 配置数据缓冲区</param>
/// <param name="iDataSize">Data size / 数据大小</param>
/// <returns>True if loaded successfully / 加载成功返回true</returns>
public bool LoadConfigsFromServer(byte[] pDataBuf, int iDataSize)
{
const uint USERCFG_VERSION = 3;
if (pDataBuf == null || iDataSize == 0)
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, configs data is empty");
return false;
}
int offset = 0;
// Read version / 读取版本号
uint dwVer = System.BitConverter.ToUInt32(pDataBuf, offset);
offset += sizeof(uint);
if (dwVer > USERCFG_VERSION)
{
Debug.LogError($"CECGameRun::LoadConfigsFromServer, version {dwVer} > {USERCFG_VERSION}");
return false;
}
byte[] pUncompBuf = null;
uint dwRealLen = (uint)(iDataSize - sizeof(uint));
if (dwRealLen < 0)
{
dwRealLen = 0;
}
byte[] pData = pDataBuf;
if (dwVer >= 3)
{
// Uncompress config data / 解压配置数据
dwRealLen = 4096;
pUncompBuf = new byte[dwRealLen];
// Extract compressed data / 提取压缩数据
byte[] compressedData = new byte[iDataSize - sizeof(uint)];
System.Array.Copy(pDataBuf, offset, compressedData, 0, compressedData.Length);
// TODO: Implement AFilePackage::Uncompress equivalent
int iRes = AFilePackage.Uncompress(compressedData, compressedData.Length, pUncompBuf, ref dwRealLen);
if (iRes != 0)
{
// 解压失败,过程出错 / Decompression failed, process error
BMLogger.LogError($"CECGameRun::LoadConfigsFromServer, Failed to uncompress configs data ({iRes}:{iDataSize})");
return false;
}
pData = pUncompBuf;
}
try
{
// Create data reader / 创建数据读取器
CECDataReader dr = new CECDataReader(pData, (int)dwRealLen);
// Load host configs / 加载主机配置
CECHostPlayer pHost = GetHostPlayer();
if (pHost != null)
{
int iSize = dr.ReadInt();
byte[] hostConfigData = dr.ReadData(iSize);
if (!pHost.LoadConfigData(hostConfigData))
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to load host configs");
return false;
}
}
//TODO: flow in update fix later
/* Task.Run(() =>
{
GameSession.Context.Post(_ =>
{
if (m_pUIManager == null)
{
m_pUIManager = CECUIManager.Instance;
}
m_pUIManager.GetCDlgQuickBar().UpdateShortcuts();
}, null);
});*/
// TODO: Uncomment when UI manager is available
// Load UI configs / 加载UI配置
CECGameUIMan pGameUI = m_pUIManager.GetInGameUIMan();
if (pGameUI != null)
{
int iSize = dr.ReadInt();
byte[] uiConfigData = dr.ReadData(iSize);
/*if (!pGameUI.SetUserLayout(uiConfigData, iSize))
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to set user layout");
return false;
}*/
}
// Load user settings / 加载用户设置
if (dwVer >= 2)
{
// TODO: Uncomment when game configs are available
int iSize = dr.ReadInt();
byte[] settingsData = dr.ReadData(iSize);
if (!EC_Game.GetConfigs().LoadUserConfigData(settingsData, iSize))
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to load user config data");
return false;
}
}
}
catch (System.Exception e)
{
BMLogger.LogError($"CECGameRun::LoadConfigsFromServer, data read error: {e.Message}");
return false;
}
return true;
}
public int GetCurStageIndex()
{
// CECGameRun.unique_data* data = GetUniqueData(0);
// if (data)
// {
// if(data->type ==1)
// {
// return data->GetValueAsInt();
// }
// }
return -1;
}
// Create shortcuts
public bool CreateShortcuts()
{
// // Normal command shortcut set
m_pNormalSCS = new CECShortcutSet();
m_pNormalSCS.Init(8);
CECSCCommand pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_SITDOWN);
m_pNormalSCS.SetShortcut(0, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_WALKRUN);
m_pNormalSCS.SetShortcut(1, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_NORMALATTACK);
m_pNormalSCS.SetShortcut(2, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_FINDTARGET);
m_pNormalSCS.SetShortcut(3, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_ASSISTATTACK);
m_pNormalSCS.SetShortcut(3, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_FLY);
m_pNormalSCS.SetShortcut(4, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_PICKUP);
m_pNormalSCS.SetShortcut(5, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_GATHER);
m_pNormalSCS.SetShortcut(6, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_RUSHFLY);
m_pNormalSCS.SetShortcut(6, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_BINDBUDDY);
m_pNormalSCS.SetShortcut(7, pSC);
// Team command shortcut set
m_pTeamSCS = new CECShortcutSet();
m_pTeamSCS.Init(2);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_INVITETOTEAM);
m_pTeamSCS.SetShortcut(0, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_LEAVETEAM);
m_pTeamSCS.SetShortcut(1, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_KICKTEAMMEM);
m_pTeamSCS.SetShortcut(2, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_FINDTEAM);
m_pTeamSCS.SetShortcut(2, pSC);
// Trade command shortcut set
m_pTradeSCS = new CECShortcutSet();
m_pTradeSCS.Init(2);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_STARTTRADE);
m_pTradeSCS.SetShortcut(0, pSC);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_SELLBOOTH);
m_pTradeSCS.SetShortcut(1, pSC);
// Pose command shortcut set
m_pPoseSCS = new CECShortcutSet();
m_pPoseSCS.Init((int)RoleExpression.NUM_ROLEEXP);
for (int i = 0; i < (int)RoleExpression.NUM_ROLEEXP; i++)
{
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_PLAYPOSE);
pSC.SetParam((uint)i);
m_pPoseSCS.SetShortcut(i, pSC);
}
// Faction command shortcut set
m_pFactionSCS = new CECShortcutSet();
m_pFactionSCS.Init(1);
pSC = new CECSCCommand((int)CECSCCommand.CommandID.CMD_INVITETOFACTION);
m_pFactionSCS.SetShortcut(0, pSC);
return true;
}
// Get UI manager
public CECUIManager GetUIManager()
{
if (m_pUIManager == null)
{
m_pUIManager = CECUIManager.Instance;
}
return m_pUIManager;
}
// Get instance by ID
public CECInstance GetInstance(int id)
{
if (m_InstTab.TryGetValue(id, out CECInstance value))
{
return value;
}
return null;
}
public string GetProfName(int i)
{
string szRet = null;
if (i >= 0 && i < (int)Profession.NUM_PROFESSION)
{
int[] s_ProfDesc = {
(int)FixedMsg.FIXMSG_PROF_WARRIOR,
(int)FixedMsg.FIXMSG_PROF_MAGE,
(int)FixedMsg.FIXMSG_PROF_MONK,
(int)FixedMsg.FIXMSG_PROF_HAG,
(int)FixedMsg.FIXMSG_PROF_ORC,
(int)FixedMsg.FIXMSG_PROF_GHOST,
(int)FixedMsg.FIXMSG_PROF_ARCHOR,
(int)FixedMsg.FIXMSG_PROF_ANGEL,
(int)FixedMsg.FIXMSG_PROF_JIANLING,
(int)FixedMsg.FIXMSG_PROF_MEILING,
(int)FixedMsg.FIXMSG_PROF_YEYING,
(int)FixedMsg.FIXMSG_PROF_YUEXIAN,
};
CECStringTab pStrTab = EC_Game.GetFixedMsgs();
szRet = pStrTab.GetWideString(s_ProfDesc[i]);
}
else
{
//BMLogger.LogError("CECGameRun::GetProfName, i: {0} is not exist", i);
return null;
}
return szRet;
}
public CECPet GetPet()
{
return ObjectSpawner.Instance.InstantiateObject(_petServerPrefab, setThisAsParent: true)
.GetComponent<CECPet>();
}
public GameObject GetPetMount()
{
return ObjectSpawner.Instance.InstantiateObject(_petMountServerPrefab, setThisAsParent: true);
}
/// <summary>
/// Add a fixed message to chat system with optional formatting parameters
/// 添加固定消息到聊天系统,支持可选的格式化参数
/// </summary>
/// <param name="iMsg">Fixed message ID / 固定消息ID</param>
/// <param name="args">Optional formatting arguments / 可选的格式化参数</param>
public void AddFixedMessage(int iMsg, params object[] args)
{
CECStringTab pStrTab = EC_Game.GetFixedMsgs();
if (pStrTab == null)
{
Debug.LogWarning("[AddFixedMessage] Failed to get fixed message table");
return;
}
string szFixMsg = pStrTab.GetWideString(iMsg);
if (string.IsNullOrEmpty(szFixMsg))
{
Debug.LogWarning($"[AddFixedMessage] Fixed message {iMsg} not found");
return;
}
// Format the message with provided arguments
string szFormattedMsg;
try
{
if (args != null && args.Length > 0)
{
szFormattedMsg = string.Format(szFixMsg, args);
}
else
{
szFormattedMsg = szFixMsg;
}
}
catch (System.FormatException ex)
{
Debug.LogError($"[AddFixedMessage] Format error for message {iMsg}: {ex.Message}");
szFormattedMsg = szFixMsg; // Use unformatted message as fallback
}
// Try to add to in-game UI chat
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan();
if (pGameUI != null)
{
//pGameUI.AddChatMessage(szFormattedMsg, (int)GP_CHAT.GP_CHAT_SYSTEM);
}
else
{
// Fallback to debug output if UI is not available
Debug.Log($"[System] {szFormattedMsg}");
}
}
/// <summary>
/// Add a fixed message to specific chat channel with optional formatting
/// 添加固定消息到指定聊天频道,支持可选的格式化
/// </summary>
/// <param name="iMsg">Fixed message ID / 固定消息ID</param>
/// <param name="cChannel">Chat channel ID / 聊天频道ID</param>
/// <param name="args">Optional formatting arguments / 可选的格式化参数</param>
public void AddFixedChannelMsg(int iMsg, int cChannel, params object[] args)
{
CECStringTab pStrTab = EC_Game.GetFixedMsgs();
if (pStrTab == null)
{
Debug.LogWarning("[AddFixedChannelMsg] Failed to get fixed message table");
return;
}
string szFixMsg = pStrTab.GetWideString(iMsg);
if (string.IsNullOrEmpty(szFixMsg))
{
Debug.LogWarning($"[AddFixedChannelMsg] Fixed message {iMsg} not found");
return;
}
// Format the message with provided arguments
string szFormattedMsg;
try
{
if (args != null && args.Length > 0)
{
szFormattedMsg = string.Format(szFixMsg, args);
}
else
{
szFormattedMsg = szFixMsg;
}
}
catch (System.FormatException ex)
{
Debug.LogError($"[AddFixedChannelMsg] Format error for message {iMsg}: {ex.Message}");
szFormattedMsg = szFixMsg; // Use unformatted message as fallback
}
// Try to add to in-game UI chat with specific channel
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan();
if (pGameUI != null)
{
//pGameUI.AddChatMessage(szFormattedMsg, cChannel);
}
else
{
// Fallback to debug output if UI is not available
Debug.Log($"[Channel {cChannel}] {szFormattedMsg}");
}
}
/// <summary>
/// Add a chat message with full parameters (matching C++ signature)
/// 添加聊天消息(完整参数版本,匹配C++签名)
/// </summary>
/// <param name="pszMsg">Message text / 消息文本</param>
/// <param name="cChannel">Chat channel / 聊天频道</param>
/// <param name="idPlayer">Player ID (default -1) / 玩家ID</param>
/// <param name="szName">Player name (optional) / 玩家名称</param>
/// <param name="byFlag">Message flag (default 0) / 消息标志</param>
/// <param name="cEmotion">Emotion ID (default 0) / 表情ID</param>
/// <param name="pItem">Related item (optional) / 相关物品</param>
/// <param name="pszMsgOrigion">Original message (optional) / 原始消息</param>
public void AddChatMessage(string pszMsg, int cChannel, int idPlayer = -1,
string szName = null, byte byFlag = 0, int cEmotion = 0,
EC_IvtrItem pItem = null, string pszMsgOrigion = null)
{
if (string.IsNullOrEmpty(pszMsg))
return;
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan();
if (pGameUI != null)
{
// Call UI manager's AddChatMessage with full parameters
//pGameUI.AddChatMessage(pszMsg, cChannel, idPlayer, szName, byFlag, cEmotion, pItem, pszMsgOrigion);
}
else
{
// Fallback to debug output if UI is not available
Debug.Log($"[Channel {cChannel}] {pszMsg}");
// Note: In C++ original, pItem is deleted here if UI is not available
// In C#, we don't need explicit deletion due to garbage collection
}
}
/// <summary>
/// Get remaining double experience time in seconds
/// 获取剩余双倍经验时间(秒)
/// </summary>
public int GetRemainDblExpTime()
{
int iRemainTime = m_iDExpEndTime - GetServerAbsTime();
if (iRemainTime < 0) iRemainTime = 0;
return iRemainTime;
}
/// <summary>
/// Get server absolute time
/// 获取服务器绝对时间
/// </summary>
public int GetServerAbsTime()
{
// TODO: Implement server time synchronization
// This should return the synchronized server timestamp
return (int)(System.DateTime.UtcNow.Subtract(new System.DateTime(1970, 1, 1))).TotalSeconds;
}
/// <summary>
/// Set double experience end time
/// 设置双倍经验结束时间
/// </summary>
public void SetDExpEndTime(int endTime)
{
m_iDExpEndTime = endTime;
}
public int GetGameState() { return m_iGameState; }
public void SaveConfigsToServer()
{
}
}
public enum GameState
{
GS_NONE = 0, // None
GS_LOGIN, // Login in state
GS_GAME, // In game
};