486 lines
16 KiB
C#
486 lines
16 KiB
C#
using BrewMonster;
|
||
using BrewMonster.Network;
|
||
using BrewMonster.Scripts;
|
||
using BrewMonster.Scripts.World;
|
||
using BrewMonster.UI;
|
||
using CSNetwork;
|
||
using CSNetwork.GPDataType;
|
||
using CSNetwork.Protocols.RPCData;
|
||
using System.Collections.Generic;
|
||
using System.Data;
|
||
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
|
||
|
||
// 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;
|
||
|
||
protected CECUIManager m_pUIManager; // UI manager
|
||
|
||
public CECWorld GetWorld() { return m_pWorld; }
|
||
// 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.
|
||
|
||
|
||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||
private static void AfterSceneLoad()
|
||
{
|
||
l_SelRoleInfo = null;
|
||
m_InstTab = new Dictionary<int, CECInstance>();
|
||
}
|
||
public void Init()
|
||
{
|
||
Application.targetFrameRate = 60;
|
||
instance = this;
|
||
// _gameRunConfig = Resources.Load<GameRunConfig>("GameRunConfig");
|
||
// _playerPrefab = _gameRunConfig.PlayerPrefab;
|
||
// _monsterPrefab = _gameRunConfig.MonsterPrefab;
|
||
// _npcServerPrefab = _gameRunConfig.NpcServerPrefab;
|
||
LoadPrefabs();
|
||
|
||
// 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;
|
||
StartGame(0, Vector3.zero);
|
||
}
|
||
|
||
private static void Dispose()
|
||
{
|
||
instance = null;
|
||
AddressableManager.Instance.ReleaseAsset(AddressResourceConfig.PlayerPrefab);
|
||
AddressableManager.Instance.ReleaseAsset(AddressResourceConfig.MonsterPrefab);
|
||
AddressableManager.Instance.ReleaseAsset(AddressResourceConfig.NpcServerPrefab);
|
||
}
|
||
|
||
private async void LoadPrefabs()
|
||
{
|
||
_playerPrefab = await AddressableManager.Instance.LoadPrefabAsync(AddressResourceConfig.PlayerPrefab);
|
||
_monsterPrefab = await AddressableManager.Instance.LoadPrefabAsync(AddressResourceConfig.MonsterPrefab);
|
||
_npcServerPrefab = await AddressableManager.Instance.LoadPrefabAsync(AddressResourceConfig.NpcServerPrefab);
|
||
}
|
||
|
||
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;
|
||
}
|
||
if (parent == null)
|
||
{
|
||
var obj = ObjectSpawner.Instance.InstantiateObject(prefab, setThisAsParent: true);
|
||
obj.transform.position = position;
|
||
DestroyTestVfx(obj, timeLife);
|
||
}
|
||
else
|
||
{
|
||
var obj = ObjectSpawner.Instance.InstantiateObject(prefab, parent, false);
|
||
obj.transform.position = position;
|
||
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;
|
||
int dataOffset = offset;
|
||
|
||
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;
|
||
dataOffset = 0;
|
||
}
|
||
|
||
try
|
||
{
|
||
// Create data reader / 创建数据读取器
|
||
CECDataReader dr = new CECDataReader(pData, dataOffset, (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;
|
||
}
|
||
}
|