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
+
+
+ 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