Files
test/Assets/Scripts/EC_GameRun.cs
T
vuong dinh hoang 28092ce6c8 log in build
2026-05-31 15:45:52 +07:00

1365 lines
49 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.Common;
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 PerfectWorld.Scripts.Shop;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Unity.Cinemachine;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.SceneManagement;
public partial class CECGameRun : ITickable
{
private static CECGameRun instance;
#region PROPERTIES AND FIELDS
private const uint USERCFG_VERSION = 3;
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 m_pHostPlayer;
private CECWorld m_pWorld;
protected CECUIManager m_pUIManager; // UI manager
CECPendingActionArray m_pendingLogout;
#endregion
public CECWorld GetWorld()
{
if (m_pWorld == null)
{
m_pWorld = new CECWorld();
}
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;
// Cache for SaveConfigsToServer: last sent config data to skip duplicate sends
private byte[] m_pCfgDataBuf;
private int m_iCfgDataSize;
// Logout flag (C++: m_iLogoutFlag)
// Selling role ID for role trade (C++: SetSellingRoleID/GetSellingRoleID)
private int m_iSellingRoleID;
[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 = 30;
#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;
//}
var instanceOB = Resources.Load<instanceDataAsset>("instance");
for(int i = 0; i < instanceOB.items.Length; i++)
{
if (!m_InstTab.ContainsKey(instanceOB.items[i].m_id))
{
var cecInstance = new CECInstance();
cecInstance.Load(instanceOB.items[i]);
m_InstTab.Add(instanceOB.items[i].m_id, cecInstance);
}
}
AddressableManager.Instance.OnDispose += Dispose;
if (m_pWorld == null)
m_pWorld = new CECWorld();
m_pendingLogout = new CECPendingActionArray( false);
TickInvoker.Instance.RegisterTickable(this);
}
private static void Dispose()
{
TickInvoker.Instance.UnregisterTickable(instance);
instance = null;
}
private void LoadPrefabs()
{
BMLogger.LogWarning("CECGameRun::LoadPrefabs, Loading prefabs from Resources. Consider using Addressables for better performance and memory management.");
_playerPrefab = Resources.Load<GameObject>(AddressResourceConfig.PlayerPrefab);
PrefabPoolManager.Instance.InitPool(_playerPrefab);
_monsterPrefab = Resources.Load<GameObject>(AddressResourceConfig.MonsterPrefab);
PrefabPoolManager.Instance.InitPool(_monsterPrefab, defaultCapacity: 200, maxSize: 250);
_npcServerPrefab = Resources.Load<GameObject>(AddressResourceConfig.NpcServerPrefab);
PrefabPoolManager.Instance.InitPool(_npcServerPrefab, defaultCapacity: 25, maxSize: 100);
_petServerPrefab = Resources.Load<GameObject>(AddressResourceConfig.PetServerPrefab);
PrefabPoolManager.Instance.InitPool(_petServerPrefab);
_petMountServerPrefab = Resources.Load<GameObject>(AddressResourceConfig.PetMountServerPrefab);
PrefabPoolManager.Instance.InitPool(_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
}
public bool StartGame(int idInst, Vector3 vHostPos)
{
// TODO: Implement the rest of the StartGame logic based on the original C++ code, including:
// End current game state
EndGameState();
//
// memset(&m_WallowInfo, 0, sizeof(m_WallowInfo));
m_iGameState = (int)GameState.GS_GAME;
//
// if (!g_pGame.LoadInGameRes())
// {
// a_LogOutput(1, "CECGameRun::StartGame, Failed to call LoadInGameRes().");
// return false;
// }
//
// // Create message manager
// if (!(m_pMessageMan = new CECMessageMan(this)))
// {
// glb_ErrorOutput(ECERR_NOTENOUGHMEMORY, "CECGameRun::StartGame", __LINE__);
// return false;
// }
//
// Create default game world
//if (!JumpToInstance(idInst, vHostPos))
//{
// // a_LogOutput(1, "CECGameRun::StartGame, Failed to create game world.");
// return false;
//}
//
// // ÉèÖÿç·þ³É¹¦±êʶ£¬ÒÔÀûÓÚ CECGameUIMan ¸ù¾Ý¿ç·þ״̬×öÏàÓ¦³õʼ»¯
// if (CECCrossServer::Instance().IsWaitLogin()){
// CECCrossServer::Instance().OnLoginSuccess();
// }
// if (CECReconnect::Instance().IsReconnecting()){
// CECReconnect::Instance().OnReconnectSuccess();
// }
//
// // Create host player
// if (!CreateHostPlayer())
// {
// a_LogOutput(1, "CECGameRun::StartGame, Failed to create host player.");
// return false;
// }
//
// // Create team manager
// if (!(m_pTeamMan = new CECTeamMan))
// {
// glb_ErrorOutput(ECERR_NOTENOUGHMEMORY, "CECGameRun::StartGame", __LINE__);
// return false;
// }
//
// // Reset faction manager
// g_pGame.GetFactionMan().Release(false);
//
// Create shortcuts
if (!CreateShortcuts())
{
// a_LogOutput(1, "CECGameRun::StartGame, Failed to create shortcuts");
return false;
}
//
// // Change UI manager
// if (!m_pUIManager.ChangeCurUIManager(CECUIManager::UIMAN_INGAME))
// {
// a_LogOutput(1, "CECGameRun::StartGame, Failed to change UI manager.");
// return false;
// }
// m_pInputFilter.LoadHotKey();
//
// CECGameUIMan* pGameUIMan = m_pUIManager.GetInGameUIMan();
// if (pGameUIMan)
// pGameUIMan.ChangeWorldInstance(idInst);
//
// l_SaveCfgCnt.Reset();
//
// // Change cursor to default icon
// g_pGame.ChangeCursor(RES_CUR_NORMAL);
// // Discard current frame
// g_pGame.DiscardFrame();
//
// // Clear frame controller
// memset(&l_fc, 0, sizeof (l_fc));
//
// // ³õʼ»¯ÍøÂçÑÓ³Ù²éѯ
// l_bFirstQuery = true;
// m_iInGameDelay = 0;
// l_DelayQueryCounter.Reset();
//
// l_QueryServerTime.Reset();
//
// // clear the selling id
// m_SellingRoleID = 0;
//
// // ÏÂÔØÆ÷ÏìÓ¦½øÈëÓÎϷ״̬
// if( g_pGame.GetConfigs().IsMiniClient() )
// CECMCDownload::GetInstance().SendSwitchGame(true);
//
return true;
}
public bool JumpToInstance(int idInst, Vector3 vHostPos, int iParallelWorldID = 0, Action actDone = null)
{
CECInstance pInst = GetInstance(idInst);
string nameScene = UnityGameSession.Instance.GetWorldInstanceName(idInst);
if (pInst == null || string.IsNullOrEmpty(nameScene))
{
CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan();
if (pGameUI != null)
pGameUI.ShowErrorMsg(pGameUI.GetStringFromTable(10700), "");
//EC_Game.GetGameSession().SetBreakLinkFlag(CECGameSession::LBR_MAP_INVALID);
//a_LogOutput(1, "CECGameRun::JumpToInstance, wrong instance id: %d", idInst);
return false;
}
if(m_pWorld != null)
{
if (m_pWorld.GetInstanceID() == pInst.GetID() /*&& m_pWorld.IsValid()*/)
{
// TO DO: fix later
//int iLast = m_pWorld.GetCurParallelWorld();
//if (iLast == iParallelWorldID)
//{
// //m_pWorld.SetLoadCenter(vPos);
//}
//else
//{
// m_pWorld.OnParallelWorldChange(vPos, iParallelWorldID);
// CECUIHelper::UpdateParallelWorld();
// if (iLast != 0)
// {
// CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan();
// if (pGameUI != null)
// {
// ACString strMsg;
// strMsg.Format(pGameUI.GetStringFromTable(10703), pInst.GetName(), iParallelWorldID);
// CECUIHelper::AddHeartBeatHint(strMsg);
// }
// }
//}
// Same map/instance: still run Goto completion (SetPos, move stamp, etc.); was missing and left player stuck until next move/jump.
// 同地图/实例:仍需执行 Goto 完成逻辑(SetPos、移动同步等);此前未调用导致传送不生效直到再次移动或跳跃。
actDone?.Invoke();
return true;
}
else
{
// Release current world
ReleaseWorld();
}
}
SceneLoader.SceneLoadProcess = SceneLoadProcess.Loading;
SceneLoader.LoadingProgress = 0;
UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single,
(progress) =>
{
LoadingSceneController.Instance.SetProgress(progress);
},
(value) =>
{
//isDoneWorldRender = value;
//isDoneNPCRender = true;
//isDoneWorldRender = true;
//actLoadChar?.Invoke();
//UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
m_pWorld.SetInstanceID(idInst);
actDone?.Invoke();
});
return true;
}
public static CECGameRun Instance
{
get
{
if (instance == null)
{
instance = new CECGameRun();
}
return instance;
}
}
public CECGameRun()
{
m_iGameState = (int)GameState.GS_NONE;
}
public CECHostPlayer GetHostPlayer()
{
return m_pHostPlayer;
}
/// <summary>
/// Animation / offline test scenes: scene-placed host is not spawned via <see cref="InitCharacter"/>.
/// Registers the in-scene <see cref="CECHostPlayer"/> so <see cref="EC_ManPlayer.GetPlayer"/> and skill GFX resolve host position.
/// </summary>
public void RegisterAnimSceneHostPlayer(CECHostPlayer host)
{
if (host == null)
return;
m_pHostPlayer = host;
BMLogger.Log($"[AnimSceneBootstrap] CECGameRun.RegisterAnimSceneHostPlayer cid={host.GetCharacterID()}");
}
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
CECGameRun.Instance?.GetWorld()?.SetInstanceID(idInst);
}
}
CECPlayer.InitStaticRes();
m_pHostPlayer = PrefabPoolManager.Instance.Spawn(_playerPrefab, Vector3.zero, Quaternion.identity, ObjectSpawner.Instance.transform).AddComponent<CECHostPlayer>();
m_pHostPlayer.InitCharacter(info);
if (m_pHostPlayer != null)
{
var t = Type.GetType("BrewMonster.UI.SelectedTargetHUDController, Assembly-CSharp");
if (t != null && m_pHostPlayer.GetComponent(t) == null)
m_pHostPlayer.gameObject.AddComponent(t);
}
}
public CECMonster GetMonster()
{
//return ObjectSpawner.Instance.InstantiateObject(_monsterPrefab, setThisAsParent: true)
// .GetComponent<CECMonster>();
return PrefabPoolManager.Instance.Spawn(_monsterPrefab, Vector3.zero, Quaternion.identity, ObjectSpawner.Instance.transform)
.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 = PrefabPoolManager.Instance.Spawn(_playerPrefab, Vector3.zero, Quaternion.identity, ObjectSpawner.Instance.transform);
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)
{
BMLogger.Log($"MH CECGameRun.LoadConfigsFromServer, iDataSize = {iDataSize}");
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>();
return PrefabPoolManager.Instance.Spawn(_petServerPrefab, Vector3.zero, Quaternion.identity, ObjectSpawner.Instance.transform)
.GetComponent<CECPet>();
}
public GameObject GetPetMount()
{
//return ObjectSpawner.Instance.InstantiateObject(_petMountServerPrefab, setThisAsParent: true);
return PrefabPoolManager.Instance.Spawn(_petMountServerPrefab, Vector3.zero, Quaternion.identity, ObjectSpawner.Instance.transform);
}
/// <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;
}
// fixed_msg.txt uses printf-style (%d, %s); not C# {0} placeholders
string szFormattedMsg;
try
{
if (args != null && args.Length > 0)
szFormattedMsg = AUIDialog.FormatPrintf(szFixMsg, args);
else
szFormattedMsg = szFixMsg;
}
catch (Exception ex)
{
Debug.LogError($"[AddFixedMessage] Format error for message {iMsg}: {ex.Message}");
szFormattedMsg = szFixMsg;
}
// Try to add to in-game UI chat
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan();
if (pGameUI != null)
{
pGameUI.AddChatMessage(szFormattedMsg, ChatChannel.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;
}
// fixed_msg.txt uses printf-style (%d, %s); not C# {0} placeholders
string szFormattedMsg;
try
{
if (args != null && args.Length > 0)
szFormattedMsg = AUIDialog.FormatPrintf(szFixMsg, args);
else
szFormattedMsg = szFixMsg;
}
catch (Exception ex)
{
Debug.LogError($"[AddFixedChannelMsg] Format error for message {iMsg}: {ex.Message}");
szFormattedMsg = szFixMsg;
}
// 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, (ChatChannel)cChannel, idPlayer, szName, byFlag, cEmotion, pItem, pszMsgOrigion);
}
else
{
// Fallback to debug output if UI is not available
BMLogger.LogError($"[Cuong] [Error] pGameUI == null");
// 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; }
// Logout flag: -1 none, 0 exit app, 1 re-select role, 2 goto login (C++: SetLogoutFlag/GetLogoutFlag)
public void SetLogoutFlag(int iFlag) { m_iLogoutFlag = iFlag; }
public int GetLogoutFlag() { return m_iLogoutFlag; }
// Selling role ID for role trade (C++: SetSellingRoleID)
public void SetSellingRoleID(int roleid) { m_iSellingRoleID = roleid; }
public int GetSellingRoleID() { return m_iSellingRoleID; }
// Save necessary user configs (UI, shortcut, accelerate keys, etc.) to server
// ֵ: 0(ʧ), 1(ظ), 2(Э)
public uint SaveConfigsToServer()
{
// if (!m_pWorld || !m_pWorld.GetHostPlayer() || !m_pWorld.GetHostPlayer().HostIsReady() || !m_pUIManager.GetInGameUIMan())
// return 0;
CECHostPlayer pHost = GetHostPlayer();
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan() as CECGameUIMan;
if (m_pWorld == null || pHost == null || !pHost.HostIsReady() || pGameUI == null)
return 0;
// g_pGame.GetConfigs().SaveBlockedID();
EC_Game.GetConfigs().SaveBlockedID(); // TODO: Check if this is needed here
// int iTotalSize = 0;
// iTotalSize += sizeof (DWORD);
// iTotalSize += sizeof (int);
// int iHostSize = 0;
// CECHostPlayer* pHost = m_pWorld.GetHostPlayer();
// pHost.SaveConfigData(NULL, &iHostSize);
// iTotalSize += iHostSize;
// iTotalSize += sizeof (int);
int iTotalSize = sizeof(uint);
iTotalSize += sizeof(int);
int iHostSize = 0;
pHost.SaveConfigData(null, ref iHostSize);
iTotalSize += sizeof(int) + iHostSize;
// DWORD dwUISize = 0;
// CECGameUIMan* pGameUI = (CECGameUIMan*)m_pUIManager.GetInGameUIMan();
// pGameUI.GetUserLayout(NULL, dwUISize);
// iTotalSize += (int)dwUISize;
// iTotalSize += sizeof (int);
uint dwUISize = 0;
pGameUI.GetUserLayout(null,0, ref dwUISize); // TODO: Check if this is needed here
iTotalSize += sizeof(int) + (int)dwUISize;
// int iSettingSize = 0;
// g_pGame.GetConfigs().SaveUserConfigData(NULL, &iSettingSize);
// iTotalSize += iSettingSize;
int iSettingSize = 0;
EC_Game.GetConfigs().SaveUserConfigData(null, 0, out iSettingSize);
// iTotalSize += sizeof(int) + iSettingSize;
iTotalSize += iSettingSize;
// void* pDataBuf = a_malloctemp(iTotalSize);
// if (!pDataBuf) { glb_ErrorOutput(ECERR_NOTENOUGHMEMORY, "CECGameRun::SaveConfigsToServer", __LINE__); return 0; }
// BYTE* pData = (BYTE*)pDataBuf;
byte[] pDataBuf = new byte[iTotalSize];
int offset = 0;
// *((DWORD*)pData) = USERCFG_VERSION;
// pData += sizeof (DWORD);
Buffer.BlockCopy(BitConverter.GetBytes(USERCFG_VERSION), 0, pDataBuf, offset, sizeof(uint));
offset += sizeof(uint);
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after version)");
// *((int*)pData) = iHostSize;
// pData += sizeof (int);
// pHost.SaveConfigData(pData, &iHostSize);
// pData += iHostSize;
Buffer.BlockCopy(BitConverter.GetBytes(iHostSize), 0, pDataBuf, offset, sizeof(int));
offset += sizeof(int);
pHost.SaveConfigData(pDataBuf, ref iHostSize, offset); // TODO: converted but need to check
offset += iHostSize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after host config, iHostSize={iHostSize})");
// *((int*)pData) = (int)dwUISize;
// pData += sizeof (int);
// pGameUI.GetUserLayout(pData, dwUISize);
// pData += dwUISize;
Buffer.BlockCopy(BitConverter.GetBytes((int)dwUISize), 0, pDataBuf, offset, sizeof(int));
offset += sizeof(int);
pGameUI.GetUserLayout(pDataBuf, offset, ref dwUISize); // TODO: Check if this is needed here
offset += (int)dwUISize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after UI layout, dwUISize={dwUISize})");
// *((int*)pData) = iSettingSize;
// pData += sizeof (int);
// g_pGame.GetConfigs().SaveUserConfigData(pData, &iSettingSize);
// pData += iSettingSize;
Buffer.BlockCopy(BitConverter.GetBytes(iSettingSize), 0, pDataBuf, offset, sizeof(int));
offset += sizeof(int);
EC_Game.GetConfigs().SaveUserConfigData(pDataBuf, offset, out iSettingSize);
offset += iSettingSize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after user config, iSettingSize={iSettingSize}), iTotalSize={iTotalSize}");
// if (m_pCfgDataBuf) {
// if (m_iCfgDataSize == iTotalSize && !memcmp(m_pCfgDataBuf, pDataBuf, iTotalSize)) { a_freetemp(pDataBuf); return 1; }
// a_free(m_pCfgDataBuf); m_pCfgDataBuf = NULL; m_iCfgDataSize = 0;
// }
if (m_pCfgDataBuf != null && m_iCfgDataSize == iTotalSize)
{
bool same = true;
for (int i = 0; i < iTotalSize && same; i++)
same = (m_pCfgDataBuf[i] == pDataBuf[i]);
if (same)
return 1;
}
m_pCfgDataBuf = null;
m_iCfgDataSize = 0;
// if ((m_pCfgDataBuf = (BYTE*)a_malloc(iTotalSize))) { memcpy(m_pCfgDataBuf, pDataBuf, iTotalSize); m_iCfgDataSize = iTotalSize; }
m_pCfgDataBuf = new byte[iTotalSize];
Buffer.BlockCopy(pDataBuf, 0, m_pCfgDataBuf, 0, iTotalSize);
m_iCfgDataSize = iTotalSize;
// DWORD dwCompLen = iTotalSize * 2;
// void* pCompBuf = a_malloctemp(dwCompLen);
// if (!pCompBuf) { a_freetemp(pDataBuf); glb_ErrorOutput(ECERR_NOTENOUGHMEMORY, "CECGameRun::SaveConfigsToServer", __LINE__); return 0; }
// int iVerLen = sizeof (DWORD);
// memcpy(pCompBuf, pDataBuf, iVerLen);
// BYTE* pSrc = (BYTE*)pDataBuf + iVerLen;
// BYTE* pDst = (BYTE*)pCompBuf + iVerLen;
// dwCompLen -= iVerLen;
// int iRes = AFilePackage::Compress(pSrc, iTotalSize - iVerLen, pDst, &dwCompLen);
int iVerLen = sizeof(uint);
// int compLen = (iTotalSize - iVerLen) * 2;
int compLen = iTotalSize * 2;
byte[] pCompBuf = new byte[iVerLen + compLen];
compLen -= iVerLen;
Buffer.BlockCopy(pDataBuf, 0, pCompBuf, 0, iVerLen);
int iRes = AFilePackage.Compress(pDataBuf, iVerLen,iTotalSize - iVerLen, pCompBuf, iVerLen, ref compLen);
// if (0 == iRes) { g_pGame->GetGameSession()->SaveConfigData(pCompBuf, dwCompLen+iVerLen); iRes = 2; }
// else { a_LogOutput(1, "CECGameRun::SaveConfigsToServer, Failed to compress config data (%d:%d)", iRes, iTotalSize); iRes = 0; }
// a_freetemp(pDataBuf);
// a_freetemp(pCompBuf);
// return iRes;
if (iRes == 0)
{
var session = UnityGameSession.Instance?.GameSession;
if (session != null)
{
session.SaveConfigData(pCompBuf, iVerLen + compLen);
return 2;
}
}
else
BMLogger.LogWarning($"CECGameRun::SaveConfigsToServer, Failed to compress config data ({iRes}:{iTotalSize})");
return 0;
}
public void ReleasePendingActions()
{
m_pendingLogout.Clear();
}
public CECPendingActionArray GetPendingLogOut(){ return m_pendingLogout; }
// Game tick routine
public bool Tick(uint dwDeltaTime)
{
// if (GetWallowInfo().anti_wallow_active &&
// g_pGame.GetGameSession().IsConnected() &&
// GetGameState() == GS_GAME)
// {
// if (CECUIConfig::Instance().GetGameUI().nWallowHintType != CECUIConfig::GameUI::WHT_KOREA)
// {
// // ·À³ÁÃÔµ½3Сʱ£¬ÈôAU²»ÌßÈË£¨ÏûÏ¢¶ªÊ§£©£¬Ôò×Ô¶¯ÏÂÏß
// int stime = g_pGame.GetServerGMTTime();
// int nTime = stime - GetWallowInfo().play_time;
// if (nTime >= 3 * 3600)
// {
// // ÒѾ­³¬¹ý3Сʱ
// g_pGame.GetGameSession().SetBreakLinkFlag(CECGameSession::LBR_ANTI_WALLOW);
// }
// }
// }
//
// DWORD dwTickTime = a_GetTime();
//
// CECGameSession* pSession = g_pGame.GetGameSession();
// pSession.ProcessNewProtocols();
// DWORD dwRealTime = g_pGame.GetRealTickTime();
if (m_iLogoutFlag >= 0)
{
Logout();
m_iLogoutFlag = -1;
}
// CECReconnect::Instance().Tick();
//
// if (m_pUIManager)
// m_bUIHasCursor = m_pUIManager.UIControlCursor();
// else
// m_bUIHasCursor = false;
//
// // Deal input first
// if (m_pInputCtrl)
// m_pInputCtrl.Tick();
//
// // Tick world
// if (!TickGameWorld(dwDeltaTime, g_pGame.GetViewport()))
// return false;
// Tick UI
// if (m_pUIManager)
// m_pUIManager.Tick();
// // Tick GFX caster
// g_pGame.GetGFXCaster().Tick(dwDeltaTime);
//
// // Tick GFX Manager
// g_pGame.GetA3DGFXExMan().Tick(dwDeltaTime);
//
// // A3DEngine::TickAnimation trigger animation of many objects.
// // For example: A3DSky objects, GFX objects etc.
// static DWORD dwAnimTime = 0;
// dwAnimTime += dwDeltaTime;
// while (dwAnimTime >= TIME_TICKANIMATION)
// {
// dwAnimTime -= TIME_TICKANIMATION;
// g_pGame.GetA3DEngine().TickAnimation();
// }
//
// // Update ear position so that all 3D sounds' positions are correct
// static DWORD dwEarTime = 0;
// if ((dwEarTime += dwDeltaTime) >= TIME_UPDATEEAR)
// {
// dwEarTime -= TIME_UPDATEEAR;
//
// CECHostPlayer* pHostPlayer = NULL;
// if (m_pWorld)
// pHostPlayer = m_pWorld.GetHostPlayer();
//
// A3DCamera * pCamera = g_pGame.GetViewport().GetA3DCamera();
//
// if (GetGameState() == CECGameRun::GS_GAME && pHostPlayer && pHostPlayer.HostIsReady())
// {
// AM3DSoundDevice * pAM3DSoundDevice = g_pGame.GetA3DEngine().GetAMSoundEngine().GetAM3DSoundDevice();
// A3DVECTOR3 vecDir = pCamera.GetDirH();
// A3DVECTOR3 vecUp = A3DVECTOR3(0.0f, 1.0f, 0.0f);
//
// // Now we should adjust the 3d sound device's pos and orientation;
// if (pAM3DSoundDevice)
// {
// pAM3DSoundDevice.SetPosition(pHostPlayer.GetPos() + A3DVECTOR3(0.0f, 0.8f, 0.0f));
// pAM3DSoundDevice.SetOrientation(vecDir, vecUp);
// pAM3DSoundDevice.UpdateChanges();
// }
// }
// else
// g_pGame.GetViewport().GetA3DCamera().UpdateEar();
// }
//
// // Tick Run-Time debug information
// g_pGame.GetRTDebug().Tick(dwDeltaTime);
//
// // Save UI configs when time reached
// if (m_iGameState == GS_GAME && l_SaveCfgCnt.IncCounter(dwRealTime))
// {
// l_SaveCfgCnt.Reset();
// SaveConfigsToServer();
// }
//
// l_StatCnt.IncCounter(dwDeltaTime);
//
// pSession.ClearOldProtocols();
//
// DWORD dwCurrentTick = a_GetTime();
// dwTickTime = (dwCurrentTick > dwTickTime) ? (dwCurrentTick - dwTickTime) : 0;
// l_Statistic.iTickTime = (int)dwTickTime;
//
// if (GetGameState() == CECGameRun::GS_GAME && l_fc.iAvgRdTime)
// {
// // Accumulate tick time
// l_fc.iTickCnt++;
// l_fc.iTickTime += (int)dwTickTime;
// }
//
// if (GetGameState() == GS_GAME && GetHostPlayer() && GetHostPlayer().HostIsReady())
// {
// if (l_bFirstQuery || l_DelayQueryCounter.IncCounter(dwDeltaTime))
// {
// // µÚÒ»´Î²éѯ£¬»òÕß²éѯ¼ÆÊýÆ÷µ½µã
//
// // ·¢ËÍÍøÂçÓµ¼·²éѯЭÒé
// l_iDelayTimeStamp = timeGetTime();
// g_pGame.GetGameSession().c2s_CmdQueryNetworkDelay(l_iDelayTimeStamp);
// l_DelayQueryCounter.Reset();
// l_bFirstQuery = false;
// }
//
// if (l_QueryServerTime.IncCounter(dwDeltaTime))
// {
// g_pGame.GetGameSession().c2s_CmdSendGetServerTime();
// l_QueryServerTime.Reset();
// }
// }
//
// m_pendingLogout.Update(dwDeltaTime);
//
// // ÓÅ»¯ÄÚ´æµÄÕ¼ÓÃ
// m_pMemSimplify.Tick(dwDeltaTime);
//
// // ¸üÐÂÏÂÔØ×´Ì¬
// CECMCDownload::GetInstance().Tick(dwDeltaTime);
//
// // ¸üÐÂ×Ô¶¯²ßÂÔ
// CECAutoPolicy::GetInstance().Tick(dwDeltaTime);
//
// if(m_pRandomMapProc)
// m_pRandomMapProc.Tick(dwDeltaTime);
//
// #ifdef _PROFILE_MEMORY
// g_TickMemoryHistory();
// #endif
TickHealthPlaytimeChatReminder(dwDeltaTime);
return true;
}
// Load instance information from file
bool LoadInstanceInfo(string szFile)
{
// AWScriptFile sf = new AWScriptFile();
//if (!sf.Open(szFile))
//{
// //a_LogOutput(1, "CECGameRun::LoadInstanceInfo, Failed to load %s", szFile);
// return false;
//}
// CECInstance pInst;
// while (sf.PeekNextToken(true))
// {
// pInst = new CECInstance();
// if (pInst == null || !pInst.Load(sf))
// {
// //a_LogOutput(1, "CECGameRun::LoadInstanceInfo, Failed to read %s near line:%d", szFile, sf.GetCurLine());
// return false;
// }
// if (!m_InstTab.ContainsKey(pInst.GetID()))
// {
// // ID collsion ?
// m_InstTab.Add(pInst.GetID(), pInst);
// }
// }
// sf.Close();
return true;
}
private Dictionary<string, int> m_Name2IDTab = new Dictionary<string, int>();
private Dictionary<int, string> m_ID2NameTab = new Dictionary<int, string>();
// Get player name
public string GetPlayerName(int cid, bool autoGen)
{
if (m_ID2NameTab.TryGetValue(cid, out var name))
return name;
if (autoGen)
return $"P-{cid}";
return null;
}
// Add player name to table
public void AddPlayerName(int cid, string szName, bool bOverwrite = false)
{
if (cid == 0)
{
Debug.LogError("CECGameRun::AddPlayerName, Invalid cid(=0)!");
return;
}
string strName = szName;
if (string.IsNullOrEmpty(strName))
{
Debug.LogError($"CECGameRun::AddPlayerName, Invalid name for cid={cid}!");
return;
}
// Name -> ID
var Pair2 = m_Name2IDTab.TryGetValue(strName, out var value2);
if (!Pair2)
m_Name2IDTab[strName] = cid;
else
m_Name2IDTab[strName] = cid;
// ID -> Name
var Pair = m_ID2NameTab.TryGetValue(cid, out var value);
if (Pair)
{
if (bOverwrite)
{
m_ID2NameTab[cid] = strName;
}
return;
}
m_ID2NameTab[cid] = strName;
}
}
public enum GameState
{
GS_NONE = 0, // None
GS_LOGIN, // Login in state
GS_GAME, // In game
};