using BrewMonster.Network; using BrewMonster.Scripts; using CSNetwork; using CSNetwork.GPDataType; using Cysharp.Threading.Tasks; using System; using System.Runtime.InteropServices; using UnityEngine; using static BrewMonster.Scripts.CECHPWork; namespace BrewMonster { public partial class CECHostPlayer { public void OnMsgHstCorrectPos(in ECMSG Msg) { //Debug.LogError("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(); //cmd_host_correct_pos pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); Debug.LogError("HoangDev :pCmd.pos " + pCmd.pos); SetPos(pCmd.pos); m_vVelocity.Clear(); m_CDRInfo.vAbsVelocity.Clear(); m_MoveCtrl.SetMoveStamp(pCmd.stamp); } public void OnMsgHstSetMoveStamp(ECMSG Msg) { cmd_set_move_stamp pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); m_MoveCtrl.SetMoveStamp(pCmd.move_stamp); } public void OnMsgHstGoto(in ECMSG Msg) { PopupManager.NotifyPlayerRevived(); // p1 is a byte[] buffer; parse into cmd_notify_hostpos then set position // p1 是一个 byte[] 缓冲区;解析为 cmd_notify_hostpos 然后设置位置 byte[] buf = (byte[])Msg.dwParam1; cmd_notify_hostpos pCmd = GPDataTypeHelper.FromBytes(buf); int idInst = pCmd.tag; Vector3 vPos = new Vector3(pCmd.vPos.x, pCmd.vPos.y, pCmd.vPos.z); int iLine = pCmd.line; // Call Goto method to properly handle teleportation // 调用 Goto 方法来正确处理传送 if (!Goto(idInst, vPos, iLine)) { BMLogger.LogError($"OnMsgHstGoto: Failed to teleport to instance {idInst}"); return; } } void OnMsgHstWayPoint(ECMSG Msg) { //CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); //if (Convert.ToInt32(Msg.dwParam2) == CommandID.ACTIVATE_WAYPOINT) //{ // cmd_activate_waypoint pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); // m_aWayPoints.Add(pCmd.waypoint); // // add to waypoints array // pGameUI.GetMapDlgsMgr().UpdateWayPoints(&pCmd.waypoint, 1, false); // // Print a notify message // const CECMapDlgsMgr::PointMap& aWayPoints = pGameUI.GetMapDlgsMgr().GetTransPoint(); // CECMapDlgsMgr::PointMap::const_iterator itr = aWayPoints.find(pCmd.waypoint); // if(itr != aWayPoints.end()) // { // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_NEWWAYPOINT, (itr.second).strName); // bool bCanPopUITips = true; // int count = CECUIConfig::Instance().GetGameUI().GetTaskIDDisableWayPointsUITipsCount(); // // ¼ì²éÉíÉÏÊÇ·ñÓнûÖ¹µ¯³ötipsµÄÈÎÎñ // for (int i=0;i 0) { SelectTarget(0); return; } // Some work have lower priority pCurWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_MOVETOPOS); if (pCurWork != null) { ((CECHPWorkMove)pCurWork).PressCancel(); return; } } public void StopMovement() { m_MoveCtrl.SendStopMoveCmd(playerTransform.position, 5f, (int)GPMoveMode.GP_MOVE_WALK); } // Return to a target town through skill // 通过技能返回目标城镇 // This method implements the Goto logic from the original C++ code // 此方法实现了原始 C++ 代码中的 Goto 逻辑 private bool Goto(int idInst, Vector3 vPos, int iParallelWorldID) { Action actDone = () => { // Stop all current work and goto specified position // 停止所有当前工作并转到指定位置 if (m_pWorkMan != null) { // Stop auto-moving if active // 如果正在自动移动则停止 // Note: IsAutoMoving check would go here if available // 注意:如果可用,IsAutoMoving 检查将放在这里 if (IsAutoMoving()) { CECHPWorkMove pWorkMove = (m_pWorkMan.GetRunningWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS) as CECHPWorkMove); pWorkMove.SetUseAutoMoveDialog(false); pWorkMove.PressCancel(); pWorkMove.Finish(); } // Finish all work // 完成所有工作 m_pWorkMan.FinishAllWork(true); } if (!IsFlying()) ShowWing(false); // Add a little height to ensure player's AABB won't embed with building // 增加一点高度以确保玩家的 AABB 不会嵌入建筑物 vPos += EC_Utility.ToVector3(GPDataTypeHelper.g_vAxisY) * 0.1f; // Ensure we are not under ground (terrain height check would go here) // 确保我们不会在地下(地形高度检查将放在这里) // Note: Terrain height check is skipped for now as it requires world access // 注意:暂时跳过地形高度检查,因为它需要世界访问 A3DVECTOR3 vNormal = new A3DVECTOR3(); float vTerrainHeight = vPos.y; if (Physics.RaycastNonAlloc(vPos, (Vector3.down), hits, 1000f, 1 << 6) > 0) { vTerrainHeight = hits[0].point.y; vNormal = EC_Utility.ToA3DVECTOR3(hits[0].normal); } if (vPos.y < vTerrainHeight) { vPos.y = vTerrainHeight; } // Set position // 设置位置 SetPos(vPos); m_CDRInfo.vTPNormal = vPos.y <= vTerrainHeight + 0.1f ? vNormal : g_vOrigin; m_CDRInfo.fYVel = 0.0f; m_CDRInfo.vAbsVelocity.Clear(); // Reset jump state if available // 如果可用则重置跳跃状态 ResetJump(); // Uncomment if ResetJump method exists m_MoveCtrl.SetHostLastPos(EC_Utility.ToA3DVECTOR3(vPos)); m_MoveCtrl.SetLastSevPos(EC_Utility.ToA3DVECTOR3(vPos)); // Update camera if available // 如果可用则更新相机 // UpdateFollowCamera(false, 10); // Uncomment if UpdateFollowCamera method exists LitModelHolder.Instance.LoadAllObjectsNearTargetPosition(vPos).Forget(); }; // Jump to instance (change world/instance) // 跳转到实例(更改世界/实例) // Note: JumpToInstance is currently a stub in CECGameRun, so we skip the call for now // 注意:JumpToInstance 目前在 CECGameRun 中是一个存根,所以我们现在跳过调用 if (CECGameRun.Instance != null && !CECGameRun.Instance.JumpToInstance(idInst, vPos, iParallelWorldID, actDone)) { Debug.LogError($"CECHostPlayer::Goto, Failed to jump to instance {idInst}"); return false; } return true; } public void SetStatusRun(bool value) { if (!isGrounded) { Debug.LogError("Player not in ground"); return; } isRun = value; } public bool IsPlayerMoving() { return m_pWorkMan.IsMoving(); } // Is auto moving ? bool IsAutoMoving() { CECHPWork pWork = m_pWorkMan.GetRunningWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS); if (pWork != null) return (pWork as CECHPWorkMove).GetAutoMove(); else return false; } } }