using BrewMonster.Network; using CSNetwork; using CSNetwork.C2SCommand; using CSNetwork.GPDataType; using CSNetwork.Protocols; using System; using System.Collections.Generic; using System.Runtime.ConstrainedExecution; using System.Security.Cryptography; using System.Text; using UnityEngine; public class CECHostMove { ushort m_wMoveStamp; float m_fMoveTime; CECHostPlayer m_pHost; 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; int m_iBlockedCnt; // Move blocked counter bool m_bSlideLock; // Locked when slide float m_fBlockTime; // Block time counter float m_fBlockMove; // Block move counter A3DVECTOR3 m_vBlockMove; bool m_bLocalMove; // true, Moving info isn't sent to server public CECHostMove(CECHostPlayer pHost) { m_wMoveStamp = 0; m_fMoveTime = 0.0f; m_pHost = pHost; m_bStop = false; } public void Tick(ulong 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)GPMoveMode.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() { int iMoveMode = (int)GPMoveMode.GP_MOVE_RUN; float fSpeed = 0f; switch (m_pHost.GetMoveEnv()) { case EC_Player.Move_environment.MOVEENV_AIR: iMoveMode |= (int)GPMoveMode.GP_MOVE_AIR; fSpeed = m_pHost.GetFlySpeed(); break; //case EC_Player.Move_environment.MOVEENV_WATER: // iMoveMode |= (int)GPMoveMode.GP_MOVE_WATER; // fSpeed = m_pHost.GetSwimSpeedSev(); // break; default: fSpeed = m_pHost.GetGroundSpeed(); break; } SendStopMoveCmd(EC_Utility.ToVector3(m_pHost.GetPos()), fSpeed, iMoveMode); } public void SendStopMoveCmd(in Vector3 vPos, float fSpeed, int iMoveMode) { Debug.LogWarning("HoangDev : SendStopMoveCmd"); iMoveMode |= (int)GPMoveMode.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); } public void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, A3DVECTOR3 vVel, int iMoveMode, bool bForceSend = false) { A3DVECTOR3 vMoveDir = vVel; float fSpeed = vMoveDir.Normalize(); SendMoveCmd(vCurPos, iDestType, vDest, vMoveDir, fSpeed, iMoveMode, bForceSend); } void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, A3DVECTOR3 vMoveDir, float fSpeed, int iMoveMode, bool bForceSend) { Vector3 pos = new Vector3(vCurPos.x, vCurPos.y, vCurPos.z); SendMoveCmd(pos, fSpeed, iMoveMode, bForceSend); } void SendMoveCmd(in Vector3 vCurPos, float fSpeed, int iMoveMode, bool bForceSend) { if (m_bStop) { // m_CmdTimeCnt.Reset(); cmdmovedelayCounter = (ulong)(m_fMoveTime * 1000); m_bStop = false; } if (!bForceSend && cmdmovedelayCounter < 500) return; int iTime = (int)(m_fMoveTime * 1000); if (iTime < 200) { if (iTime == 0 || !bForceSend) { // if time is too little, wait again cmdmovedelayCounter = (ulong)(iTime); return; } } cmdmovedelayCounter = 0; m_DelayedStop.bValid = false; fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vCurPos, m_fMoveTime, fSpeed); m_fMoveTime = 0.0f; iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD; 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; } public void GroundMove(float ftime) { m_fMoveTime += ftime; } 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; }; // Check whether host meet a slope // vMoveDirH: normalized horizontal moving direction // fMaxSpeed (out): maximum vertical speed public bool MeetSlope(A3DVECTOR3 vMoveDirH, float fMaxSpeedV) { A3DVECTOR3 vTangent = m_pHost.m_GndInfo.vGndNormal; float d = vTangent.MagnitudeH(); float tan = d / (float)Math.Abs(vTangent.y); float max = m_pHost.GetGroundSpeed() * tan * 0.96f; // Prevent max is too small, tan60 = 1.732 EC_Utility.a_ClampFloor(max, m_pHost.GetGroundSpeed() * 1.732f); fMaxSpeedV = EC_Utility.a_Min(max, 19.5f); // fMaxSpeedV = 100.0f; vTangent.y = 0.0f; vTangent.Normalize(); if (A3DVECTOR3.DotProduct(vMoveDirH, vTangent) <= -0.85f) return true; return false; } public A3DVECTOR3 GroundMove(A3DVECTOR3 vDirH, float fSpeedH, float fTime, float fSpeedV = 0f, float fGravity = 9.8f) { A3DVECTOR3 vRealDirH = vDirH; if (Math.Abs(vRealDirH.y) > 0.0001) { vRealDirH.y = 0.0f; vRealDirH.Normalize(); } // OnGroundMove only accept positive speed value if (fSpeedH < 0.0f) { vRealDirH = -vDirH; fSpeedH = -fSpeedH; } //int idInst = g_pGame.GetGameRun().GetWorld().GetInstanceID(); //CECInstance pInstance = g_pGame.GetGameRun().GetInstance(idInst); //if (pInstance.GetLimitJump()) fGravity *= 4.0f; CDR_INFO cdr = m_pHost.m_CDRInfo; var pos = m_pHost.m_aabbServer.Center; cdr.vCenter = new Vector3(pos.x, pos.y, pos.z); cdr.vXOZVelDir = new Vector3(vRealDirH.x, vRealDirH.y, vRealDirH.z); cdr.fSpeed = fSpeedH; cdr.t = fTime; cdr.fGravityAccel = fGravity; cdr.fYVel += fSpeedV; EC_CDR.OnGroundMove(ref cdr); //if (g_pGame.GetGameRun().GetWorld().GetAssureMove()) // g_pGame.GetGameRun().GetWorld().GetAssureMove().AssureMove(m_pHost.m_aabbServer.Center, cdr.vCenter); if (cdr.vTPNormal != Vector3.zero) m_pHost.SetGroundNormal(new A3DVECTOR3(cdr.vTPNormal.x, cdr.vTPNormal.y, cdr.vTPNormal.z)); else m_pHost.SetGroundNormal(GPDataTypeHelper.g_vAxisY); A3DVECTOR3 vNewPos = new A3DVECTOR3(cdr.vCenter.x, cdr.vCenter.y, cdr.vCenter.z) - GPDataTypeHelper.g_vAxisY * m_pHost.m_aabbServer.Extents.y; m_iBlockedCnt = 0; m_fBlockMove += (vNewPos - m_pHost.GetPos()).Magnitude(); m_vBlockMove += vNewPos - m_pHost.GetPos(); if ((m_fBlockTime += fTime) >= 1.0f) { if (m_fBlockMove < GPDataTypeHelper.MIN_MOVELEN_ON_GROUND || m_vBlockMove.Magnitude() < GPDataTypeHelper.MIN_MOVELEN_FOR_DETECT_VIBRATION) { m_iBlockedCnt = 5; } m_fBlockTime = 0.0f; m_fBlockMove = 0.0f; m_vBlockMove.Clear(); } m_fMoveTime += fTime; return vNewPos; } public int MoveBlocked() { return m_iBlockedCnt; } public void SetSlideLock(bool bLock) { m_bSlideLock = bLock; } } public struct CDR_INFO { //the aabb public Vector3 vCenter; //@note : the caller should make sure ext(.x, .y, .z) > 0. By Kuiwu[22/9/2005] public Vector3 vExtent; public float fStepHeight; // Velocity Info public Vector3 vXOZVelDir; public float fYVel; public float fSpeed; // time span ( sec ) public float t; // Gravity acceleration public float fGravityAccel; // the Climb Slope Thresh public float fSlopeThresh; // Tangent plane Info public Vector3 vTPNormal; // Absolute Velocity: output for forcast! public Vector3 vAbsVelocity; //the moving dist public float fMoveDist; };