831 lines
37 KiB
C#
831 lines
37 KiB
C#
using BrewMonster;
|
|
using BrewMonster.Managers;
|
|
using BrewMonster.Network;
|
|
using BrewMonster.Scripts;
|
|
using CSNetwork;
|
|
using CSNetwork.GPDataType;
|
|
using CSNetwork.Protocols;
|
|
using CSNetwork.Protocols.RPCData;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
namespace PerfectWorld.Scripts.Managers
|
|
{
|
|
namespace BrewMonster.Managers
|
|
{
|
|
[Serializable]
|
|
public class EC_ManPlayer : IMsgHandler
|
|
{
|
|
Dictionary<int, int> m_UkPlayerTab = new Dictionary<int, int>();
|
|
Dictionary<int, EC_ElsePlayer> m_PlayerTab = new Dictionary<int, EC_ElsePlayer>();
|
|
private readonly object m_csPlayerTab = new object();
|
|
CECHostPlayer m_pHostPlayer;
|
|
public int HandlerId => (int)MANAGER_INDEX.MAN_PLAYER;
|
|
public bool ProcessMessage(ECMSG Msg)
|
|
{
|
|
if (Msg.iSubID == 0)
|
|
{
|
|
if (CECGameRun.Instance == null) return true;
|
|
if (CECGameRun.Instance.GetHostPlayer() == null) return true;
|
|
CECGameRun.Instance.GetHostPlayer().ProcessMessage(Msg);
|
|
}
|
|
else if (Msg.iSubID < 0)
|
|
{
|
|
switch ((int)Msg.dwMsg)
|
|
{
|
|
case int value when value == EC_MsgDef.MSG_PM_PLAYERINFO:
|
|
{
|
|
OnMsgPlayerInfo(Msg);
|
|
break;
|
|
}
|
|
case int value when value == EC_MsgDef.MSG_PM_PLAYERMOVE:
|
|
{
|
|
OnMsgPlayerMove(Msg);
|
|
break;
|
|
}
|
|
case int value when value == EC_MsgDef.MSG_PM_PLAYERLEVELUP:
|
|
OnMsgPlayerLevelUp(Msg);
|
|
break;
|
|
case int value when value == EC_MsgDef.MSG_PM_PLAYERSTOPMOVE:
|
|
{
|
|
OnMsgPlayerStopMove(Msg);
|
|
break;
|
|
}
|
|
case int value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO:
|
|
case int value2 when value2 == EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY:
|
|
case int value3 when value3 == EC_MsgDef.MSG_PM_PLAYERATKRESULT:
|
|
case int value4 when value4 == EC_MsgDef.MSG_PM_CASTSKILL:
|
|
case int value5 when value5 == EC_MsgDef.MSG_PM_ENCHANTRESULT:
|
|
case int value6 when value6 == EC_MsgDef.MSG_PM_PLAYERDOEMOTE:
|
|
case int value7 when value7 == EC_MsgDef.MSG_PM_PLAYERGATHER:
|
|
case int value8 when value8 == EC_MsgDef.MSG_PM_PLAYERFLY:
|
|
TransmitMessage(Msg);
|
|
break;
|
|
case int value when value == EC_MsgDef.MSG_PM_PLAYERDIED:
|
|
OnMsgPlayerDied(Msg);
|
|
break;
|
|
case int value when value == EC_MsgDef.MSG_PM_PLAYERREVIVE:
|
|
OnMsgPlayerRevive(Msg);
|
|
break;
|
|
case int value when value == EC_MsgDef.MSG_PM_PLAYERRUNOUT:
|
|
OnMsgPlayerRunOut(Msg);
|
|
break;
|
|
case EC_MsgDef.MSG_PM_PICKUPMATTER:
|
|
OnMsgPlayerPickupMatter(Msg);
|
|
break;
|
|
case EC_MsgDef.MSG_PM_PLAYEREXTPROP:
|
|
OnMsgPlayerExtProp(Msg);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void OnMsgPlayerDied(ECMSG Msg)
|
|
{
|
|
cmd_player_died pCmd = GPDataTypeHelper.FromBytes<cmd_player_died>((byte[])Msg.dwParam1);
|
|
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.idPlayer);
|
|
//if (pPlayer && !pPlayer.IsAboutToDie())
|
|
// pPlayer.Killed(pCmd.idKiller);
|
|
|
|
EventBus.PublishChannel(pPlayer.GetCharacterID(), new ClearComActFlagAllRankNodesEvent(true));
|
|
pPlayer.PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE);
|
|
}
|
|
|
|
private void OnMsgPlayerRevive(ECMSG Msg)
|
|
{
|
|
cmd_player_revive pCmd = GPDataTypeHelper.FromBytes<cmd_player_revive>((byte[])Msg.dwParam1);
|
|
CECHostPlayer pHost = GetHostPlayer();
|
|
if (pHost && pHost.GetCharacterID() == pCmd.idPlayer)
|
|
{
|
|
pHost.HandleRevive(pCmd.sReviveType, pCmd.pos);
|
|
}
|
|
else
|
|
{
|
|
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.idPlayer);
|
|
if (pPlayer)
|
|
pPlayer.HandleRevive(pCmd.sReviveType, pCmd.pos);
|
|
}
|
|
}
|
|
|
|
public void OnMsgPlayerInfo(ECMSG Msg)
|
|
{
|
|
int iHostID = Convert.ToInt32(Msg.dwParam3);
|
|
int lenghtByte = Marshal.SizeOf<int>();
|
|
byte[] byteArray = new byte[lenghtByte];
|
|
byte[] data = (byte[])Msg.dwParam1;
|
|
for (int i = 0; i < lenghtByte; i++)
|
|
{
|
|
byteArray[i] = data[i];
|
|
}
|
|
int cid = BitConverter.ToInt32(byteArray);
|
|
int commandID = Convert.ToInt32(Msg.dwParam2);
|
|
switch (commandID)
|
|
{
|
|
case CommandID.PLAYER_INFO_1:
|
|
case CommandID.PLAYER_ENTER_WORLD:
|
|
case CommandID.PLAYER_ENTER_SLICE:
|
|
{
|
|
if (cid != iHostID)
|
|
{
|
|
info_player_1 info_Player_1 = GPDataTypeHelper.FromBytes<info_player_1>((byte[])Msg.dwParam1);
|
|
ElsePlayerEnter(info_Player_1, commandID);
|
|
}
|
|
break;
|
|
}
|
|
case CommandID.SELF_INFO_1:
|
|
cmd_self_info_1 info = GPDataTypeHelper.FromBytes<cmd_self_info_1>((byte[])Msg.dwParam1);
|
|
HostPlayerInfo1(info);
|
|
break;
|
|
case CommandID.PLAYER_INFO_2: break;
|
|
case CommandID.PLAYER_INFO_3: break;
|
|
case CommandID.PLAYER_INFO_4: break;
|
|
|
|
case CommandID.PLAYER_INFO_1_LIST:
|
|
{
|
|
byte[] bytes = (byte[])Msg.dwParam1;
|
|
cmd_player_info_1_list pCmd = GPDataTypeHelper.FromBytes<cmd_player_info_1_list>(bytes);
|
|
if (pCmd.count == 0) break;
|
|
|
|
List<int> a1 = new();
|
|
List<int> a2 = new();
|
|
List<int> a3 = new();
|
|
List<int> a4 = new();
|
|
|
|
|
|
int lenght = Marshal.SizeOf<info_player_1>();
|
|
int preSize = 0;
|
|
byte[] pDataBuf = null;
|
|
preSize += Marshal.SizeOf<ushort>();
|
|
for (int i = 0; i < pCmd.count; i++)
|
|
{
|
|
pDataBuf = new byte[lenght];
|
|
for (int j = 0; j < pDataBuf.Length; j++)
|
|
{
|
|
pDataBuf[j] = bytes[preSize + j];
|
|
}
|
|
info_player_1 Info = GPDataTypeHelper.FromBytes<info_player_1>(pDataBuf);
|
|
if (Info.cid != iHostID)
|
|
{
|
|
EC_ElsePlayer pPlayer = ElsePlayerEnter(Info, commandID);
|
|
|
|
if (pPlayer != null)
|
|
{
|
|
if (!pPlayer.m_bCustomReady)
|
|
{
|
|
if (!pPlayer.m_bBaseInfoReady)
|
|
a2.Add(Info.cid);
|
|
else
|
|
a3.Add(Info.cid);
|
|
}
|
|
|
|
// Is equipment data ready
|
|
if (!pPlayer.m_bEquipReady)
|
|
a1.Add(Info.cid);
|
|
|
|
// TODO: Implement get faction
|
|
/*/
|
|
// Get faction info
|
|
if (pPlayer.GetFactionID() && !g_pGame.GetFactionMan().GetFaction(pPlayer.GetFactionID()))
|
|
{
|
|
int i(0);
|
|
for (i = 0; i < a4.GetSize(); i++)
|
|
if (a4[i] == pPlayer.GetFactionID())
|
|
break;
|
|
|
|
if (i == a4.GetSize())
|
|
a4.Add(pPlayer.GetFactionID());
|
|
}
|
|
//*/
|
|
}
|
|
}
|
|
|
|
// Calculate player info data size and skip it
|
|
int iSize = Marshal.SizeOf<info_player_1>();
|
|
if ((Info.state & PlayerNPCState.GP_STATE_ADV_MODE) != 0)
|
|
iSize += Marshal.SizeOf<int>() * 2;
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_SHAPE) != 0)
|
|
iSize += Marshal.SizeOf<byte>();
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_EMOTE) != 0)
|
|
iSize += Marshal.SizeOf<byte>();
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0)
|
|
iSize += Marshal.SizeOf<int>() * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT;
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_FACTION) != 0)
|
|
iSize += (Marshal.SizeOf<int>() + Marshal.SizeOf<byte>());
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_BOOTH) != 0)
|
|
iSize += Marshal.SizeOf<byte>();
|
|
|
|
//// Parse effect data
|
|
if ((Info.state & PlayerNPCState.GP_STATE_EFFECT) != 0)
|
|
{
|
|
iSize += Marshal.SizeOf<byte>();
|
|
byte byNum = bytes[preSize + iSize];
|
|
|
|
if (byNum > 0)
|
|
iSize += byNum * Marshal.SizeOf<short>();
|
|
}
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_PARIAH) != 0)
|
|
iSize += Marshal.SizeOf<byte>();
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_IN_MOUNT) != 0)
|
|
iSize += Marshal.SizeOf<ushort>() + Marshal.SizeOf<int>();
|
|
|
|
// Parse bind data
|
|
if ((Info.state & PlayerNPCState.GP_STATE_IN_BIND) != 0)
|
|
iSize += Marshal.SizeOf<char>() + Marshal.SizeOf<int>();
|
|
|
|
// Parse spouse data
|
|
if ((Info.state & PlayerNPCState.GP_STATE_SPOUSE) != 0)
|
|
iSize += Marshal.SizeOf<int>();
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_EQUIPDISABLED) != 0)
|
|
iSize += Marshal.SizeOf<long>();
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_PLAYERFORCE) != 0)
|
|
iSize += Marshal.SizeOf<int>();
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0)
|
|
{
|
|
int effectNum = Marshal.ReadInt32(bytes, iSize);//*(int*)(pDataBuf + iSize);
|
|
iSize += Marshal.SizeOf<int>();
|
|
|
|
if (effectNum > 0)
|
|
iSize += effectNum * (Marshal.SizeOf<int>() + Marshal.SizeOf<char>());
|
|
}
|
|
|
|
if ((Info.state & PlayerNPCState.GP_STATE_COUNTRY) != 0)
|
|
iSize += Marshal.SizeOf<int>();
|
|
if ((Info.state2 & PlayerNPCState2.GP_STATE2_TITLE) != 0)
|
|
iSize += Marshal.SizeOf<ushort>();
|
|
if ((Info.state2 & PlayerNPCState2.GP_STATE2_REINCARNATION) != 0)
|
|
iSize += Marshal.SizeOf<byte>();
|
|
if ((Info.state2 & PlayerNPCState2.GP_STATE2_REALM) != 0)
|
|
iSize += Marshal.SizeOf<byte>();
|
|
if ((Info.state2 & PlayerNPCState2.GP_STATE2_FACTION_PVP_MASK) != 0)
|
|
iSize += Marshal.SizeOf<byte>();
|
|
|
|
// Goblin refine data
|
|
if ((Info.state & PlayerNPCState.GP_STATE_GOBLINREFINE) != 0)
|
|
iSize += Marshal.SizeOf<int>();
|
|
|
|
//pDataBuf += iSize;
|
|
|
|
preSize += iSize;
|
|
}
|
|
|
|
// Get both base info and custom data
|
|
if (a2.Count > 0)
|
|
UnityGameSession.GetRoleBaseInfo(a2.Count, a2);
|
|
|
|
// Only get custom data
|
|
if (a3.Count > 0)
|
|
UnityGameSession.GetRoleCustomizeData(a3.Count, a3);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OnMsgPlayerMove(ECMSG Msg)
|
|
{
|
|
int iHostID = Convert.ToInt32(Msg.dwParam3);
|
|
cmd_object_move pCmd = GPDataTypeHelper.FromBytes<cmd_object_move>((byte[])Msg.dwParam1);
|
|
if (pCmd.use_time == 0)
|
|
return;
|
|
if (pCmd.id != iHostID)
|
|
{
|
|
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id);
|
|
if (pPlayer)
|
|
{
|
|
pPlayer.MoveTo(pCmd);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool OnMsgPlayerLevelUp(ECMSG Msg)
|
|
{
|
|
cmd_level_up pCmd = GPDataTypeHelper.FromBytes<cmd_level_up>((byte[])Msg.dwParam1);
|
|
CECHostPlayer pHost = GetHostPlayer();
|
|
if (pCmd.id == pHost.GetCharacterID())
|
|
{
|
|
pHost.LevelUp();
|
|
}
|
|
else
|
|
{
|
|
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id);
|
|
if (pPlayer)
|
|
pPlayer.LevelUp();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool HostPlayerInfo1(cmd_self_info_1 info)
|
|
{
|
|
//bool isDoneWorldRender = false;
|
|
//bool isDoneNPCRender = false;
|
|
//Action actLoadChar = () =>
|
|
//{
|
|
// if (!isDoneNPCRender || !isDoneWorldRender)
|
|
// {
|
|
// return;
|
|
// }
|
|
// GameController.Instance.InitCharacter(info);
|
|
//};
|
|
//string nameScene = "NPCRender";
|
|
//UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) =>
|
|
//{
|
|
// isDoneNPCRender = value;
|
|
// actLoadChar?.Invoke();
|
|
//});
|
|
//nameScene = "WorldRender";
|
|
//UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) =>
|
|
//{
|
|
// isDoneWorldRender = value;
|
|
// actLoadChar?.Invoke();
|
|
//});
|
|
//UnityGameSession.Instance.LoadScene("HoangTest", LoadSceneMode.Single, (value) =>
|
|
//{
|
|
// isDoneWorldRender = value;
|
|
// actLoadChar?.Invoke();
|
|
//});
|
|
CECGameRun.Instance.InitCharacter(info);
|
|
return true;
|
|
}
|
|
|
|
public EC_ElsePlayer ElsePlayerEnter(info_player_1 info, int iCmd)
|
|
{
|
|
// If this player's id is in unknown table, remove it because this player
|
|
// won't be unknown anymore
|
|
if (m_UkPlayerTab.TryGetValue(info.cid, out int value))
|
|
{
|
|
if (value != 0) // Pair.second != 0
|
|
{
|
|
m_UkPlayerTab.Remove(info.cid);
|
|
}
|
|
}
|
|
|
|
int iAppearFlag = (iCmd == (int)CommandID.PLAYER_ENTER_WORLD) ?
|
|
(int)PlayerAppearFlag.APPEAR_ENTERWORLD : (int)PlayerAppearFlag.APPEAR_RUNINTOVIEW;
|
|
|
|
// Has player been in active player table ?
|
|
EC_ElsePlayer pPlayer = GetElsePlayer(info.cid);
|
|
if (pPlayer != null)
|
|
{
|
|
// Check if the GameObject is still valid (not destroyed)
|
|
if (pPlayer.gameObject != null)
|
|
{
|
|
// This player has existed in player table, call special initial function
|
|
pPlayer.Init(info, iAppearFlag);
|
|
return pPlayer;
|
|
}
|
|
else
|
|
{
|
|
// GameObject was destroyed but entry still exists in table - clean it up
|
|
lock (m_csPlayerTab)
|
|
{
|
|
m_PlayerTab.Remove(info.cid);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create a new player
|
|
if (!(pPlayer = CreateElsePlayer(info, iAppearFlag)))
|
|
{
|
|
return null;
|
|
}
|
|
lock (m_csPlayerTab)
|
|
{
|
|
if (m_PlayerTab.ContainsKey(info.cid))
|
|
{
|
|
m_PlayerTab[info.cid] = pPlayer;
|
|
}
|
|
else
|
|
{
|
|
m_PlayerTab.Add(info.cid, pPlayer);
|
|
}
|
|
}
|
|
return pPlayer;
|
|
}
|
|
|
|
private EC_ElsePlayer CreateElsePlayer(info_player_1 info, int iAppearFlag)
|
|
{
|
|
GameObject ob = CECGameRun.Instance.InitCharacter(info);
|
|
EC_ElsePlayer elsePlayer = ob.AddComponent<EC_ElsePlayer>();
|
|
|
|
elsePlayer.Init(info, iAppearFlag);
|
|
return elsePlayer;
|
|
}
|
|
|
|
public EC_ElsePlayer GetElsePlayer(int cid, long dwBornStamp = 0)
|
|
{
|
|
lock (m_csPlayerTab)
|
|
{
|
|
if (!m_PlayerTab.TryGetValue(cid, out var player))
|
|
return null;
|
|
if (dwBornStamp != 0)
|
|
{
|
|
//TO DO: fix after GetBornStamp() is create in code
|
|
//if (player.GetBornStamp() != dwBornStamp)
|
|
return null;
|
|
}
|
|
|
|
return player;
|
|
}
|
|
}
|
|
|
|
private EC_ElsePlayer SeekOutElsePlayer(int cid)
|
|
{
|
|
if (!m_PlayerTab.TryGetValue(cid, out var player))
|
|
{
|
|
// Couldn't find this else player, put it into unknown player table
|
|
m_UkPlayerTab[cid] = cid;
|
|
return null;
|
|
}
|
|
|
|
return player;
|
|
}
|
|
|
|
|
|
public bool OnMsgPlayerStopMove(ECMSG Msg)
|
|
{
|
|
cmd_object_stop_move pCmd = GPDataTypeHelper.FromBytes<cmd_object_stop_move>((byte[])Msg.dwParam1);
|
|
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id);
|
|
if (pPlayer)
|
|
pPlayer.StopMoveTo(pCmd);
|
|
return true;
|
|
}
|
|
|
|
public bool OnMsgPlayerRunOut(ECMSG Msg)
|
|
{
|
|
int id = GPDataTypeHelper.FromBytes<int>((byte[])Msg.dwParam1);
|
|
CECHostPlayer pHost = GetHostPlayer();
|
|
if (pHost != null && id == pHost.GetCharacterID())
|
|
return true; // Don't process if it's the host player
|
|
|
|
ElsePlayerLeave(id, false);
|
|
return true;
|
|
}
|
|
|
|
public void OnMsgPlayerPickupMatter(ECMSG Msg)
|
|
{
|
|
cmd_matter_pickup pCmd = GPDataTypeHelper.FromBytes<cmd_matter_pickup>((byte[])Msg.dwParam1);
|
|
// CECHostPlayer pHost = GetHostPlayer();
|
|
|
|
|
|
EC_ManMessageMono.Instance.EC_ManMatter.RemoveMatter(pCmd.matter_id);
|
|
|
|
}
|
|
|
|
private void ElsePlayerLeave(int cid, bool bExitGame)
|
|
{
|
|
EC_ElsePlayer pPlayer = SeekOutElsePlayer(cid);
|
|
if (pPlayer == null)
|
|
return;
|
|
|
|
// Remove from active player table
|
|
lock (m_csPlayerTab)
|
|
{
|
|
m_PlayerTab.Remove(cid);
|
|
}
|
|
|
|
// If this player is selected by host, cancel the selection
|
|
CECHostPlayer pHost = GetHostPlayer();
|
|
if (pHost != null && pHost.GetSelectedTarget() == cid)
|
|
pHost.SelectTarget(0);
|
|
|
|
// Release player resource
|
|
if (pPlayer != null)
|
|
{
|
|
if (bExitGame)
|
|
{
|
|
// Player exited game - handle differently if needed
|
|
}
|
|
// Destroy the player GameObject
|
|
if (pPlayer.gameObject != null)
|
|
UnityEngine.Object.Destroy(pPlayer.gameObject);
|
|
}
|
|
}
|
|
|
|
//private cmd_object_move ConvertToStruct(byte[] bytes)
|
|
//{
|
|
// if (bytes.Length < Marshal.SizeOf<cmd_object_move>())
|
|
// {
|
|
// return default;
|
|
// }
|
|
|
|
// cmd_object_move result = new cmd_object_move();
|
|
// int preLenghtData = 0;
|
|
// int lenghtDataType = Marshal.SizeOf<int>();
|
|
// byte[] arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
|
|
// result.id = BitConverter.ToInt32(arrByteData);
|
|
|
|
// preLenghtData += lenghtDataType;
|
|
// lenghtDataType = Marshal.SizeOf<float>();
|
|
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
|
|
// result.dest_X = BitConverter.ToSingle(arrByteData);
|
|
|
|
// preLenghtData += lenghtDataType;
|
|
// lenghtDataType = Marshal.SizeOf<float>();
|
|
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
|
|
// result.dest_Y = BitConverter.ToSingle(arrByteData);
|
|
|
|
// preLenghtData += lenghtDataType;
|
|
// lenghtDataType = Marshal.SizeOf<float>();
|
|
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
|
|
// result.dest_Z = BitConverter.ToSingle(arrByteData);
|
|
|
|
// preLenghtData += lenghtDataType;
|
|
// lenghtDataType = Marshal.SizeOf<ushort>();
|
|
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
|
|
// result.use_time = BitConverter.ToUInt16(arrByteData);
|
|
|
|
// preLenghtData += lenghtDataType;
|
|
// lenghtDataType = Marshal.SizeOf<short>();
|
|
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
|
|
// result.sSpeed = BitConverter.ToInt16(arrByteData);
|
|
|
|
// preLenghtData += lenghtDataType;
|
|
// result.move_mode = bytes[preLenghtData + 1];
|
|
// return result;
|
|
//}
|
|
|
|
private byte[] GetBytes(byte[] bytes, int length, int index)
|
|
{
|
|
byte[] arrByteData = new byte[length];
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
arrByteData[i] = bytes[i + index];
|
|
}
|
|
return arrByteData;
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
|
|
}
|
|
public bool TransmitMessage(ECMSG Msg)
|
|
{
|
|
int cid = 0;
|
|
var host = CECGameRun.Instance.GetHostPlayer();
|
|
|
|
switch (Msg.dwMsg)
|
|
{
|
|
/*case long value when value == EC_MsgDef.MSG_PM_PLAYEREQUIPDATA:
|
|
if (msg.dwParam2 == S2C.EQUIP_DATA)
|
|
cid = ((cmd_equip_data)msg.dwParam1).idPlayer;
|
|
else // EQUIP_DATA_CHANGED
|
|
cid = ((cmd_equip_data_changed)msg.dwParam1).idPlayer;
|
|
break;*/
|
|
|
|
case long value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO:
|
|
cid = (int)((playerbaseinfo_re)Msg.dwParam1).Player.id;
|
|
// Xoá khỏi cache
|
|
//g_pGame.GetGameSession().GetC2SCmdCache().RemovePlayerBaseInfo(cid);
|
|
break;
|
|
|
|
/*case long value when value == EC_MsgDef.MSG_PM_PLAYERCUSTOM:
|
|
cid = ((GetCustomData_Re)msg.dwParam1).cus_roleid;
|
|
break;
|
|
|
|
case long value when value == EC_MsgDef.MSG_PM_PLAYERFLY:
|
|
if (msg.dwParam2 == S2C.OBJECT_TAKEOFF)
|
|
cid = ((cmd_object_takeoff)msg.dwParam1).object_id;
|
|
else
|
|
cid = ((cmd_object_landing)msg.dwParam1).object_id;
|
|
break;*/
|
|
case long value when value == EC_MsgDef.MSG_PM_PLAYERATKRESULT:
|
|
cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes<cmd_object_atk_result>((byte[])Msg.dwParam1);
|
|
cid = pCmdAtk.attacker_id;
|
|
break;
|
|
case long value when value == EC_MsgDef.MSG_PM_CASTSKILL:
|
|
switch (Convert.ToInt32(Msg.dwParam2))
|
|
{
|
|
case int value2 when value2 == CommandID.OBJECT_CAST_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_skill>((byte[])Msg.dwParam1)).caster; break;
|
|
case int value2 when value2 == CommandID.OBJECT_CAST_INSTANT_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_instant_skill>((byte[])Msg.dwParam1)).caster; break;
|
|
case int value2 when value2 == CommandID.OBJECT_CAST_POS_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_pos_skill>((byte[])Msg.dwParam1)).caster; break;
|
|
case int value2 when value2 == CommandID.SKILL_INTERRUPTED: cid = (GPDataTypeHelper.FromBytes<cmd_skill_interrupted>((byte[])Msg.dwParam1)).caster; break;
|
|
case int value2 when value2 == CommandID.PLAYER_CAST_RUNE_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_player_cast_rune_skill>((byte[])Msg.dwParam1)).caster; break;
|
|
case int value2 when value2 == CommandID.PLAYER_CAST_RUNE_INSTANT_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_player_cast_rune_instant_skill>((byte[])Msg.dwParam1)).caster; break;
|
|
}
|
|
break;
|
|
case long value when value == EC_MsgDef.MSG_PM_PLAYERDOEMOTE:
|
|
|
|
if (Convert.ToInt32(Msg.dwParam2) == CommandID.OBJECT_DO_EMOTE)
|
|
{
|
|
cmd_object_do_emote pCmdDoEmote = GPDataTypeHelper.FromBytes<cmd_object_do_emote>((byte[])Msg.dwParam1);
|
|
cid = pCmdDoEmote.id;
|
|
}
|
|
else // Msg.dwParam2 == OBJECT_EMOTE_RESTORE
|
|
{
|
|
// cid = ((cmd_object_emote_restore*)Msg.dwParam1)->id;
|
|
}
|
|
|
|
break;
|
|
case long value when value == EC_MsgDef.MSG_PM_ENCHANTRESULT:
|
|
|
|
cid = GPDataTypeHelper.FromBytes<cmd_enchant_result>((byte[])Msg.dwParam1).caster;
|
|
break;
|
|
case long value when value == EC_MsgDef.MSG_PM_PLAYERGATHER:
|
|
|
|
if (Convert.ToInt32(Msg.dwParam2) == CommandID.PLAYER_GATHER_START)
|
|
{
|
|
cmd_player_gather_start cmdPlayerGatherStart = GPDataTypeHelper.FromBytes<cmd_player_gather_start>((byte[])Msg.dwParam1);
|
|
cid = cmdPlayerGatherStart.pid;
|
|
}
|
|
else if (Convert.ToInt32(Msg.dwParam2) == CommandID.PLAYER_GATHER_STOP)
|
|
{
|
|
cmd_player_gather_stop cmdPlayerGatherStop = GPDataTypeHelper.FromBytes<cmd_player_gather_stop>((byte[])Msg.dwParam1);
|
|
cid = cmdPlayerGatherStop.pid;
|
|
}
|
|
else
|
|
{
|
|
cmd_mine_gathered cmdMineGathered = GPDataTypeHelper.FromBytes<cmd_mine_gathered>((byte[])Msg.dwParam1);
|
|
cid = cmdMineGathered.player_id;
|
|
}
|
|
|
|
break;
|
|
case long value when value == EC_MsgDef.MSG_PM_PLAYERFLY:
|
|
|
|
if (Convert.ToInt32(Msg.dwParam2) == CommandID.OBJECT_TAKEOFF)
|
|
cid = (GPDataTypeHelper.FromBytes<cmd_object_takeoff>((byte[])Msg.dwParam1)).object_id;
|
|
else // OBJECT_LANDING
|
|
cid = (GPDataTypeHelper.FromBytes<cmd_object_landing>((byte[])Msg.dwParam1)).object_id;
|
|
|
|
break;
|
|
// ⚠️ Các case khác cũng tương tự, chỉ việc lấy ra đúng trường id / caster / user ...
|
|
// Do quá dài nên bạn có thể copy dần từng case từ C++ sang.
|
|
|
|
default:
|
|
System.Diagnostics.Debug.Assert(false, "Unknown message");
|
|
return false;
|
|
}
|
|
|
|
if (cid == 0)
|
|
{
|
|
System.Diagnostics.Debug.Assert(false, "cid = 0");
|
|
return false;
|
|
}
|
|
|
|
if (host != null && cid == host.GetCharacterID())
|
|
{
|
|
host.ProcessMessage(Msg);
|
|
}
|
|
else
|
|
{
|
|
var elsePlayer = SeekOutElsePlayer(cid);
|
|
if (elsePlayer != null)
|
|
elsePlayer.ProcessMessage(Msg);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Get a player (may be host or else player) by id
|
|
public CECPlayer GetPlayer(int cid, uint dwBornStamp = 0)
|
|
{
|
|
CECHostPlayer pHost = GetHostPlayer();
|
|
if (pHost && pHost.GetCharacterID() == cid)
|
|
return pHost;
|
|
else
|
|
return GetElsePlayer(cid, dwBornStamp);
|
|
}
|
|
|
|
public CECHostPlayer GetHostPlayer()
|
|
{
|
|
return CECGameRun.Instance.GetHostPlayer();
|
|
}
|
|
|
|
public bool OnMsgPlayerExtProp(ECMSG Msg)
|
|
{
|
|
object pData;
|
|
int idPlayer, iIndex;
|
|
|
|
switch (Msg.dwParam2)
|
|
{
|
|
case CommandID.PLAYER_EXT_PROP_BASE:
|
|
{
|
|
cmd_pep_base pCmd = GPDataTypeHelper.FromBytes<cmd_pep_base>((byte[])Msg.dwParam1);
|
|
idPlayer = pCmd.idPlayer;
|
|
pData = pCmd.ep_base;
|
|
iIndex = (int)ExtendPropertyClass.EXTPROPIDX_BASE;
|
|
break;
|
|
}
|
|
case CommandID.PLAYER_EXT_PROP_MOVE:
|
|
{
|
|
cmd_pep_move pCmd = GPDataTypeHelper.FromBytes<cmd_pep_move>((byte[])Msg.dwParam1);
|
|
idPlayer = pCmd.idPlayer;
|
|
pData = pCmd.ep_move;
|
|
iIndex = (int)ExtendPropertyClass.EXTPROPIDX_MOVE;
|
|
break;
|
|
}
|
|
case CommandID.PLAYER_EXT_PROP_ATK:
|
|
{
|
|
cmd_pep_attack pCmd = GPDataTypeHelper.FromBytes<cmd_pep_attack>((byte[])Msg.dwParam1);
|
|
idPlayer = pCmd.idPlayer;
|
|
pData = pCmd.ep_attack;
|
|
iIndex = (int)ExtendPropertyClass.EXTPROPIDX_ATTACK;
|
|
break;
|
|
}
|
|
|
|
case CommandID.PLAYER_EXT_PROP_DEF:
|
|
{
|
|
cmd_pep_def pCmd = GPDataTypeHelper.FromBytes<cmd_pep_def>((byte[])Msg.dwParam1);
|
|
idPlayer = pCmd.idPlayer;
|
|
pData = pCmd.ep_def;
|
|
iIndex = (int)ExtendPropertyClass.EXTPROPIDX_DEF;
|
|
break;
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
if (!GPDataTypeHelper.ISPLAYERID(idPlayer))
|
|
{
|
|
//ASSERT(ISPLAYERID(idPlayer));
|
|
return false;
|
|
}
|
|
|
|
//CECGameSession* pSession = g_pGame.GetGameSession();
|
|
|
|
if (idPlayer == m_pHostPlayer.GetCharacterID())
|
|
{
|
|
GetHostPlayer().SetPartExtendProps(iIndex, pData);
|
|
}
|
|
else
|
|
{
|
|
EC_ElsePlayer pPlayer = SeekOutElsePlayer(idPlayer);
|
|
if (pPlayer)
|
|
pPlayer.SetPartExtendProps(iIndex, pData);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Get player candidates whom can be auto-selected by 'TAB' key
|
|
public void TabSelectCandidates(int idCurSel, List<EC_ElsePlayer> aCands)
|
|
{
|
|
CECHostPlayer pHost = GetHostPlayer();
|
|
if (pHost == null)
|
|
return;
|
|
|
|
// Note: IsSkeletonReady() check is commented out in Unity codebase
|
|
// if (!pHost.IsSkeletonReady())
|
|
// {
|
|
// // Only when IsSkeletonReady() is true, GetDistToHost() is valid
|
|
// return;
|
|
// }
|
|
|
|
// Trace all Else Players
|
|
lock (m_csPlayerTab)
|
|
{
|
|
foreach (var kvp in m_PlayerTab)
|
|
{
|
|
EC_ElsePlayer pPlayer = kvp.Value;
|
|
if (pPlayer == null)
|
|
continue;
|
|
|
|
if (!pPlayer.IsSelectable() ||
|
|
pPlayer.IsDead() ||
|
|
pPlayer.GetCharacterID() == idCurSel ||
|
|
pHost.AttackableJudge(pPlayer.GetCharacterID(), false) != 1)
|
|
continue;
|
|
|
|
float fDist = pPlayer.GetDistToHost();
|
|
if (fDist > EC_RoleTypes.EC_TABSEL_DIST || !pHost.CanSafelySelectWith(fDist))
|
|
continue; // Target is too far
|
|
|
|
aCands.Add(pPlayer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public struct EC_PLAYERLOADRESULT
|
|
{
|
|
public uint dwValidMask;
|
|
public CECModel pPlayerModel;
|
|
public int iShape;
|
|
public CECModel pDummyModel;
|
|
public CECModel pPetModel;
|
|
/* CECFace pFaceModel;
|
|
A3DShader pBodyShaders[3];*/
|
|
public CECModel pFlyNviagteModel;
|
|
//CECPlayer::EquipsLoadResult EquipResult;
|
|
};
|
|
} |