최종 갱신 (KST)

← 일감 목록
T-032

클라 — 인벤토리 판매 UI

태웅 Closed 우선순위 높음 목표 미정 · 보관됨

배경

방치형은 인벤토리가 자동으로 찬다. 낮은 등급을 하나씩 골라 파는 UI면 플레이어가 매일 수십 번 클릭하게 되고, 이는 P1(주의를 뺏지 않는다)을 정면으로 어긴다.

일괄 판매가 기본 동선이어야 한다. 서버(T-028)가 목록 단위 요청을 받도록 설계된 이유다.

할 일

✅ 막힘이 풀렸다 (2026-09-02). T-028이 서버 구현과 미러 커밋을 끝내 Assets/Scripts_Server/Protocol에 판매 패킷이 들어왔다. 전 항목 착수 가능하다. BasePrice도 156종 전부 채워져 판매가 미리보기를 지금 그릴 수 있다. → 이슈 #22

✅ 코드·씬 배선이 다 들어갔다 (2026-09-04). 남은 것은 에디터 실측뿐이다. 동선은 우클릭으로 담고 → 아래 칸에서 한 번에 판다 — 상세는 Storage 규칙.md의 "판매는 우클릭으로 담고".

  • [x] 칸을 고르는 수단 — InventorySlotView에 우클릭 이벤트(RightClicked)를 달았다. 담긴 칸을 다시 누르면 뺀다(토글), 보유 2개 이상이면 수량 팝업(AmountInputPresenter)이 뜬다
  • [x] 판매 목록 상태를 Managers/SellCartModel(MonoService)에 두고 격자·정보 칸이 각자 구독
  • [x] 판매가 미리보기(합계 골드) — ItemTable.BasePrice × 수량. 지금 판매율은 100%다
  • [x] 판매 후 인벤토리·골드 표시 갱신 (S_ItemSellResponse + S_CurrencyResponse)
  • [x] 확인 단계 — 담기 → [판매] 두 단계가 그 역할이다. 별도 모달을 두지 않았다(P1)
  • [x] 상위 등급(Rare~Mythic) 오판매 방지 — 담기면 합계 옆에 경고 문구를 켠다. 목록에서 빼지는 않는다("왜 안 담기지"가 되고, 파는 자유는 남긴다)
  • [x] Handle_S_ItemSellResponse를 Unity 핸들러에 추가 — ServerPacketHandler에 #region 상점 신설
  • [x] 담아 둔 사이 인벤토리가 줄면 카트가 따라 깎인다 — 없으면 NotEnoughItem으로 전량 거절된다
  • [x] 씬·프리팹 배선 (아래 "배선 결과" 참조)
  • [x] 에디터 실측 — 담기·수량 팝업·합계·판매·골드 증가 (2026-09-05 확인)

이번 범위에서 뺀 것

  • 희귀도/산업 단위 일괄 선택 — 우클릭 낱개 담기부터 세웠다. 필요해지면 새 번호로 등록한다
  • 캐릭터·장비 판매 — ⏸ 서버 패킷이 없다. C_ItemSellRequest가 아이템 TID 축 (ItemInfo { ItemId, Count })이라 개체 PK로 식별되는 캐릭터를 담을 수 없다. 그래서 격자가 자원 탭이 아니면 우클릭을 무시한다
  • 좌클릭 상세 표시 — 판매 목록이 Information Presenter 자리를 차지했다. 상세를 되살릴지는 따로 정한다

서버가 내려 준 것 (2026-09-02)

// 요청 — 종류 목록을 한 번에 보낸다. Count는 "파는 개수"(델타)다
C_ItemSellRequest { List<ItemInfo> Items }          // ItemInfo { int ItemId; int Count; }

// 응답 — 잔액이 아니라 이번에 번 금액이다. 갱신된 잔액은 S_CurrencyResponse가 따로 온다
S_ItemSellResponse {
    EResultCode          Result;
    long                 GainedGold;
    List<ItemChangeInfo> ItemChangeInfos;  // 갱신 후 누적 총량. 0개는 Kind=Remove
}
결과 코드 언제
Ok = 0 판매 성공
NotLoggedIn = 1 로그인 전 요청
InvalidSellRequest = 300 빈 목록 · 수량 0 이하 · 존재하지 않는 ItemTID
NotEnoughItem = 301 보유량 부족

⚠️ 판매는 전부 되거나 전혀 안 된다. 목록 중 한 종류라도 보유량이 모자라면 NotEnoughItem으로 거절되고 아무것도 팔리지 않는다. 부분 성공 응답은 오지 않는다.

  • ItemChangeInfos의 Count는 델타가 아니라 갱신 후 총량이다 — 덮어쓰기로 반영한다.
  • 다 팔아 0개가 된 아이템은 Kind = Remove로 온다. 목록에서 칸을 지우면 된다.
  • 판매 성공 시 S_ItemSellResponse 뒤에 S_CurrencyResponse가 따라온다(확정 잔액).
  • 같은 ItemId를 목록에 여러 번 넣어도 서버가 합산한다.
  • 판매 불가 아이템은 아직 없다. 156종 전부 팔린다(상자가 생기는 T-029에서 갈린다).

배선 결과 (2026-09-04)

전부 들어갔다. 빠진 참조 0건으로 검증했고 씬은 저장됐다. 화면 위치는 UI 배치 현황.md에 있다 — 여기 다시 쓰지 않는다.

무엇 어디
담김 마크 (임시 — 주황 네모 + "판") InventorySlotView.prefab > Sell Mark (평소 꺼짐 · raycast 끔)
판매 줄 Assets/Prefabs/SellCartRowView.prefab (이름·개수·가격·빼기)
수량 팝업 !System Canvas > AmountInput Presenter (↓ SUB VIEW) — 창고가 아니다
판매 목록 Information Presenter 안 (스크롤 · 빈 안내 · 합계 · 경고 · [판매])
카트 씬 루트 SellCart (MODEL) (PlayerData (MODEL) 옆)
  • ⚠️ Rarity Image의 raycast target을 켜 둔 채로 두어야 우클릭이 잡힌다. Sell Mark 쪽은 반대로 꺼 두었다 — 마크가 클릭을 먹으면 담긴 칸을 다시 못 뺀다.
  • 🔴 수량 팝업은 창고 캔버스에 두면 안 된다 (2026-09-05 이동). 열 캔버스는 넷 다 Sorting Order가 0인 형제라 창고 안의 차단막이 다른 열에 닿지 않는다 — 확인 전인데 상태바·메인·거래가 눌린다. !System Canvas(order 2)로 옮기고 CanvasGroup으로 여닫는다. 창고는 UIManager.AskAmount(...)로 부르기만 하므로 팝업 참조를 들지 않는다.
  • 새 스크립트·프리팹의 .meta는 원본과 함께 커밋한다.

완료 조건

화면에서 자원 칸을 우클릭해 담고 [판매]를 누르면 골드가 오르고 목록에서 사라진다. 그 골드로 가챠 화면(T-031)에서 바로 뽑을 수 있다.

막고 있는 것 / 선행 일감

  • 없음 — T-028(패킷·판매가 규칙)과 BasePrice 임시값이 2026-09-02에 들어왔다. T-018은 값을 확정하는 일감이라 미리보기 구현을 막지 않는다

관련 커밋

  • 없음

참고

  • 거래 3.1 — 즉시 판매는 낮은 등급의 출구다
  • Assets/Scripts_Client/폴더 구조.md