최종 갱신 (KST)

← 일감 목록
T-044

클라 — 인벤토리 칸 서버 위치 연동 · 드래그 이동 (자원 · 캐릭터)

태웅 New 우선순위 낮음 목표 261010 · 보관됨

T-036에서 갈라져 나왔다. 격자가 인덱스 기반으로 바뀌면서 자리는 열렸지만, 서버에 슬롯 위치라는 개념이 없어 지금은 만들 수 없다.

2026-09-16 범위 확장 — 자원만이 아니라 캐릭터 탭도 옮긴다. 그리고 T-015에서 넣은 [정렬] 버튼의 임시 기억을 서버 위치로 바꾸는 일도 여기서 한다(같은 필드를 쓴다).

배경

칸을 끌어 다른 자리로 옮기는 수단이 없다. 인벤토리 칸의 순서는 지금 공급자가 내놓는 순서이고, 그것은 서버가 보내 준 목록 순서다 — 사람이 정한 자리가 아니다.

[정렬] 버튼(2026-09-16)은 누른 순간의 순서를 클라가 세션 동안만 기억한다(StorageSlotSource._place). 재접속하면 사라진다. 자리의 주인은 서버여야 한다 → T-058.

2026-09-25 — 빈 칸 유지는 클라가 먼저 넣었다

장착·배치로 개체가 빠질 때 뒤의 것이 통째로 앞으로 당겨지던 문제를 먼저 고쳤다. 이제 StorageSlotSource가 Key → 칸(_place)을 들고 있고, 떠난 자리는 빈 칸으로 남으며, 들어오는 것은 앞에서부터 첫 빈 칸을 가져간다. 격자는 Get(i)가 null이면 그 프레임을 비운다.

그래서 아래 할 일 중 "빈 칸은 빈 채로 그린다"는 이미 됐다. 남은 것은 그 자리가 재접속해도 남게 하는 것 — 즉 _place를 서버 칸 번호로 바꾸는 일이다.

무엇이 막고 있나

▶ 풀렸다 (2026-10-01) — 서버 T-058이 끝났다. 클라가 쓸 것:

  • ItemInfo.Slot · ItemChangeInfo.Slot · CharacterInfo.Slot · EquipInfo.SlotPosition — 지금은 전부 Container = Inventory
  • 송신 C_StorageSortRequest { Container, Tab, SortKey(Rarity·Name·Count), Order(Descending·Ascending) } — 응답에 탭 전체
  • 송신 C_StorageMoveSlotRequest { Container, Tab, FromSlot, ToSlot } — 응답에 바뀐 칸만(교환이면 둘)
  • 수신 ServerPacketHandler.StorageSlotsReceived (S_StorageSlotsResponse { Result, Container, Tab, Slots[(Key, Slot)] })
  • 거절: StorageSlotOutOfRange · StorageSlotEmpty · InvalidStorageSortKey(캐릭터·장비 탭의 수량순) · StorageSlotPending(뽑기·우편 수령 응답 전 예약된 칸으로 이동 — 잠시 뒤 다시)

할 일

  • [x] ⏸ 서버 — T-058 — 2026-10-01 완료
  • [x] 빈 칸은 빈 채로 그린다 — 2026-09-25 완료. 자리 기억(_place)과 첫 빈 칸 배치가 들어갔다
  • [x] [정렬]을 서버 요청으로 바꾼다 — 2026-10-06. _place·ClearOrder·OnLoginCompleted를 걷어냈다. 공급자는 서버 칸 번호(ItemInfo.Slot · CharacterInfo.Slot · EquipInfo.SlotPosition)에 그대로 앉힌다. 클라 정렬 규칙(CompareForSort)도 지웠다 — 규칙의 주인은 서버 StorageSort
  • [x] PlayerDataModel — 채취·지급 증분(ItemChangeInfo.Slot)의 칸 번호도 덮어쓴다(전에는 수량만 복사해 새 자원이 0번 칸으로 읽혔다) · S_StorageSlotsResponse를 받아 칸 번호 반영 + StorageSlotsResponded
  • [x] 드래그 앤 드롭 — 2026-10-06. InventorySlotDrag를 격자가 칸을 만들 때 코드로 붙인다(가챠 결과 칸에는 안 붙는다). 세 탭 모두. 찾기 중에는 막고 알림으로 이유를 말한다
  • [x] 놓을 자리 판정(좌표로 프레임 찾기 · 뷰포트 밖이면 버림) · 빈 칸에 놓기 · 다른 칸과 자리 교환(서버가 판정)
  • [x] 서버 승인 후에 옮긴다 — 놓으면 C_StorageMoveSlotRequest만 보내고 칸은 응답 뒤에 바뀐다. 끄는 동안 같은 칸 프리팹 그림이 포인터를 따라가고 원래 칸은 흐려진다(연출은 🎨). 거절은 알림(ResultMessages에 1100~1103 추가)
  • [x] 좌클릭(상자 개봉 · 큐브 창)·우클릭(판매 담기)과 부딪히지 않게 — 끌기는 왼쪽 버튼만, 끌기가 시작되면 EventSystem이 클릭을 취소한다
  • [x] 실측 — 2026-10-06 사용자 확인("잘 된다") — 이동 · 교환 · 서버 저장
  • [x] 끌리는 칸 그림이 보이게 — 루트 캔버스에 붙어 열 캔버스(overrideSorting) 뒤에 깔려 있었다 → 그림에 자기 캔버스(순서 10) · 2026-10-06 수정
  • [x] 놓을 칸을 어둡게 덮는다 — 포인터 아래 프레임에 검정 50% 덮개 · 2026-10-06 추가
  • [x] 위 둘 실측 — 2026-10-06 사용자 확인(덮개는 30% → 50%로 올림)
  • 🎨 끌기 연출 · 끌어서 화면 밖 칸으로 가는 자동 스크롤은 하지 않았다 (휠로 스크롤하며 끈다) — 필요해지면 새 일감

이 일감에서 하지 않는 것

  • 창고로 끌어 넣기 → T-126 — 창고(T-107)가 서야 붙인다

완료 조건

[정렬]과 드래그로 정한 자리가 재로그인해도 그대로이고, 자원·캐릭터·장비 세 탭 모두 칸을 끌어 옮기거나 바꿀 수 있다.

막고 있는 것 / 선행 일감

  • T-058 — 서버 칸 위치 · 정렬 · 이동 패킷

참고

  • Assets/Scripts_Client/UI/Inventory/InventoryGridPresenter/InventoryGridPresenter.cs — 격자는 이미 i번째 항목 → i번째 프레임이라 위치 필드만 오면 얹을 수 있다
  • Assets/Scripts_Client/UI/Inventory/InventoryGridPresenter/InventorySlotSource.cs — 걷어낼 임시 기억
  • Assets/Scripts_Server/Protocol/PacketInfo.cs — ItemInfo·CharacterInfo