281 lines
11 KiB
C#
281 lines
11 KiB
C#
using BrewMonster.Network;
|
|
using BrewMonster.Scripts;
|
|
using BrewMonster.UI;
|
|
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<cmd_host_correct_pos>((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<cmd_set_move_stamp>((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<cmd_notify_hostpos>(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 = CECUIManager.Instance.GetInGameUIMan();
|
|
|
|
if (Convert.ToInt32(Msg.dwParam2) == CommandID.ACTIVATE_WAYPOINT)
|
|
{
|
|
cmd_activate_waypoint pCmd = GPDataTypeHelper.FromBytes<cmd_activate_waypoint>((byte[])Msg.dwParam1);
|
|
m_aWayPoints.Add(pCmd.waypoint);
|
|
|
|
// add to waypoints array
|
|
// pGameUI.GetMapDlgsMgr().UpdateWayPoints(&pCmd.waypoint, 1, false);
|
|
}
|
|
else if (Convert.ToInt32(Msg.dwParam2) == CommandID.WAYPOINT_LIST)
|
|
{
|
|
cmd_waypoint_list pCmd = new cmd_waypoint_list();
|
|
pCmd.FromBytes((byte[])Msg.dwParam1);
|
|
|
|
for (int i=0; i < pCmd.count; i++)
|
|
m_aWayPoints.Add(pCmd.list[i]);
|
|
|
|
// update the whole list
|
|
pGameUI.GetMapDlgsMgr().UpdateWayPoints(pCmd.list, pCmd.count, true);
|
|
}
|
|
}
|
|
|
|
private void OnMsgHstPressCancel(ECMSG Msg)
|
|
{
|
|
CECHPWork pCurWork = null;
|
|
pCurWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_TRACEOBJECT);
|
|
if (pCurWork is CECHPWorkTrace workTrace)
|
|
{
|
|
workTrace.PressCancel();
|
|
return;
|
|
}
|
|
|
|
pCurWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_HACKOBJECT);
|
|
if (pCurWork != null)
|
|
{
|
|
UnityGameSession.c2s_CmdCancelAction();
|
|
return;
|
|
}
|
|
|
|
pCurWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_USEITEM);
|
|
if (pCurWork != null)
|
|
{
|
|
UnityGameSession.c2s_CmdCancelAction();
|
|
return;
|
|
}
|
|
|
|
pCurWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_SPELLOBJECT);
|
|
if (pCurWork != null)
|
|
{
|
|
int iState = ((CECHPWorkSpell)pCurWork).GetState();
|
|
if (iState == CECHPWorkSpell.Spell_magic_state.ST_INCANT)
|
|
{
|
|
UnityGameSession.c2s_CmdCancelAction();
|
|
return;
|
|
}
|
|
}
|
|
|
|
pCurWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_PICKUP);
|
|
if (pCurWork != null)
|
|
{
|
|
if (((EC_HPWorkPick)pCurWork).IsGather())
|
|
{
|
|
UnityGameSession.c2s_CmdCancelAction();
|
|
return;
|
|
}
|
|
}
|
|
//todo: handle this part
|
|
// pCurWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_CONCENTRATE);
|
|
// if (pCurWork !=null){
|
|
// if (IsOperatingPet()){
|
|
// UnityGameSession.c2s_CmdCancelAction();
|
|
// return;
|
|
// }
|
|
// }
|
|
// pCurWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_CONGREGATE);
|
|
// if (pCurWork !=null){
|
|
// if (IsCongregating()){
|
|
// UnityGameSession.c2s_CmdCancelAction();
|
|
// return;
|
|
// }
|
|
// }
|
|
|
|
if (m_bUsingTrashBox || DoingSessionPose())
|
|
{
|
|
UnityGameSession.c2s_CmdCancelAction();
|
|
return;
|
|
}
|
|
|
|
// Cancel current selection
|
|
if (m_idSelTarget > 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));
|
|
isLitToReady = false;
|
|
isTerrainToReady = false;
|
|
// Update camera if available
|
|
// 如果可用则更新相机
|
|
// UpdateFollowCamera(false, 10); // Uncomment if UpdateFollowCamera method exists
|
|
// Streaming anchor follows navigate clone when force-navigate is active (LitModelHolder.UpdateStreamingAnchorPosition).
|
|
// 强制导航时流式锚点跟随导航克隆(LitModelHolder.UpdateStreamingAnchorPosition)。
|
|
LitModelHolder.Instance.LoadAllObjectsNearTargetPosition(default, useHostPlayerPosition: true).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;
|
|
}
|
|
}
|
|
}
|