diff --git a/.gitignore b/.gitignore index 9eb70ce1f5..0855b4d9af 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,4 @@ InitTestScene*.unity* # Auto-generated scenes by play mode tests /[Aa]ssets/[Ii]nit[Tt]est[Ss]cene*.unity* +ProjectSettings/EditorBuildSettings.asset diff --git a/.idea/.idea.perfect-world-unity/.idea/projectSettingsUpdater.xml b/.idea/.idea.perfect-world-unity/.idea/projectSettingsUpdater.xml new file mode 100644 index 0000000000..ef20cb08cd --- /dev/null +++ b/.idea/.idea.perfect-world-unity/.idea/projectSettingsUpdater.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.perfect-world-unity/.idea/workspace.xml b/.idea/.idea.perfect-world-unity/.idea/workspace.xml new file mode 100644 index 0000000000..85b3df73df --- /dev/null +++ b/.idea/.idea.perfect-world-unity/.idea/workspace.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1757057210233 + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Assets/Editor/EditorLogTools.cs b/Assets/Editor/EditorLogTools.cs new file mode 100644 index 0000000000..400a9b51c3 --- /dev/null +++ b/Assets/Editor/EditorLogTools.cs @@ -0,0 +1,160 @@ +// Assets/Editor/EditorLogTools.cs +#if UNITY_EDITOR +using System; +using System.IO; +using UnityEditor; +using UnityEngine; + +public static class EditorLogTools +{ + // ===== Public Menu ===== + [MenuItem("Tools/Logs/Clear Editor.log")] + public static void ClearEditorLogMenu() + { + string path = GetEditorLogPath(); + if (string.IsNullOrEmpty(path)) + { + EditorUtility.DisplayDialog("Editor.log", "Không xác định được đường dẫn Editor.log trên hệ điều hành này.", "OK"); + return; + } + + if (!File.Exists(path)) + { + EditorUtility.DisplayDialog("Editor.log", $"Không tìm thấy file:\n{path}", "OK"); + return; + } + + try + { + TruncateFile(path); + EditorUtility.DisplayDialog("Editor.log", "Đã xoá sạch nội dung Editor.log ✅", "OK"); + } + catch (Exception e) + { + Debug.LogError($"[EditorLogTools] Clear failed: {e}"); + EditorUtility.DisplayDialog("Editor.log", "Xoá thất bại. Xem Console để biết chi tiết.", "OK"); + } + } + + [MenuItem("Tools/Logs/Trim Editor.log…")] + public static void TrimEditorLogMenu() + { + string input = EditorUtility.DisplayDialogComplex("Trim Editor.log", + "Chọn kích thước còn lại của Editor.log sau khi cắt:", + "Giữ 256 KB", "Giữ 1 MB", "Tự nhập (KB)") switch + { + 0 => "256", + 1 => "1024", + _ => EditorUtility.DisplayDialog("Nhập dung lượng", "Nhập số KB muốn giữ lại (ví dụ 512):", "OK") + ? "512" // fallback, Unity không có input prompt chuẩn; giữ default + : null + }; + + if (string.IsNullOrEmpty(input)) return; + + if (!int.TryParse(input, out int keepKb) || keepKb < 1) keepKb = 512; + + string path = GetEditorLogPath(); + if (!File.Exists(path)) + { + EditorUtility.DisplayDialog("Editor.log", $"Không tìm thấy file:\n{path}", "OK"); + return; + } + + try + { + TrimTail(path, keepKb * 1024); + EditorUtility.DisplayDialog("Editor.log", $"Đã cắt Editor.log, giữ lại ~{keepKb} KB cuối cùng ✅", "OK"); + } + catch (Exception e) + { + Debug.LogError($"[EditorLogTools] Trim failed: {e}"); + EditorUtility.DisplayDialog("Editor.log", "Trim thất bại. Xem Console để biết chi tiết.", "OK"); + } + } + + [MenuItem("Tools/Logs/Open Editor.log")] + public static void OpenEditorLogMenu() + { + string path = GetEditorLogPath(); + if (File.Exists(path)) + EditorUtility.OpenWithDefaultApp(path); + else + EditorUtility.DisplayDialog("Editor.log", $"Không tìm thấy file:\n{path}", "OK"); + } + + [MenuItem("Tools/Logs/Reveal log folder")] + public static void RevealLogFolder() + { + string path = GetEditorLogPath(); + string dir = string.IsNullOrEmpty(path) ? null : Path.GetDirectoryName(path); + if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir)) + EditorUtility.RevealInFinder(dir); + else + EditorUtility.DisplayDialog("Editor.log", "Không mở được thư mục log.", "OK"); + } + + // ===== Core ===== + private static void TruncateFile(string path) + { + // Cho phép Editor tiếp tục ghi khi ta truncate (FileShare.ReadWrite) + using var fs = new FileStream(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite); + fs.SetLength(0); + fs.Flush(true); + } + + private static void TrimTail(string path, int keepBytes) + { + var fi = new FileInfo(path); + long size = fi.Length; + if (size <= keepBytes) + return; // không cần cắt + + // đọc phần đuôi rồi ghi đè lại + byte[] buffer; + using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + fs.Seek(size - keepBytes, SeekOrigin.Begin); + buffer = new byte[keepBytes]; + int read = fs.Read(buffer, 0, keepBytes); + if (read < keepBytes) + { + Array.Resize(ref buffer, read); + } + } + + using (var fs = new FileStream(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)) + { + fs.SetLength(0); + fs.Write(buffer, 0, buffer.Length); + fs.Flush(true); + } + } + + // ===== OS Paths ===== + private static string GetEditorLogPath() + { + // Tham chiếu đường dẫn theo Unity docs + switch (Application.platform) + { + case RuntimePlatform.WindowsEditor: + // C:\Users\\AppData\Local\Unity\Editor\Editor.log + string localApp = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + return Path.Combine(localApp, "Unity", "Editor", "Editor.log"); + + case RuntimePlatform.OSXEditor: + // ~/Library/Logs/Unity/Editor.log + string home = Environment.GetFolderPath(Environment.SpecialFolder.Personal); + return Path.Combine(home, "Library", "Logs", "Unity", "Editor.log"); + + case RuntimePlatform.LinuxEditor: + // ~/.config/unity3d/Editor.log (đường dẫn phổ biến cho Editor) + string homeLinux = Environment.GetFolderPath(Environment.SpecialFolder.Personal); + return Path.Combine(homeLinux, ".config", "unity3d", "Editor.log"); + + default: + return null; + } + } +} +#endif diff --git a/Assets/Editor/EditorLogTools.cs.meta b/Assets/Editor/EditorLogTools.cs.meta new file mode 100644 index 0000000000..abd6a5e3f2 --- /dev/null +++ b/Assets/Editor/EditorLogTools.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b640a9ed9ecce724cb2cd5891d01b4ff \ No newline at end of file diff --git a/Assets/Joystick Pack/Scripts/Base/Joystick.cs b/Assets/Joystick Pack/Scripts/Base/Joystick.cs index c332b26d44..f592403968 100644 --- a/Assets/Joystick Pack/Scripts/Base/Joystick.cs +++ b/Assets/Joystick Pack/Scripts/Base/Joystick.cs @@ -1,10 +1,13 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class Joystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler { + public event Action OnPointUp; + public float Horizontal { get { return (snapX) ? SnapFloat(input.x, AxisOptions.Horizontal) : input.x; } } public float Vertical { get { return (snapY) ? SnapFloat(input.y, AxisOptions.Vertical) : input.y; } } public Vector2 Direction { get { return new Vector2(Horizontal, Vertical); } } @@ -133,6 +136,8 @@ public class Joystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPoint { input = Vector2.zero; handle.anchoredPosition = Vector2.zero; + + OnPointUp?.Invoke(); } protected Vector2 ScreenPointToAnchoredPosition(Vector2 screenPosition) diff --git a/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll b/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll index 12a503363f..a8c3896e21 100644 Binary files a/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll and b/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll differ diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs new file mode 100644 index 0000000000..edf7b5a694 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs @@ -0,0 +1,40 @@ +using BrewMonster; +using CSNetwork; +using CSNetwork.GPDataType; +using System; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace PerfectWorld.Scripts.Managers +{ + namespace BrewMonster.Managers + { + public class EC_HostPlayer : IMsgHandler + { + public int HandlerId => (int)MANAGER_INDEX.MAN_PLAYER; + public bool ProcessMessage(ECMSG Msg) + { + switch ((int)Msg.dwMsg) + { + case int value when value == EC_MsgDef.MSG_HST_IVTRINFO: + { + OnMsgHstIvtrInfo(Msg); + break; + } + } + return true; + } + public void OnMsgHstIvtrInfo(ECMSG Msg) + { + switch (Convert.ToInt32(Msg.dwParam2)) + { + case CommandID.OWN_IVTR_DATA: + { + Debug.Log("Chay OWN_IVTR_DATA"); + break; + } + } + } + } + } +} \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs.meta new file mode 100644 index 0000000000..fd6314db24 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HostPlayer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: eece34ce0cfd6bc409982ce9b90b263b \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs index e309719bb2..dafdf4811c 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs @@ -29,6 +29,7 @@ namespace PerfectWorld.Scripts.Managers if (Msg.iSubID == 0) { Debug.LogWarning("HoangDev : EC_ManPlayerEC_ManPlayerEC_ManPlayer"); + if (GameController.Instance == null) return true; GameController.Instance.GetHostPlayer().ProcessMessage(Msg); } else if (Msg.iSubID < 0) @@ -37,6 +38,7 @@ namespace PerfectWorld.Scripts.Managers { case int value when value == EC_MsgDef.MSG_PM_PLAYERINFO: { + Debug.Log(" EC_MsgDef.MSG_PM_PLAYERINFO"); OnMsgPlayerInfo(Msg); break; } @@ -88,6 +90,7 @@ namespace PerfectWorld.Scripts.Managers break; } case CommandID.SELF_INFO_1: + Debug.Log("SELF_INFO_1"); cmd_self_info_1 info = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); HostPlayerInfo1(info); break; @@ -223,9 +226,9 @@ namespace PerfectWorld.Scripts.Managers public bool HostPlayerInfo1(cmd_self_info_1 info) { + Debug.Log("HostPlayerInfo1"); bool isDoneWorldRender = false; bool isDoneNPCRender = false; - Debug.Log("HostPlayerInfo1HostPlayerInfo1"); Action actLoadChar = () => { if (!isDoneNPCRender || !isDoneWorldRender) diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs index 57bc9655ac..e15719b626 100644 --- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs @@ -70,7 +70,17 @@ namespace BrewMonster.Network Instance._gameSession.LoginAsync(username, password, onLoginComplete); } - + public void c2s_SendCmdStopMove(in Vector3 vDest, float fSpeed, int iMoveMode, + byte byDir, ushort wStamp, int iTime) + { + Debug.LogWarning("HoangDev : c2s_SendCmdStopMove"); + Instance._gameSession.c2s_SendCmdStopMove(EC_Utility.ToNumerics( vDest),fSpeed,iMoveMode,byDir,wStamp,iTime); + } + public void c2s_CmdPlayerMove(in Vector3 vCurPos, in Vector3 vDest, + int iTime, float fSpeed, int iMoveMode, ushort wStamp) + { + Instance._gameSession.c2s_CmdPlayerMove(EC_Utility.ToNumerics(vCurPos),EC_Utility.ToNumerics( vDest),iTime,fSpeed,iMoveMode,wStamp); + } protected override void Initialize() { BaseSecurity.Initizalize(); @@ -102,6 +112,16 @@ namespace BrewMonster.Network { Instance._gameSession.SelectRoleAsync(roleInfo, callback); } + public static void EnterWorldAsync(RoleInfo roleInfo, Action callback = null) + { + Debug.Log("EnterWorldAsync !!!!! nay "); + Instance._gameSession.EnterWorldAsync(roleInfo, callback); + } + + public static void RequestInventoryAsync(Action callback = null) + { + Instance._gameSession.RequestInventoryAsync(callback); + } public void LoadScene(string sceneName, LoadSceneMode mode, Action actDone) { diff --git a/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs b/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs index 7daba2cdb2..32a89a0fa6 100644 --- a/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs +++ b/Assets/PerfectWorld/Scripts/UI/Login/LoginScreenUI.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading.Tasks; using BrewMonster.Network; using CSNetwork.Protocols; using CSNetwork.Protocols.RPCData; @@ -82,8 +83,6 @@ namespace BrewMonster.UI private void OnSelectRoleComplete(RoleInfo roleInfo) { - Logger.Log($"OnSelectRoleComplete {roleInfo.name} - {roleInfo.roleid}"); - // now we have to enter the world UnityGameSession.SendProtocol( new enterworld() @@ -97,8 +96,24 @@ namespace BrewMonster.UI Timeout = 0 } ); + /* Debug.Log("OnSelectRoleComplete"); + UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);*/ } + private async void OnEnterWorldComplete() + { + Debug.Log("OnEnterWorldDelay"); + + await Task.Delay(2000); + Logger.Log("Entered world successfully."); + UnityGameSession.RequestInventoryAsync(() => { Logger.Log("Sent Inventory Detail Request"); }); + } + + //private void OnInventoryReceived(List inventoryData) + //{ + // _inventoryUI.DisplayInventory(inventoryData); + //} + #if UNITY_EDITOR private void OnValidate() { diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 1972c140e7..e98b7c5d12 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -1,7 +1,6 @@ using BrewMonster.Network; using CSNetwork; using CSNetwork.GPDataType; -using CSNetwork.C2SCommand; using CSNetwork.Protocols; using CSNetwork.Protocols.RPCData; using System; @@ -13,8 +12,10 @@ using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using UnityEngine.UI; using Scene = UnityEngine.SceneManagement.Scene; +using System.Runtime.InteropServices; +using static UnityEngine.InputManagerEntry; +using Unity.VisualScripting; using PerfectWorld.Scripts.Managers; -using System.Collections; public class CECHostPlayer : MonoBehaviour { @@ -26,8 +27,9 @@ public class CECHostPlayer : MonoBehaviour [SerializeField] private Button btnRun; [SerializeField] private Transform parentModel; - PlayerStateMachine playerStateMachine; - PlayerMoveState moveState; + PlayerStateMachine _playerStateMachine; + PlayerMoveState _moveState; + PlayerIdleState _idleState; CECHostMove m_MoveCtrl; float playerSpeed = 5.0f; @@ -57,8 +59,9 @@ public class CECHostPlayer : MonoBehaviour private void Awake() { - moveState = new PlayerMoveState(this); - playerStateMachine = new PlayerStateMachine(); + _moveState = new PlayerMoveState(this); + _idleState = new PlayerIdleState(this); + _playerStateMachine = new PlayerStateMachine(); m_MoveCtrl = new CECHostMove(this); // Cache: không bắt buộc, nhưng gọn tay và ít gọi property lặp. @@ -69,12 +72,11 @@ public class CECHostPlayer : MonoBehaviour } } - public IEnumerator SetModelHostPlayer() + + public void SetModelHostPlayer() { - Scene scene = SceneManager.GetSceneByName("WorldRender"); - //SceneManager.MoveGameObjectToScene(gameObject, scene); - yield return new WaitUntil(()=> NPCManager.Instance != null); modle = NPCManager.Instance.GetModelPlayer(); + Scene scene = SceneManager.GetSceneByName("WorldRender"); SceneManager.MoveGameObjectToScene(modle, scene); modle.transform.SetParent(parentModel); modle.transform.localPosition = Vector3.zero; @@ -82,19 +84,23 @@ public class CECHostPlayer : MonoBehaviour } private void Start() { - playerStateMachine.InitState(moveState); + _playerStateMachine.InitState(_moveState); // btnJump.onClick.AddListener(HandleJump); } private void Update() { - m_MoveCtrl.Tick(Time.deltaTime); + Debug.Log($"(ulong)Time.deltaTime * 1000 {(ulong)(Time.deltaTime * 1000)}"); + m_MoveCtrl.Tick((ulong)(Time.deltaTime * 1000)); // Nếu có thay đổi runtime, có thể lấy lại mỗi vài giây/Start nếu bạn thích: // ccRadius = controller.radius; ccSkin = controller.skinWidth; - playerStateMachine.UpdateState(); + _playerStateMachine.UpdateState(); + } + public void StopMovement() + { + m_MoveCtrl.SendStopMoveCmd(transform.position, 5f, (int)MoveMode.GP_MOVE_WALK); } - public void HandleMovement() { // 1) Kiểm tra grounded bằng SphereCast ngắn dựa trên radius + skinWidth @@ -128,9 +134,14 @@ public class CECHostPlayer : MonoBehaviour transform.forward = move; Debug.LogWarning("HoangDev :HandleMovement"); m_MoveCtrl.GroundMove(Time.deltaTime); - m_MoveCtrl.SendMoveCmd(transform.position, controller.velocity, (int)MoveMode.GP_MOVE_WALK); + m_MoveCtrl.SendMoveCmd(transform.position, controller.velocity, (int)MoveMode.GP_MOVE_RUN); } else + { + //_playerStateMachine.ChangeState(_idleState); + } + + if (joystick) { } @@ -138,6 +149,10 @@ public class CECHostPlayer : MonoBehaviour Vector3 finalMove = (move * playerSpeed) + (playerVelocity.y * Vector3.up); controller.Move(finalMove * Time.deltaTime); } + private void JoystickRelease() + { + StopMovement(); + } private bool GroundCheck(out RaycastHit hit) { @@ -186,20 +201,125 @@ public class CECHostPlayer : MonoBehaviour } public void ProcessMessage(in ECMSG Msg) { + Debug.LogWarning("HoangDev : ProcessMessageProcessMessageProcessMessage"); switch ((int)Msg.dwMsg) { case int value when value == EC_MsgDef.MSG_HST_CORRECTPOS: OnMsgHstCorrectPos(Msg); break; + case int value when value == EC_MsgDef.MSG_HST_GOTO: OnMsgHstGoto(Msg); break; + case int value when value == EC_MsgDef.MSG_HST_IVTRINFO: + { + OnMsgHstIvtrInfo(Msg); + break; + } + } + } + public void OnMsgHstIvtrInfo(ECMSG Msg) + { + var data = Msg.dwParam1 as byte[]; + int cmd = Convert.ToInt32(Msg.dwParam2); + int hostId = Convert.ToInt32(Msg.dwParam3); + + switch (cmd) + { + case CommandID.OWN_IVTR_DATA: + { + Debug.Log("[Inventory] OWN_IVTR_DATA received"); + LogInventoryPacket("OWN_IVTR_DATA", data, hostId); + break; + } + case CommandID.OWN_IVTR_DETAIL_DATA: + { + Debug.Log("[Inventory] OWN_IVTR_DETAIL_DATA received"); + LogInventoryPacket("OWN_IVTR_DETAIL_DATA", data, hostId); + break; + } + case CommandID.GET_OWN_MONEY: + { + Debug.Log("[Inventory] GET_OWN_MONEY received"); + LogInventoryRaw("GET_OWN_MONEY", data); + break; + } + case CommandID.CHANGE_IVTR_SIZE: + { + Debug.Log("[Inventory] CHANGE_IVTR_SIZE received"); + LogInventoryRaw("CHANGE_IVTR_SIZE", data); + break; + } + default: + { + Debug.Log($"[Inventory] Unhandled inventory cmd={cmd}"); + LogInventoryRaw($"CMD_{cmd}", data); + break; + } } } - - public void OnMsgHstCorrectPos(in ECMSG Msg) { - Debug.Log("OnMsgHstCorrectPos"); - cmd_host_correct_pos pCmd = (cmd_host_correct_pos)Msg.dwParam1; - Debug.LogWarning("pCmd.pos " + pCmd.pos); + Debug.LogWarning("HoangDev : OnMsgHstCorrectPos"); + byte[] buf = (byte[])Msg.dwParam1; // chỗ bạn lưu pDataBuf + GCHandle handle = GCHandle.Alloc(buf, GCHandleType.Pinned); + cmd_host_correct_pos pCmd = (cmd_host_correct_pos)Marshal.PtrToStructure( + handle.AddrOfPinnedObject(), typeof(cmd_host_correct_pos)); + handle.Free(); + Debug.LogWarning("HoangDev :pCmd.pos " + pCmd.pos); SetPos(pCmd.pos); } + public void OnMsgHstGoto(in ECMSG Msg) + { + Debug.Log("HoangDev :OnMsgHstGoto"); + cmd_notify_hostpos pCmd = (cmd_notify_hostpos)Msg.dwParam1; + + } + + private void LogInventoryPacket(string tag, byte[] buffer, int hostId) + { + if (buffer == null) + { + Debug.LogWarning($"[Inventory] {tag}: buffer is null (hostId={hostId})"); + return; + } + + int index = 0; + if (buffer.Length < 6) + { + Debug.LogWarning($"[Inventory] {tag}: buffer too small: {buffer.Length} bytes (hostId={hostId})"); + LogInventoryRaw(tag, buffer); + return; + } + + byte byPackage = buffer[index++]; + byte ivtrSize = buffer[index++]; + uint contentLength = BitConverter.ToUInt32(buffer, index); index += 4; + + int remaining = buffer.Length - index; + int contentBytes = remaining; + if (contentLength < (uint)remaining) + { + contentBytes = (int)contentLength; + } + + Debug.Log($"[Inventory] {tag}: hostId={hostId}, totalBytes={buffer.Length}, byPackage={byPackage}, ivtrSize={ivtrSize}, contentLength={contentLength}, actualContentBytes={contentBytes}"); + + if (contentBytes > 0) + { + byte[] content = new byte[contentBytes]; + Buffer.BlockCopy(buffer, index, content, 0, contentBytes); + Debug.Log($"[Inventory] {tag}: content HEX=\n{BitConverter.ToString(content)}"); + } + + int trailing = buffer.Length - (index + contentBytes); + if (trailing > 0) + { + byte[] tail = new byte[trailing]; + Buffer.BlockCopy(buffer, index + contentBytes, tail, 0, trailing); + Debug.Log($"[Inventory] {tag}: trailing {trailing} byte(s) HEX=\n{BitConverter.ToString(tail)}"); + } + } + + private void LogInventoryRaw(string tag, byte[] buffer) + { + Debug.Log($"[Inventory] {tag}: RAW HEX (len={buffer?.Length ?? 0})=\n{(buffer == null ? "" : BitConverter.ToString(buffer))}"); + } private void SetPos(Vector3 pos) { transform.position = pos; @@ -223,9 +343,10 @@ public class CECHostPlayer : MonoBehaviour Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); if (txtName != null) txtName.text = roleName; transform.position = pos; - StartCoroutine(SetModelHostPlayer()); + SetModelHostPlayer(); Debug.LogError("Pos Character = " + pos); joystick = FindAnyObjectByType(); + joystick.OnPointUp += JoystickRelease; } public void InitCharacter(info_player_1 role) @@ -238,7 +359,7 @@ public class CECHostPlayer : MonoBehaviour Vector3 pos = new Vector3(role.pos.x, role.pos.y, role.pos.z); if (txtName != null) txtName.text = roleName; transform.position = pos; - StartCoroutine(SetModelHostPlayer()); + SetModelHostPlayer(); Debug.LogError("Pos Character = " + pos); } } diff --git a/Assets/Scripts/EC_GPDataType.cs b/Assets/Scripts/EC_GPDataType.cs index eb2c5fc390..8b43195bdb 100644 --- a/Assets/Scripts/EC_GPDataType.cs +++ b/Assets/Scripts/EC_GPDataType.cs @@ -15,25 +15,9 @@ struct cmd_host_correct_pos public Vector3 pos; public ushort stamp; }; -enum MoveMode +struct cmd_notify_hostpos { - GP_MOVE_WALK = 0, - GP_MOVE_RUN = 1, - GP_MOVE_STAND = 2, - GP_MOVE_FALL = 3, - GP_MOVE_SLIDE = 4, - GP_MOVE_PUSH = 5, // only sent to NPC - GP_MOVE_FLYFALL = 6, - GP_MOVE_RETURN = 7, - GP_MOVE_JUMP = 8, - GP_MOVE_PULL = 9, // only sent to NPC - GP_MOVE_BLINK = 10, // only sent to NPC˲ƣ - GP_MOVE_MASK = 0x0f, - - GP_MOVE_TURN = 0x10, // Turnaround - GP_MOVE_DEAD = 0x20, - - GP_MOVE_AIR = 0x40, - GP_MOVE_WATER = 0x80, - GP_MOVE_ENVMASK = 0xc0, + public Vector3 vPos; + public int tag; + public int line; }; diff --git a/Assets/Scripts/EC_Utility.cs b/Assets/Scripts/EC_Utility.cs new file mode 100644 index 0000000000..9acaef124a --- /dev/null +++ b/Assets/Scripts/EC_Utility.cs @@ -0,0 +1,37 @@ +using System; +using UnityEngine; + +public static class EC_Utility +{ + public static byte glb_CompressDirH(float x, float z) + { + const float fInvInter = 256.0f / 360.0f; + + if (Math.Abs(x) < 0.00001f) + { + if (z > 0.0f) + return 64; + else + return 192; + } + else + { + // atan2 trong C# trả về radian, cần đổi sang độ + float fDeg = (float)(Math.Atan2(z, x) * (180.0 / Math.PI)); + + // đảm bảo góc nằm trong [0, 360) + if (fDeg < 0) + fDeg += 360.0f; + + return (byte)(fDeg * fInvInter); + } + } + public static System.Numerics.Vector3 ToNumerics(this UnityEngine.Vector3 v) + { + return new System.Numerics.Vector3(v.x, v.y, v.z); + } + public static float MagnitudeH(this Vector3 v) + { + return Mathf.Sqrt(v.x * v.x + v.z * v.z); + } +} diff --git a/Assets/Scripts/EC_Utility.cs.meta b/Assets/Scripts/EC_Utility.cs.meta new file mode 100644 index 0000000000..7abe73c18c --- /dev/null +++ b/Assets/Scripts/EC_Utility.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 927789371b017f345a12f6d7adbc87ff \ No newline at end of file diff --git a/Assets/Scripts/GameController.cs b/Assets/Scripts/GameController.cs index f7c1c3935f..ad01338ecb 100644 --- a/Assets/Scripts/GameController.cs +++ b/Assets/Scripts/GameController.cs @@ -1,4 +1,3 @@ -using CSNetwork; using CSNetwork.GPDataType; using CSNetwork.Protocols.RPCData; using System.Data; @@ -21,18 +20,26 @@ public class GameController : MonoBehaviour if (instance == null) { instance = FindAnyObjectByType(); + if (instance == null) + { + var go = new GameObject("GameController"); + instance = go.AddComponent(); + DontDestroyOnLoad(go); + } } return instance; } } - - public int HandlerId => 99; - private void Awake() { if(instance == null) { instance = this; + DontDestroyOnLoad(gameObject); + } + else if(instance != this) + { + Destroy(gameObject); } } @@ -47,6 +54,11 @@ public class GameController : MonoBehaviour } public CECHostPlayer GetHostPlayer() { + if(hostPlayer == null) + { + hostPlayer = FindAnyObjectByType(); + } + Debug.Log("hostPlayer " + hostPlayer); return hostPlayer; } public void InitCharacter(cmd_self_info_1 info) @@ -78,9 +90,8 @@ public class GameController : MonoBehaviour character.InitCharacter(info); return character.gameObject; } - - public bool ProcessMessage(ECMSG Msg) + private void OnDestroy() { - throw new System.NotImplementedException(); + instance = null; } } diff --git a/Assets/Scripts/Move/CECHostMove.cs b/Assets/Scripts/Move/CECHostMove.cs index 0c6c979765..47059f7a4a 100644 --- a/Assets/Scripts/Move/CECHostMove.cs +++ b/Assets/Scripts/Move/CECHostMove.cs @@ -8,47 +8,127 @@ using System.Text; using UnityEngine; using CSNetwork.Protocols; using UnityEngine.LightTransport; +using CSNetwork; public class CECHostMove { - ushort m_wMoveStamp; + ushort m_wMoveStamp; float m_fMoveTime; CECHostPlayer m_pHost; - CECCounter m_CmdTimeCnt; bool m_bStop; const float MOVECMD_INTERVAL = .5f; Vector3 m_vLastSevPos; + STOPMOVE m_DelayedStop; + ulong cmdstopdelayCounter = 500; + ulong cmdmovedelayCounter = 500; + ulong m_dwLastTime; + Vector3 m_vLastPos; + float m_fAverSpeedH; + public CECHostMove(CECHostPlayer pHost) { m_wMoveStamp = 0; m_fMoveTime = 0.0f; m_pHost = pHost; - m_bStop = true; - m_CmdTimeCnt = new CECCounter(); - m_CmdTimeCnt.SetPeriod(MOVECMD_INTERVAL); + m_bStop = false; } - public void Tick(float dwDeltaTime) + + public void Tick(ulong dwDeltaTime) { - m_CmdTimeCnt.IncCounter(dwDeltaTime); + cmdstopdelayCounter += dwDeltaTime; + cmdmovedelayCounter += dwDeltaTime; + if (cmdstopdelayCounter >= 500 && m_DelayedStop.bValid) + { + var m = m_DelayedStop; + + // a_GetTime() -> Environment.TickCount (ms) + ulong dwCurrent = (ulong)Mathf.RoundToInt( Time.time * 1000); + + // iTime: thời gian tích lũy (ms) + delta từ timestamp đến hiện tại + int iTime = (int)((m.fTime * 1000f) + + ((dwCurrent > m.dwTimeStamp) ? (dwCurrent - m.dwTimeStamp) : 0)); + + // tính tốc độ trung bình (giây = iTime * 0.001f) + float fSpeed = l_CalcAverageSpeed(m_vLastSevPos, m.vPos, iTime * 0.001f, m.fSpeed); + + int iMoveMode = m.iMoveMode; + + // make a potential check with tuojigua + iMoveMode |= (int)MoveMode.GP_MOVE_DEAD; + + UnityGameSession.Instance.c2s_SendCmdStopMove( + m.vPos, fSpeed, iMoveMode, m.byDir, m_wMoveStamp++, iTime + ); + + // Record this position + m_vLastSevPos = m.vPos; + + Reset(); + } + + m_dwLastTime = Math.Max(m_dwLastTime, 1); + Vector3 vOffset = m_pHost.transform.position - m_vLastPos; + m_fAverSpeedH = EC_Utility.MagnitudeH(vOffset) * 1000.0f / m_dwLastTime; + m_vLastPos = m_pHost.transform.position; + m_dwLastTime = dwDeltaTime; + } + public void SendStopMoveCmd(in Vector3 vPos, float fSpeed, int iMoveMode) + { + Debug.LogWarning("HoangDev : SendStopMoveCmd"); + iMoveMode |= (int)MoveMode.GP_MOVE_DEAD; + + if (cmdstopdelayCounter == 500) + { + Vector3 vDir = m_pHost.transform.forward; + byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z); + fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vPos, m_fMoveTime, fSpeed); + int iTime = (int)(m_fMoveTime * 1000); + + UnityGameSession.Instance.c2s_SendCmdStopMove(vPos, fSpeed, iMoveMode, byDir, m_wMoveStamp++, iTime); + + m_vLastSevPos = vPos; + Reset(); + } + else + { + Vector3 vDir = m_pHost.transform.forward; + byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z); + + if (!m_DelayedStop.bValid) + { + m_DelayedStop.dwTimeStamp = (ulong)Mathf.RoundToInt(Time.time * 1000); + m_DelayedStop.fTime = m_fMoveTime; + } + + m_DelayedStop.bValid = true; + m_DelayedStop.byDir = byDir; + m_DelayedStop.vPos = vPos; + m_DelayedStop.iMoveMode = iMoveMode; + m_DelayedStop.fSpeed = fSpeed; + } + m_fMoveTime = 0.0f; } public void SendMoveCmd(in Vector3 vCurPos, in Vector3 vVel, int iMoveMode, bool bForceSend = false) { Vector3 vMoveDir = vVel; float fSpeed = vMoveDir.magnitude; - SendMoveCmd(vCurPos, fSpeed, iMoveMode, bForceSend); + SendMoveCmd(vCurPos, fSpeed, iMoveMode, bForceSend); } void SendMoveCmd(in Vector3 vCurPos, float fSpeed, int iMoveMode, bool bForceSend) { + Debug.LogWarning($"cmdmovedelayCounter 1 = {cmdmovedelayCounter}"); + if (m_bStop) { + Debug.LogWarning($"cmdmovedelayCounter 2 = {(ulong)m_fMoveTime * 1000}"); // m_CmdTimeCnt.Reset(); - m_CmdTimeCnt.SetCounter((m_fMoveTime * 1000)); + cmdmovedelayCounter = (ulong)( m_fMoveTime * 1000); m_bStop = false; } - - if (!bForceSend && !m_CmdTimeCnt.IsFull()) + Debug.LogWarning($"cmdmovedelayCounter = {cmdmovedelayCounter}"); + if (!bForceSend && cmdmovedelayCounter < 500) return; int iTime = (int)(m_fMoveTime * 1000); @@ -58,38 +138,63 @@ public class CECHostMove if (iTime == 0 || !bForceSend) { // if time is too little, wait again - m_CmdTimeCnt.SetCounter(iTime); + cmdmovedelayCounter = (ulong)(iTime); return; } } - m_CmdTimeCnt.Reset(); + cmdmovedelayCounter = 0; + m_DelayedStop.bValid = false; - c2s_CmdPlayerMove(vCurPos, vCurPos, iTime/* MOVECMD_INTERVAL */, fSpeed, iMoveMode, m_wMoveStamp++); + fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vCurPos, m_fMoveTime, fSpeed); + m_fMoveTime = 0.0f; + + iMoveMode |= (int)MoveMode.GP_MOVE_DEAD; + Debug.LogWarning("nityGameSession.Instance.c2s_CmdPlayerMove"); + UnityGameSession.Instance.c2s_CmdPlayerMove(vCurPos, vCurPos, iTime/* MOVECMD_INTERVAL */, fSpeed, iMoveMode, m_wMoveStamp++); m_vLastSevPos = vCurPos; } + + float l_CalcAverageSpeed(in Vector3 p1, in Vector3 p2, float fTime, float fDefSpeed) + { + if (Mathf.Approximately(fTime, 0f)) + return fDefSpeed; + + Vector3 d = p2 - p1; + float fSpeed = d.magnitude / fTime; + + if (fTime < 0.05f || fSpeed > 50.0f) + { + // tương đương ASSERT(0) trong C++, ở đây có thể Debug.LogWarning + Debug.LogWarning("CalcAverageSpeed: invalid input, fallback to default speed."); + return fDefSpeed; + } + + return fSpeed; + } private void Reset() { + cmdstopdelayCounter = 0; m_bStop = true; + m_DelayedStop.bValid = false; } - private void c2s_CmdPlayerMove(in Vector3 vCurPos, in Vector3 vDest, - int iTime, float fSpeed, int iMoveMode, ushort wStamp) - { - gamedatasend gamedatasend = new gamedatasend(); - //TODO: tim cach convert vector 3 unity sang System.Numerics.Vector3 - Debug.LogWarning("vCurPos " + vCurPos); - gamedatasend.Data = C2SCommandFactory.CreatePlayerMove(ToSysVec3(vCurPos), ToSysVec3(vDest), (ushort)iTime, (short)fSpeed, (byte)iMoveMode, wStamp); - UnityGameSession.SendProtocol(gamedatasend); - Debug.LogWarning("HoangDev : SendProtocolSendProtocolSendProtocol"); - } public void GroundMove(float ftime) { m_fMoveTime += ftime; } - public System.Numerics.Vector3 ToSysVec3(UnityEngine.Vector3 v) - => new System.Numerics.Vector3(v.x, v.y, v.z); + + struct STOPMOVE + { + public bool bValid; // Valid flag + public Vector3 vPos; + public float fSpeed; + public int iMoveMode; + public byte byDir; + public ulong dwTimeStamp; + public float fTime; + }; } public struct CDR_INFO { @@ -123,4 +228,4 @@ public struct CDR_INFO //the moving dist public float fMoveDist; -}; \ No newline at end of file +}; diff --git a/Assets/Scripts/PlayerState/PlayerIdleState.cs b/Assets/Scripts/PlayerState/PlayerIdleState.cs new file mode 100644 index 0000000000..f62768c933 --- /dev/null +++ b/Assets/Scripts/PlayerState/PlayerIdleState.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +public class PlayerIdleState : PlayerState +{ + public PlayerIdleState(CECHostPlayer characterCtrl) : base(characterCtrl) + { + } + + public override void Enter() + { + + } + + public override void Exit() + { + + } + + public override void Update() + { + + } +} diff --git a/Assets/Scripts/PlayerState/PlayerIdleState.cs.meta b/Assets/Scripts/PlayerState/PlayerIdleState.cs.meta new file mode 100644 index 0000000000..7941cfe01f --- /dev/null +++ b/Assets/Scripts/PlayerState/PlayerIdleState.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 89482cfe1c5315b4d833133e919eac40 \ No newline at end of file diff --git a/Assets/Scripts/PlayerState/PlayerMoveState.cs b/Assets/Scripts/PlayerState/PlayerMoveState.cs index d284e874e7..d884b4cce0 100644 --- a/Assets/Scripts/PlayerState/PlayerMoveState.cs +++ b/Assets/Scripts/PlayerState/PlayerMoveState.cs @@ -13,11 +13,12 @@ public class PlayerMoveState : PlayerState public override void Exit() { - + _characterCtrl.StopMovement(); } public override void Update() { _characterCtrl.HandleMovement(); } + } diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset deleted file mode 100644 index 3d9bb9e553..0000000000 --- a/ProjectSettings/EditorBuildSettings.asset +++ /dev/null @@ -1,25 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1045 &1 -EditorBuildSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Scenes: - - enabled: 1 - path: Assets/PerfectWorld/Scene/Boostrap.unity - guid: 40f9b53766c74f541b85df4d35cfc767 - - enabled: 1 - path: Assets/PerfectWorld/Scene/LoginScene.unity - guid: 48fc9d6a0ce7ade4ba2075f927f8e305 - - enabled: 1 - path: Assets/Scenes/NPCRender.unity - guid: a104c7e42c2924c12843255c6bab3a8b - - enabled: 1 - path: Assets/Scenes/WorldRender.unity - guid: 6d5fa77a0ed1542c8a76520fd198c7f1 - - enabled: 1 - path: Assets/Scenes/HoangTest.unity - guid: 9172bad49fed35e46819504e93c44a84 - m_configObjects: - com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 052faaac586de48259a63d0c4782560b, type: 3} - m_UseUCBPForAssetBundles: 0