TPS 개발 : 트러블슈팅 — 크래프팅 탄 스왑 시 MaxStack 붕괴
테이블 없는 크래프팅 탄이 스왑 시 잔탄을 가방에 넣는 과정에서 MaxStack을 잃어버리는 버그를 추적한 기록
TPS 개발 - 트러블슈팅: 크래프팅 탄 스왑 버그
크래프팅으로 만든 특수탄은 일반 탄과 데이터 구조 자체가 다르다. 이 차이가 탄 스왑 로직에서 꽤 복잡한 버그로 터졌다.
배경 — 크래프팅 탄은 테이블이 없다
크래프팅한 탄은 데이터 테이블이 없다. MaxStack은 1000으로 고정(Fix)해두고, 그 위에서 Definition이 재료(Material)의 효과 개수만큼 추가되는 식으로 만들어졌다.
1
2
3
4
크래프팅 탄
├─ 데이터 테이블 X (일반 탄과 다름)
├─ MaxStack: 1000 (고정값)
└─ Definition: 재료 효과 수만큼 동적으로 늘어남
일반 탄은 CSV 테이블을 기준으로 값을 읽어오는데, 크래프팅 탄은 그 자리에 참고할 테이블이 없다. 이 차이가 나중에 문제의 근원이 된다.
잔탄 반환 로직
탄을 스왑할 때, 무기에 남아있던 잔탄(잔여 탄약)은 가방(인벤토리)으로 들어가도록 개발되어 있었다.
1
2
탄 스왑
└─ 무기에 장전된 잔탄 → 가방으로 반환
문제는 여기서 시작됐다. 가방에 해당 탄이 0발이고, 무기에 남은 잔탄에 특수탄이 남아있는 상태에서 잔탄을 가방에 넣으려 하니, MaxStack을 제대로 못 받아오는 이슈가 생겼다.
방어 코드 → 방어 코드 → 새 버그
여기서부터 방어 코드가 방어 코드를 낳는 연쇄가 시작됐다.
1차 — “MaxStack 최소값은 1이다” 방어 코드와 충돌
예전에 넣어둔 “MaxStack의 최소값은 1이다”라는 방어 코드가 있었다. 이게 위 이슈와 맞물리면서, 잔탄이 1발만 들어오는 현상이 생겼다.
2차 — 총알을 다 쓰고 스왑할 때도 1발이 낀다
거기다 총알을 다 쓰고 일반 탄으로 스왑하는 과정에서도 무조건 1발이 들어오는 이상한 이슈가 함께 발생했다.
3차 — 1발 방어 코드 제거, 0으로 픽스
그래서 “최소 1발” 방어 코드를 아예 없앴다. 대신 0발로 픽스를 박았다.
1
2
Before: MaxStack 최소값 = 1 (→ 잔탄 1발 오염)
After : MaxStack 픽스값 = 0
진짜 문제 — Origin Table에 크래프팅 탄이 없다
0으로 픽스한 뒤, 진짜 버그가 드러났다.
상황: 가방 탄 0발, 총에 붙은 스페셜 아모(크래프팅 탄) 180발. 이 상태에서 다른 탄으로 스왑을 시도했다.
1
2
3
4
5
스왑 시도
└─ 가방에 해당 탄 Definition이 없음
└─ Origin Table을 참고해서 체크
└─ Origin Table에도 크래프팅 탄 정의가 없음
└─ "최소 스택 0" 방어 코드 발동
결과가 꽤 복잡했다.
- 탄 레이아웃(무기 쪽 표시) 에는 분명 탄이 있다고 뜬다.
- 가방 에는 탄이 비었다고 뜬다.
같은 탄에 대해 두 곳의 상태가 서로 다르게 보이는, 겉보기엔 사소해도 원인 추적은 까다로운 버그였다. [배경]에서 언급했듯 크래프팅 탄은 애초에 데이터 테이블이 없는데, 인벤토리 로직이 정보가 없을 때 참고하는 곳이 하필 Origin Table이었던 게 근본 원인이었다.
해결 — 참고 대상을 Origin Table에서 탄 레이아웃 Definition으로
인벤토리가 정보를 잃었을 때 엉뚱한 곳(Origin Table) 을 참고하던 걸 바로잡았다.
- 탄 레이아웃은 기존처럼 인벤에서 정보를 제공받는다. (역할 유지)
- 인벤은 탄 레이아웃의 탄 정보가 없을 때, Origin Table이 아니라 탄 레이아웃 Definition을 직접 참고해서 인스턴스를 다시 관리할 수 있도록 변경했다.
1
2
3
4
5
Before
인벤 정보 없음 → Origin Table 참고 (크래프팅 탄 없음 → 붕괴)
After
인벤 정보 없음 → 탄 레이아웃 Definition 참고 → 인스턴스 재구성
크래프팅 탄은 테이블 기반이 아니라 런타임에 조립된 Definition이 유일한 진실이므로, 정보가 끊겼을 때 되돌아갈 곳도 그 Definition이어야 맞았다.
오늘 정리
- 크래프팅 탄은 데이터 테이블이 없고 MaxStack 1000 고정 + Definition에 재료 효과 누적
- 잔탄 반환 시 MaxStack을 못 가져오는 문제 → “최소 1발” 방어 코드와 얽혀 1발 오염 버그
- 방어 코드 제거하고 0으로 픽스했더니, Origin Table에 크래프팅 탄이 없어 레이아웃/가방 상태 불일치 버그로 재발
- 근본 해결: 정보 유실 시 참고 대상을 Origin Table → 탄 레이아웃 Definition으로 변경
방어 코드를 하나 걷어낼 때마다 다른 방어 코드와의 상호작용이 드러나는, 전형적인 “고칠수록 다른 데서 터지는” 버그였다.