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