Merge branch 'develop' into feature/skill-data

This commit is contained in:
VDH
2025-12-17 17:18:28 +07:00
123 changed files with 3281172 additions and 2260 deletions
+109
View File
@@ -18,6 +18,13 @@ public partial class CECGameRun
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;
@@ -27,6 +34,12 @@ public partial class CECGameRun
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>();
public void Init()
@@ -52,6 +65,7 @@ public partial class CECGameRun
if(!m_InstTab.ContainsKey(161))
m_InstTab.Add(161, new CECInstance());
AddressableManager.Instance.OnDispose += Dispose;
StartGame(0, Vector3.zero);
}
private static void Dispose()
@@ -68,13 +82,26 @@ public partial class CECGameRun
_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;
}
@@ -315,6 +342,88 @@ public partial class CECGameRun
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
+17 -16
View File
@@ -7,6 +7,7 @@ using UnityEngine;
using System.Runtime.InteropServices;
using BrewMonster.Network;
using BrewMonster.UI;
using Cysharp.Threading.Tasks;
namespace BrewMonster
{
@@ -56,7 +57,7 @@ namespace BrewMonster
public CECShortcutSet GetShortcutSet1(int n) { return m_aSCSets1[n]; }
public CECShortcutSet GetShortcutSet2(int n) { return m_aSCSets2[n]; }
private void OnMsgHstTaskData(ECMSG Msg)
private async UniTaskVoid OnMsgHstTaskData(ECMSG Msg)
{
// decode header to distinguish TASK_DATA vs TASK_VAR_DATA
// if (!(Msg.dwParam2 is cmd_header header))
@@ -64,7 +65,7 @@ namespace BrewMonster
// Debug.LogError("OnMsgHstTaskData: invalid header");
// return;
// }
int header = Convert.ToInt32(Msg.dwParam2);
byte[] pDataBuf = Msg.dwParam1 as byte[];
@@ -85,12 +86,13 @@ namespace BrewMonster
m_pTaskInterface = null;
m_pTaskInterface = new CECTaskInterface(this);
if (!m_pTaskInterface.Init(
pCmd.active_list, (int)pCmd.active_list_size,
pCmd.finished_list, (int)pCmd.finished_list_size,
pCmd.finished_time_list, (int)pCmd.finished_time_list_size,
pCmd.finished_count, (int)pCmd.finished_count_size,
pCmd.storage_task, (int)pCmd.storage_task_size))
var initTask = await m_pTaskInterface.Init(
pCmd.active_list, (int)pCmd.active_list_size,
pCmd.finished_list, (int)pCmd.finished_list_size,
pCmd.finished_time_list, (int)pCmd.finished_time_list_size,
pCmd.finished_count, (int)pCmd.finished_count_size,
pCmd.storage_task, (int)pCmd.storage_task_size);
if (!initTask)
{
Debug.LogError("CECHostPlayer::OnMsgHstTaskData, failed to initialize task interface");
return;
@@ -108,16 +110,15 @@ namespace BrewMonster
}
else if (header == CommandID.TASK_VAR_DATA)
{
Debug.Log($" OnMsgHstTaskData: Received TASK_VAR_DATA, size: {pDataBuf.Length} bytes");
// Minimal forwarding; original code passes inner data pointer and size
if (m_pTaskInterface != null)
{
OnServerNotify(m_pTaskInterface, pDataBuf, pDataBuf.Length);
}
cmd_task_var_data pCmd = new cmd_task_var_data();
pCmd.ReadBuffer(pDataBuf);
// ASSERT(pCmd);
if(m_pTaskInterface!= null)
OnServerNotify(m_pTaskInterface, pCmd.data, (int)pCmd.size);
else
{
Debug.LogError("OnMsgHstTaskData: m_pTaskInterface is null on TASK_VAR_DATA");
}
// ASSERT(m_pTaskInterface);
BMLogger.LogError($" CECHostPlayer::OnMsgHstTaskData: TASK_VAR_DATA received but m_pTaskInterface is null");
}
}
File diff suppressed because it is too large Load Diff
+123 -25
View File
@@ -26,18 +26,22 @@ public class CECUIManager : MonoSingleton<CECUIManager>
protected override void Awake()
{
base.Awake();
EventBus.Subscribe<NPCINFO>(ShowUINPC);
EventBus.Subscribe<CECHostPlayer.NPCINFO>(ShowUINPC);
EventBus.Subscribe<NPCDiedEvent>(TryHideUINPC);
gameUI = new CECGameUIMan();
gameUI.SetDependency(dialogResouce, canvasDlg);
gameUI.Init();
}
private void OnDestroy()
{
EventBus.Unsubscribe<NPCINFO>(ShowUINPC);
EventBus.Unsubscribe<CECHostPlayer.NPCINFO>(ShowUINPC);
EventBus.Unsubscribe<NPCDiedEvent>(TryHideUINPC);
}
private void ShowUINPC(NPCINFO obj)
private void ShowUINPC(CECHostPlayer.NPCINFO obj)
{
npsUI.gameObject.SetActive(true);
npsUI.SetText($"{obj.CurrentHealth}/{obj.MaxHealth}", obj.Name, "");
@@ -59,36 +63,114 @@ public class CECUIManager : MonoSingleton<CECUIManager>
}
/// <summary>
/// Lấy hoặc spawn UI mới nếu chưa có
/// Show UI by name of component ("DlgTask", "EC_InventoryUI")
/// </summary>
public T ShowUI<T>() where T : Component
/// <param name="componentName">name of component ("DlgTask", "EC_InventoryUI")</param>
public void ShowUI(string componentName)
{
var type = typeof(T);
if (string.IsNullOrEmpty(componentName) || canvasDlg == null)
{
if (canvasDlg == null) Debug.LogError("canvasDlg chưa được gán");
return;
}
// Nếu đã spawn rồi thì bật lại
if (_spawnedUIs.TryGetValue(type, out var uiGo))
var type = FindTypeByName(componentName);
if (TryShowCachedUI(type)) return;
if (FindUIByName(componentName, type)) return;
if (FindUIByType(type)) return;
Debug.LogWarning($"Không tìm thấy UI {componentName} đã spawn trong canvasDlg. Type found: {(type != null ? type.FullName : "null")}");
}
private System.Type FindTypeByName(string componentName)
{
string[] namespacePrefixes = {
"", // No namespace
"BrewMonster.Scripts.Task.UI.",
"BrewMonster.UI.",
"BrewMonster.Scripts.UI.",
"BrewMonster."
};
// Try with common namespace prefixes
foreach (var prefix in namespacePrefixes)
{
string fullTypeName = string.IsNullOrEmpty(prefix) ? componentName : prefix + componentName;
var type = System.Type.GetType(fullTypeName);
if (type != null) return type;
}
// Search in all assemblies
foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies())
{
var type = assembly.GetType(componentName);
if (type != null) return type;
foreach (var prefix in namespacePrefixes)
{
if (string.IsNullOrEmpty(prefix)) continue;
type = assembly.GetType(prefix + componentName);
if (type != null) return type;
}
}
return null;
}
private bool TryShowCachedUI(System.Type type)
{
if (type != null && _spawnedUIs.TryGetValue(type, out var uiGo))
{
uiGo.SetActive(true);
return uiGo.GetComponent<T>();
return true;
}
// Tìm prefab phù hợp
var prefab = uiPrefabs.Find(p => p.GetComponent<T>() != null);
if (prefab == null)
{
Debug.LogError($"Không tìm thấy prefab chứa component {type.Name}");
return null;
}
// Spawn mới
var instance = Instantiate(prefab, uiRoot ? uiRoot : transform);
instance.name = $"{type.Name}_UI";
_spawnedUIs[type] = instance;
instance.SetActive(true);
return instance.GetComponent<T>();
return false;
}
private bool FindUIByName(string componentName, System.Type type)
{
for (int i = 0; i < canvasDlg.transform.childCount; i++)
{
var child = canvasDlg.transform.GetChild(i);
if (!child.name.Contains(componentName) && child.name != componentName) continue;
if (type != null)
{
var foundComponent = child.GetComponentInChildren(type, true);
if (foundComponent != null)
{
ActivateAndCacheUI(foundComponent.gameObject, type);
return true;
}
}
ActivateAndCacheUI(child.gameObject, type);
return true;
}
return false;
}
private bool FindUIByType(System.Type type)
{
if (type == null) return false;
var foundComponent = canvasDlg.GetComponentInChildren(type, true);
if (foundComponent != null)
{
ActivateAndCacheUI(foundComponent.gameObject, type);
return true;
}
return false;
}
private void ActivateAndCacheUI(GameObject uiGameObject, System.Type type)
{
uiGameObject.SetActive(true);
if (type != null) _spawnedUIs[type] = uiGameObject;
}
/// <summary>
/// Ẩn UI (disable thay vì destroy)
/// </summary>
@@ -139,4 +221,20 @@ public class CECUIManager : MonoSingleton<CECUIManager>
{
return currentTargetNPCID;
}
//todo: change this code to other place
private int slot = 0;
public void OnClickedWaveHand()
{
if (EC_Game.GetGameRun().GetPoseCmdShortcuts() == null)
{
EC_Game.GetGameRun().StartGame(0, Vector3.zero);
}
CECShortcut pSC = EC_Game.GetGameRun().GetPoseCmdShortcuts().GetShortcut(slot);
if (pSC != null) // && pObjSrc->GetDataPtr("ptr_CECShortcut") == pSC
{
// a_LogOutput(1, "[Dat Emote] ptr_CECShortcut");
pSC.Execute();
}
}
}
+16 -3
View File
@@ -103,9 +103,22 @@ namespace BrewMonster
}
};
[ StructLayout(LayoutKind.Sequential, Pack = 1) ]
struct cmd_task_var_data
{
public uint size;
public int size;
public byte[] data;
};
}
public void ReadBuffer(byte[] buffer)
{
int offset = 0;
size = BitConverter.ToInt32(buffer, offset);
offset += 4;
data = new byte[size];
Buffer.BlockCopy(buffer, offset, data, 0, size);
offset += size;
}
}
}
+3
View File
@@ -1,3 +1,4 @@
using System;
using Animancer;
using BrewMonster;
using System.Collections.Generic;
@@ -150,6 +151,7 @@ namespace BrewMonster
return namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false;
}
private string _currentAnimationName;
/// <summary>
/// play an animation with name
/// </summary>
@@ -159,6 +161,7 @@ namespace BrewMonster
private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode)
{
_currentState = namedAnimancer.TryPlay(animationName, duration, fadeMode);
_currentAnimationName = animationName;
if (_currentState == null)
{
BMLogger.LogError($"Null animation with name: {animationName}");