Add quick sort item feature
This commit is contained in:
@@ -58,6 +58,9 @@ namespace BrewMonster.Scripts.Managers
|
||||
[Header("Stack combine — merge into another stack (C++ inventory drag-merge, assign in Inspector)")]
|
||||
[SerializeField] private Button combineStackButton;
|
||||
|
||||
[Header("Sort / arrange pack (C++ DlgInventory arrange)")]
|
||||
[SerializeField] private Button sortInventoryButton;
|
||||
|
||||
private int _splitAmount = 1;
|
||||
private int _splitMaxAmount = 1;
|
||||
|
||||
@@ -137,6 +140,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
WireBagTabButtons();
|
||||
WireSplitUI();
|
||||
WireCombineUI();
|
||||
WireSortInventoryUI();
|
||||
|
||||
//if (currentDragImage == null)
|
||||
//{
|
||||
@@ -228,6 +232,60 @@ namespace BrewMonster.Scripts.Managers
|
||||
}
|
||||
}
|
||||
|
||||
private void WireSortInventoryUI()
|
||||
{
|
||||
ResolveSortInventoryButton();
|
||||
if (sortInventoryButton != null)
|
||||
{
|
||||
sortInventoryButton.onClick.RemoveAllListeners();
|
||||
sortInventoryButton.onClick.AddListener(OnSortInventoryClicked);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResolveSortInventoryButton()
|
||||
{
|
||||
if (sortInventoryButton != null)
|
||||
return;
|
||||
|
||||
var buttons = GetComponentsInChildren<Button>(true);
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
var btn = buttons[i];
|
||||
if (btn == null)
|
||||
continue;
|
||||
string n = btn.name.ToLowerInvariant();
|
||||
if (n.Contains("arrange") || n.Contains("sort") || n == "btn_arrange")
|
||||
{
|
||||
sortInventoryButton = btn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Arrange main inventory (IVTRTYPE_PACK). C++ CDlgInventory::OnCommand_arrange.</summary>
|
||||
public void OnSortInventoryClicked()
|
||||
{
|
||||
if (_bagTab != InventoryBagTab.Item)
|
||||
{
|
||||
Debug.LogWarning("[InventoryUI] Sort pack: switch to Item tab first");
|
||||
return;
|
||||
}
|
||||
|
||||
var host = CECGameRun.Instance?.GetHostPlayer();
|
||||
if (host == null)
|
||||
return;
|
||||
|
||||
int cool = host.GetCoolTime((int)CoolTimeIndex.GP_CT_MULTI_EXCHANGE_ITEM, out _);
|
||||
if (cool > 0)
|
||||
{
|
||||
EC_Game.GetGameRun()?.AddFixedMessage((int)FixedMsg.FIXMSG_CMD_INCOOLTIME);
|
||||
return;
|
||||
}
|
||||
|
||||
host.SortPack(InventoryConst.IVTRTYPE_PACK);
|
||||
RefreshAll();
|
||||
}
|
||||
|
||||
private void ShowSplitPanel(bool show)
|
||||
{
|
||||
if (splitPanelRoot != null)
|
||||
|
||||
@@ -439,6 +439,25 @@ namespace CSNetwork.C2SCommand
|
||||
return SerializeCommand(CommandID.MOVE_IVTR_ITEM, cmd);
|
||||
}
|
||||
|
||||
/// <summary>C++ c2s_SendCmdMultiExchangeItem — pack arrange / sort (variable-length operation list).</summary>
|
||||
public static Octets CreateMultiExchangeItem(byte location, int pairCount, int[] indexPairs)
|
||||
{
|
||||
if (pairCount < 1 || indexPairs == null || indexPairs.Length < pairCount * 2)
|
||||
return null;
|
||||
|
||||
var octets = new Octets();
|
||||
WriteBasicValue(octets, (ushort)CommandID.MULTI_EXCHANGE_ITEM);
|
||||
WriteBasicValue(octets, location);
|
||||
WriteBasicValue(octets, (byte)pairCount);
|
||||
for (int i = 0; i < pairCount; i++)
|
||||
{
|
||||
WriteBasicValue(octets, (byte)indexPairs[i * 2]);
|
||||
WriteBasicValue(octets, (byte)indexPairs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
return octets;
|
||||
}
|
||||
|
||||
public static Octets CreatePickupItem(int idItem, int tid)
|
||||
{
|
||||
var cmd = new CMD_Pickup
|
||||
|
||||
@@ -471,6 +471,16 @@ namespace CSNetwork
|
||||
SendProtocol(gamedatasendRequest);
|
||||
}
|
||||
|
||||
public void RequestMultiExchangeItem(byte location, int pairCount, int[] indexPairs)
|
||||
{
|
||||
var data = C2SCommandFactory.CreateMultiExchangeItem(location, pairCount, indexPairs);
|
||||
if (data == null)
|
||||
return;
|
||||
var gamedatasendRequest = new gamedatasend();
|
||||
gamedatasendRequest.Data = data;
|
||||
SendProtocol(gamedatasendRequest);
|
||||
}
|
||||
|
||||
public void RequestPickupItem(int idItem, int tid)
|
||||
{
|
||||
gamedatasend gamedatasendRequest = new gamedatasend();
|
||||
|
||||
@@ -497,6 +497,12 @@ namespace BrewMonster.Network
|
||||
{
|
||||
Instance._gameSession.RequestMoveIvtrItem(src, dest, count);
|
||||
}
|
||||
|
||||
public static void RequestMultiExchangeItem(byte location, int pairCount, int[] indexPairs)
|
||||
{
|
||||
Instance._gameSession.RequestMultiExchangeItem(location, pairCount, indexPairs);
|
||||
}
|
||||
|
||||
public static void LoadConfigData()
|
||||
{
|
||||
Instance._gameSession.LoadConfigData();
|
||||
|
||||
@@ -6807,13 +6807,14 @@ GameObject:
|
||||
- component: {fileID: 7902430374187284626}
|
||||
- component: {fileID: 2646092870800509053}
|
||||
- component: {fileID: 8343020880054062986}
|
||||
- component: {fileID: 4947710734819332199}
|
||||
m_Layer: 5
|
||||
m_Name: sap_xep
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &7902430374187284626
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -6828,9 +6829,9 @@ RectTransform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 5322092470266254149}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 37.5748, y: -45.8533}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 75.1496, y: 91.7066}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2646092870800509053
|
||||
@@ -6848,7 +6849,7 @@ MonoBehaviour:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2805221609055900627}
|
||||
m_Enabled: 0
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
@@ -6871,6 +6872,50 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &4947710734819332199
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2805221609055900627}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 8343020880054062986}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &2956478068852740616
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -12766,6 +12811,7 @@ MonoBehaviour:
|
||||
splitDecreaseButton: {fileID: 4996709440620641399}
|
||||
splitMaxButton: {fileID: 1013848439096781118}
|
||||
combineStackButton: {fileID: 4438583262695563174}
|
||||
sortInventoryButton: {fileID: 4947710734819332199}
|
||||
autoRefresh: 1
|
||||
refreshInterval: 1
|
||||
showEquipmentDetails: 1
|
||||
@@ -13665,7 +13711,7 @@ MonoBehaviour:
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: 37.12
|
||||
m_Spacing: -204.8
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
@@ -20524,7 +20570,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7209086543831860202, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -42
|
||||
value: -836.15
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8894405194986632892, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
@@ -20544,7 +20590,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8894405194986632892, guid: c56ed80641ff74ce49f91401e3eb8367, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -21
|
||||
value: -418.075
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using System.Collections.Generic;
|
||||
using static BrewMonster.Scripts.EC_Inventory;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public partial class CECHostPlayer
|
||||
{
|
||||
/// <summary>
|
||||
/// C++ CECHostPlayer::SortPack — reorder pack via MULTI_EXCHANGE_ITEM (DlgInventory OnCommand_arrange).
|
||||
/// </summary>
|
||||
public void SortPack(int iPack)
|
||||
{
|
||||
EC_Inventory pInventory = GetPack(iPack);
|
||||
if (pInventory == null)
|
||||
return;
|
||||
|
||||
int nIvtrSize = pInventory.GetSize();
|
||||
if (nIvtrSize <= 0)
|
||||
return;
|
||||
|
||||
if (pInventory.GetEmptySlotNum() == nIvtrSize)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < nIvtrSize; i++)
|
||||
{
|
||||
var pItem = pInventory.GetItem(i, false);
|
||||
if (pItem != null && pItem.IsFrozen())
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nIvtrSize; i++)
|
||||
{
|
||||
var pItem = pInventory.GetItem(i, false);
|
||||
pItem?.Freeze(true);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var vecItem = new List<int>(nIvtrSize);
|
||||
for (int i = 0; i < nIvtrSize; i++)
|
||||
vecItem.Add(i);
|
||||
|
||||
vecItem.Sort((a, b) => ComparePackSortIndices(pInventory, a, b));
|
||||
|
||||
var vecExchange = new List<int>();
|
||||
int pos = 0;
|
||||
while (pos < nIvtrSize)
|
||||
{
|
||||
int j = vecItem[pos];
|
||||
if (j == pos)
|
||||
{
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int k = vecItem[j];
|
||||
if (pInventory.GetItem(j, false) != null || pInventory.GetItem(k, false) != null)
|
||||
{
|
||||
vecExchange.Add(pos);
|
||||
vecExchange.Add(j);
|
||||
}
|
||||
|
||||
int tmp = vecItem[pos];
|
||||
vecItem[pos] = vecItem[j];
|
||||
vecItem[j] = tmp;
|
||||
}
|
||||
|
||||
if (vecExchange.Count > 0)
|
||||
{
|
||||
int pairCount = vecExchange.Count / 2;
|
||||
for (int i = 0, j = vecExchange.Count - 1; i < j; i++, j--)
|
||||
{
|
||||
int t = vecExchange[i];
|
||||
vecExchange[i] = vecExchange[j];
|
||||
vecExchange[j] = t;
|
||||
}
|
||||
|
||||
UnityGameSession.RequestMultiExchangeItem((byte)iPack, pairCount, vecExchange.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
var pGameRun = EC_Game.GetGameRun();
|
||||
pGameRun?.AddChatMessage("Không cần sắp xếp kho đồ.", (int)ChatChannel.GP_CHAT_SYSTEM);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
for (int i = 0; i < nIvtrSize; i++)
|
||||
{
|
||||
var pItem = pInventory.GetItem(i, false);
|
||||
pItem?.Freeze(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int ComparePackSortIndices(EC_Inventory pInventory, int index1, int index2)
|
||||
{
|
||||
if (DefaultPackSortLess(pInventory, index1, index2))
|
||||
return -1;
|
||||
if (DefaultPackSortLess(pInventory, index2, index1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>Returns true when slot <paramref name="index1"/> should appear before <paramref name="index2"/>.</summary>
|
||||
private static bool DefaultPackSortLess(EC_Inventory pInventory, int index1, int index2)
|
||||
{
|
||||
if (pInventory == null)
|
||||
return false;
|
||||
|
||||
EC_IvtrItem pItem1 = pInventory.GetItem(index1, false);
|
||||
EC_IvtrItem pItem2 = pInventory.GetItem(index2, false);
|
||||
|
||||
if (pItem1 == null)
|
||||
return false;
|
||||
if (pItem2 == null)
|
||||
return true;
|
||||
|
||||
int cid1 = pItem1.GetClassID();
|
||||
int tid1 = pItem1.GetTemplateID();
|
||||
int cid2 = pItem2.GetClassID();
|
||||
int tid2 = pItem2.GetTemplateID();
|
||||
|
||||
if (cid1 != cid2)
|
||||
{
|
||||
int cidOrder1 = GetPackSortClassOrder(cid1);
|
||||
int cidOrder2 = GetPackSortClassOrder(cid2);
|
||||
if (cidOrder1 != cidOrder2)
|
||||
return cidOrder1 > cidOrder2;
|
||||
return cid1 < cid2;
|
||||
}
|
||||
|
||||
if (cid1 == (int)EC_IvtrItem.InventoryClassId.ICID_WEAPON)
|
||||
{
|
||||
if (pItem1 is CECIvtrWeapon w1 && pItem2 is CECIvtrWeapon w2)
|
||||
{
|
||||
var e1 = w1.GetDBEssence();
|
||||
var e2 = w2.GetDBEssence();
|
||||
if (e1.level != e2.level)
|
||||
return e1.level > e2.level;
|
||||
}
|
||||
}
|
||||
else if (cid1 == (int)EC_IvtrItem.InventoryClassId.ICID_ARMOR)
|
||||
{
|
||||
if (pItem1 is EC_IvtrArmor a1 && pItem2 is EC_IvtrArmor a2)
|
||||
{
|
||||
var e1 = a1.GetDBEssence();
|
||||
var e2 = a2.GetDBEssence();
|
||||
if (e1.level != e2.level)
|
||||
return e1.level > e2.level;
|
||||
}
|
||||
}
|
||||
else if (cid1 == (int)EC_IvtrItem.InventoryClassId.ICID_GENERALCARD)
|
||||
{
|
||||
if (pItem1 is EC_IvtrGeneralCard c1 && pItem2 is EC_IvtrGeneralCard c2)
|
||||
{
|
||||
int t1 = c1.GetEssence().type;
|
||||
int t2 = c2.GetEssence().type;
|
||||
if (t1 != t2)
|
||||
return t1 < t2;
|
||||
}
|
||||
}
|
||||
|
||||
return tid1 < tid2;
|
||||
}
|
||||
|
||||
private static int GetPackSortClassOrder(int cid)
|
||||
{
|
||||
int[] s_CIDs =
|
||||
{
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_WEAPON,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_ARROW,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_TOSSMAT,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_ARMOR,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_DECORATION,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_BIBLE,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_FLYSWORD,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_WING,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_GOBLIN,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_GOBLIN_EQUIP,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_FASHION,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_AUTOHP,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_AUTOMP,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_MEDICINE,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_SKILLMATTER,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_TARGETITEM,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_STONE,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_PETEGG,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_REFINETICKET,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_DYETICKET,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_GOBLIN_EXPPILL,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_GENERALCARD,
|
||||
(int)EC_IvtrItem.InventoryClassId.ICID_GENERALCARD_DICE,
|
||||
};
|
||||
|
||||
for (int i = 0; i < s_CIDs.Length; i++)
|
||||
{
|
||||
if (cid == s_CIDs[i])
|
||||
return s_CIDs.Length - i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22d7c6cd009100d44956b805ed093795
|
||||
Reference in New Issue
Block a user