Merge pull request 'Add CreateGetOtherEquipDetailCmd and update player option UI prefab' (#208) from feature/character_info into develop
Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/208
This commit is contained in:
@@ -116,7 +116,7 @@ MonoBehaviour:
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 0
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 369226366953714584}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
|
||||
@@ -457,6 +457,19 @@ namespace CSNetwork.C2SCommand
|
||||
public int[] idList; // Variable length array
|
||||
}
|
||||
|
||||
// Get other player equip/profile detail (view other player profile) — same shape as CMD_GetOtherEquip
|
||||
public struct CMD_GetOtherEquipDetail
|
||||
{
|
||||
public ushort size;
|
||||
public int[] idList; // Variable length array (role IDs)
|
||||
}
|
||||
|
||||
// Single-role variant: body is only roleId (4 bytes). Some servers expect this instead of size+idList.
|
||||
public struct CMD_GetOtherEquipDetailSingle
|
||||
{
|
||||
public int roleId;
|
||||
}
|
||||
|
||||
// Team set pickup command
|
||||
public struct CMD_TeamSetPickup
|
||||
{
|
||||
|
||||
@@ -377,6 +377,22 @@ namespace CSNetwork.C2SCommand
|
||||
return SerializeCommand(CommandID.SELECT_TARGET, cmd);
|
||||
}
|
||||
|
||||
/// <summary>Create C2S GET_OTHER_EQUIP_DETAIL command (view other player profile/equip). Sends cmd + roleId only (4-byte body).</summary>
|
||||
public static Octets CreateGetOtherEquipDetailCmd(int roleId)
|
||||
{
|
||||
var cmd = new CMD_GetOtherEquipDetailSingle { roleId = roleId };
|
||||
return SerializeCommand(CommandID.GET_OTHER_EQUIP_DETAIL, cmd);
|
||||
}
|
||||
|
||||
/// <summary>Create C2S GET_OTHER_EQUIP_DETAIL command for multiple role IDs (size + idList format).</summary>
|
||||
public static Octets CreateGetOtherEquipDetailCmd(int[] roleIds)
|
||||
{
|
||||
if (roleIds == null || roleIds.Length == 0)
|
||||
throw new ArgumentException("roleIds cannot be null or empty.", nameof(roleIds));
|
||||
var cmd = new CMD_GetOtherEquipDetail { size = (ushort)roleIds.Length, idList = roleIds };
|
||||
return SerializeCommand(CommandID.GET_OTHER_EQUIP_DETAIL, cmd);
|
||||
}
|
||||
|
||||
public static Octets CreateDropIvtrItem(byte index, int amount)
|
||||
{
|
||||
var cmd = new CMD_DropIvtrItem
|
||||
|
||||
@@ -1363,6 +1363,34 @@ namespace CSNetwork.GPDataType
|
||||
public uint count_equip;
|
||||
}
|
||||
|
||||
/// <summary>S2C PLAYER_EQUIP_DETAIL: one equipment slot entry (slot index + item template id).</summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct s2c_player_equip_detail_slot
|
||||
{
|
||||
public byte slot_index;
|
||||
public int tid;
|
||||
}
|
||||
|
||||
/// <summary>Parsed S2C PLAYER_EQUIP_DETAIL payload for readable use.</summary>
|
||||
public class PlayerEquipDetailData
|
||||
{
|
||||
public int RoleId { get; set; }
|
||||
public List<(byte SlotIndex, int Tid)> Slots { get; } = new List<(byte, int)>();
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"[PlayerEquipDetail] RoleId={RoleId}, Slots={Slots.Count}: ");
|
||||
for (int i = 0; i < Slots.Count; i++)
|
||||
{
|
||||
var (slot, tid) = Slots[i];
|
||||
if (i > 0) sb.Append(", ");
|
||||
sb.Append($"[{slot}]=tid{tid}");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct cmd_move_equip_item
|
||||
{
|
||||
@@ -1701,6 +1729,30 @@ namespace CSNetwork.GPDataType
|
||||
return (id & 0xC0000000) == 0xC0000000;
|
||||
}
|
||||
|
||||
/// <summary>Parse S2C PLAYER_EQUIP_DETAIL payload into readable data. Layout: roleId (4), count (2), then count × (slot byte, tid int).</summary>
|
||||
public static PlayerEquipDetailData ParsePlayerEquipDetail(byte[] data)
|
||||
{
|
||||
var result = new PlayerEquipDetailData();
|
||||
if (data == null || data.Length < 6)
|
||||
return result;
|
||||
|
||||
int pos = 0;
|
||||
result.RoleId = BitConverter.ToInt32(data, pos);
|
||||
pos += 4;
|
||||
ushort count = BitConverter.ToUInt16(data, pos);
|
||||
pos += 2;
|
||||
|
||||
int slotSize = Marshal.SizeOf<s2c_player_equip_detail_slot>();
|
||||
for (int i = 0; i < count && pos + slotSize <= data.Length; i++)
|
||||
{
|
||||
var slot = FromBytes<s2c_player_equip_detail_slot>(data, pos);
|
||||
result.Slots.Add((slot.slot_index, slot.tid));
|
||||
pos += slotSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static A3DVECTOR3 g_vOrigin = new A3DVECTOR3(0.0f);
|
||||
public static A3DVECTOR3 g_vAxisX = new A3DVECTOR3(1.0f, 0.0f, 0.0f);
|
||||
public static A3DVECTOR3 g_vAxisY = new A3DVECTOR3(0.0f, 1.0f, 0.0f);
|
||||
|
||||
@@ -15,6 +15,7 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using UnityEngine;
|
||||
using CommandID = CSNetwork.GPDataType.CommandID;
|
||||
|
||||
@@ -639,7 +640,39 @@ namespace CSNetwork
|
||||
EC_Game.GetGameRun().SetLogoutFlag(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Format parsed PLAYER_EQUIP_DETAIL with real game data: slot names and item names from element data.</summary>
|
||||
private static string FormatPlayerEquipDetailReadable(PlayerEquipDetailData parsed)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"RoleId={parsed.RoleId}");
|
||||
if (parsed.Slots.Count == 0)
|
||||
{
|
||||
sb.Append(", no slots");
|
||||
return sb.ToString();
|
||||
}
|
||||
sb.Append(" | ");
|
||||
for (int i = 0; i < parsed.Slots.Count; i++)
|
||||
{
|
||||
var (slotIndex, tid) = parsed.Slots[i];
|
||||
string slotName = GetEquipSlotName(slotIndex);
|
||||
string itemName = tid <= 0 ? "(empty)" : (EC_IvtrItemUtils.Instance.ResolveItemName(tid) ?? $"(tid{tid})");
|
||||
if (string.IsNullOrEmpty(itemName)) itemName = $"(tid{tid})";
|
||||
if (i > 0) sb.Append(", ");
|
||||
sb.Append($"{slotName}: {itemName}");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string GetEquipSlotName(byte slotIndex)
|
||||
{
|
||||
if (Enum.IsDefined(typeof(IndexOfIteminEquipmentInventory), slotIndex))
|
||||
{
|
||||
var name = Enum.GetName(typeof(IndexOfIteminEquipmentInventory), slotIndex);
|
||||
if (!string.IsNullOrEmpty(name)) return name;
|
||||
}
|
||||
return $"Slot{slotIndex}";
|
||||
}
|
||||
|
||||
private void HandleServerDataSend(gamedatasend protocol)
|
||||
{
|
||||
@@ -783,6 +816,26 @@ namespace CSNetwork
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ITEMOPERATION, (int)MANAGER_INDEX.MAN_PLAYER, 0,
|
||||
pDataBuf, pCmdHeader);
|
||||
break;
|
||||
case CommandID.PLAYER_EQUIP_DETAIL:
|
||||
// View other player profile/equip detail — parse and log with real game data (item names, slot names)
|
||||
if (pDataBuf != null && pDataBuf.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var parsed = GPDataTypeHelper.ParsePlayerEquipDetail(pDataBuf);
|
||||
string readable = FormatPlayerEquipDetailReadable(parsed);
|
||||
Debug.Log($"[PLAYER_EQUIP_DETAIL] {readable}");
|
||||
if (parsed.Slots.Count == 0 && pDataBuf.Length > 6)
|
||||
Debug.Log($"[PLAYER_EQUIP_DETAIL] Raw(hex): {BitConverter.ToString(pDataBuf)}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[PLAYER_EQUIP_DETAIL] Parse failed: {ex.Message}. Raw length={pDataBuf.Length}, hex: {BitConverter.ToString(pDataBuf, 0, Math.Min(64, pDataBuf.Length))}...");
|
||||
}
|
||||
}
|
||||
else
|
||||
Debug.Log("[PLAYER_EQUIP_DETAIL] Server sent empty payload.");
|
||||
break;
|
||||
case CommandID.PLAYER_CASH:
|
||||
{
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf,
|
||||
@@ -1824,6 +1877,14 @@ namespace CSNetwork
|
||||
// }
|
||||
}
|
||||
|
||||
/// <summary>Request other player profile/equip detail (C2S GET_OTHER_EQUIP_DETAIL). Server responds with PLAYER_EQUIP_DETAIL.</summary>
|
||||
public void c2s_SendCmdGetOtherEquipDetail(int roleId)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
gamedatasend.Data = C2SCommandFactory.CreateGetOtherEquipDetailCmd(roleId);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
|
||||
public void c2s_SendCmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
|
||||
@@ -732,6 +732,12 @@ namespace BrewMonster.Network
|
||||
Instance._gameSession.CmdCache.SendCmdExtProps();
|
||||
}
|
||||
|
||||
/// <summary>Request other player profile/equip detail (C2S GET_OTHER_EQUIP_DETAIL). Server responds with PLAYER_EQUIP_DETAIL; response is currently logged via Debug.Log.</summary>
|
||||
public static void c2s_SendCmdGetOtherEquipDetail(int roleId)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdGetOtherEquipDetail(roleId);
|
||||
}
|
||||
|
||||
/// <summary>Send C2S::SET_STATUS_POINT (attribute point allocation).</summary>
|
||||
public static void c2s_CmdSetStatusPts(int vitality, int energy, int strength, int agility)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,8 @@ namespace BrewMonster.UI
|
||||
{
|
||||
Debug.Log("OnViewInfo: " + characterId);
|
||||
var list = new List<int> { characterId };
|
||||
UnityGameSession.GetRoleBaseInfo(1, list);
|
||||
//UnityGameSession.GetRoleBaseInfo(1, list);
|
||||
UnityGameSession.c2s_SendCmdGetOtherEquipDetail(characterId);
|
||||
}
|
||||
|
||||
void OnTeamInvite(int characterId)
|
||||
|
||||
Reference in New Issue
Block a user