배경
방치형은 인벤토리가 자동으로 찬다. 낮은 등급을 하나씩 골라 파는 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