Files
test/Assets/Scripts/CECHostPlayer.World.cs
2026-04-30 16:29:22 +07:00

279 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));
// 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;
}
}
}