|
| 1 | +# 👻 Specter — 시간의 유령 시스템 |
| 2 | + |
| 3 | +<p align="center"> |
| 4 | + <img src="https://img.shields.io/badge/Minecraft-1.21.4-brightgreen?style=for-the-badge&logo=mojang-studios" alt="Minecraft 1.21.4"/> |
| 5 | + <img src="https://img.shields.io/badge/Paper-API-blue?style=for-the-badge" alt="Paper API"/> |
| 6 | + <img src="https://img.shields.io/badge/Java-21-orange?style=for-the-badge&logo=openjdk" alt="Java 21"/> |
| 7 | + <img src="https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge" alt="License"/> |
| 8 | +</p> |
| 9 | + |
| 10 | +> **과거의 플레이어 행동을 유령으로 되살려 보는 Paper 플러그인** |
| 11 | +> |
| 12 | +> 모든 플레이어의 움직임, 블록 조작, 전투, 사망을 기록하고 — 투명한 고스트 엔티티로 다시 재생합니다. |
| 13 | +> 게임플레이 연출과 서버 보안, 두 가지 목적을 동시에 달성하는 올인원 기록/재생 시스템입니다. |
| 14 | +
|
| 15 | +--- |
| 16 | + |
| 17 | +## 📋 목차 |
| 18 | + |
| 19 | +- [주요 기능](#-주요-기능) |
| 20 | +- [명령어 일람](#-명령어-일람) |
| 21 | +- [설치 방법](#-설치-방법) |
| 22 | +- [설정 파일](#-설정-파일) |
| 23 | +- [권한 노드](#-권한-노드) |
| 24 | +- [작동 원리](#-작동-원리) |
| 25 | +- [스크린샷](#-스크린샷) |
| 26 | +- [FAQ](#-자주-묻는-질문) |
| 27 | +- [문제 신고 및 기여](#-문제-신고--기여) |
| 28 | + |
| 29 | +--- |
| 30 | + |
| 31 | +## ✨ 주요 기능 |
| 32 | + |
| 33 | +### 🎮 게임플레이 기능 |
| 34 | + |
| 35 | +| 기능 | 설명 | |
| 36 | +|------|------| |
| 37 | +| **자기 재생** | 자신의 과거 행동을 고스트로 되돌려 봅니다. 건축 과정 리뷰, 탐험 경로 확인 등에 활용할 수 있습니다. | |
| 38 | +| **사망 유령** | 플레이어가 사망한 위치에 붉은 해골 고스트가 나타납니다. 위험 지역을 시각적으로 경고해줍니다. | |
| 39 | +| **스펙터 존** | 플레이어 활동이 많은 청크에 밀도에 따라 다른 색상의 파티클이 나타납니다. (흰색 → 파란색 → 보라색 → 금색) | |
| 40 | +| **유령 메시지** | 월드 어디에든 떠다니는 메시지를 남길 수 있습니다. 다른 플레이어에게 힌트나 메모를 전달하세요. | |
| 41 | + |
| 42 | +### 🔒 보안 / 관리 기능 |
| 43 | + |
| 44 | +| 기능 | 설명 | |
| 45 | +|------|------| |
| 46 | +| **타인 기록 재생** | 관리자가 특정 플레이어의 과거 행동을 고스트로 재생하여 확인할 수 있습니다. 분쟁 해결, 테러 확인에 유용합니다. | |
| 47 | +| **영역 기록 재생** | 특정 반경 내에서 활동한 모든 플레이어의 기록을 한번에 재생합니다. 건물이 파괴된 현장 조사 등에 적합합니다. | |
| 48 | +| **실시간 감시** | 특정 플레이어의 행동을 실시간으로 모니터링합니다. 액션바에 실시간 행동이 표시됩니다. | |
| 49 | +| **자동 알림** | 대량 블록 파괴, 엑스레이 패턴, 속도 이상, 컨테이너 습격, 용암 배치 등 의심스러운 행위를 자동으로 감지하고 알림을 보냅니다. | |
| 50 | + |
| 51 | +### 🎬 재생 시스템 |
| 52 | + |
| 53 | +- **BossBar UI** — 재생 진행률, 경과 시간, 배속을 실시간으로 표시 |
| 54 | +- **속도 조절** — 0.25배 ~ 8배속까지 자유롭게 변경 |
| 55 | +- **일시정지/재개** — 특정 장면에서 멈추고 관찰 가능 |
| 56 | +- **고스트 렌더링** — ArmorStand(플레이어 헤드) + TextDisplay(이름표) + 파티클 궤적으로 유령을 시각화 |
| 57 | +- **뷰어 전용** — 고스트는 재생을 요청한 플레이어에게만 보입니다 |
| 58 | + |
| 59 | +--- |
| 60 | + |
| 61 | +## 📝 명령어 일람 |
| 62 | + |
| 63 | +### 일반 명령어 |
| 64 | + |
| 65 | +| 명령어 | 설명 | |
| 66 | +|--------|------| |
| 67 | +| `/specter help` | 도움말을 표시합니다 | |
| 68 | +| `/specter self [시간]` | 자신의 과거 행동을 재생합니다 (기본: 30분) | |
| 69 | +| `/specter stop` | 현재 재생을 정지합니다 | |
| 70 | +| `/specter pause` | 재생을 일시정지하거나 재개합니다 | |
| 71 | +| `/specter speed <배속>` | 재생 속도를 변경합니다 (0.25, 0.5, 1, 2, 4, 8) | |
| 72 | +| `/specter message <텍스트>` | 현재 위치에 유령 메시지를 남깁니다 | |
| 73 | +| `/specter message delete` | 가장 가까운 내 메시지를 삭제합니다 | |
| 74 | +| `/specter deaths [on/off]` | 사망 유령 표시를 켜거나 끕니다 | |
| 75 | +| `/specter zone` | 현재 위치의 스펙터 존 정보를 확인합니다 | |
| 76 | + |
| 77 | +### 관리자 명령어 |
| 78 | + |
| 79 | +| 명령어 | 권한 | 설명 | |
| 80 | +|--------|------|------| |
| 81 | +| `/specter replay <플레이어> [시간]` | `specter.admin.replay` | 다른 플레이어의 기록을 재생합니다 | |
| 82 | +| `/specter area <반경> [시간]` | `specter.admin.area` | 주변 영역의 모든 기록을 재생합니다 | |
| 83 | +| `/specter watch <플레이어>` | `specter.admin.watch` | 플레이어를 실시간 감시합니다 | |
| 84 | +| `/specter watch stop` | `specter.admin.watch` | 감시를 중단합니다 | |
| 85 | +| `/specter alerts [페이지]` | `specter.admin.alerts` | 보안 알림 목록을 확인합니다 | |
| 86 | +| `/specter alerts review <ID>` | `specter.admin.alerts` | 알림을 확인 처리합니다 | |
| 87 | +| `/specter alerts replay <ID>` | `specter.admin.alerts` | 알림 관련 기록을 재생합니다 | |
| 88 | +| `/specter reload` | `specter.admin.reload` | 설정을 다시 불러옵니다 | |
| 89 | +| `/specter stats` | `specter.admin.reload` | 스토리지 통계를 확인합니다 | |
| 90 | + |
| 91 | +> 💡 **별칭**: `/specter` 대신 `/sp` 또는 `/spc`를 사용할 수 있습니다. |
| 92 | +
|
| 93 | +--- |
| 94 | + |
| 95 | +## 📦 설치 방법 |
| 96 | + |
| 97 | +### 요구 사항 |
| 98 | + |
| 99 | +- **Paper 1.21.4** 이상 (Spigot은 지원하지 않습니다) |
| 100 | +- **Java 21** 이상 |
| 101 | + |
| 102 | +### 설치 순서 |
| 103 | + |
| 104 | +1. [Releases](../../releases) 페이지에서 최신 `Specter-x.x.x.jar`를 다운로드합니다. |
| 105 | +2. 서버의 `plugins/` 폴더에 넣습니다. |
| 106 | +3. 서버를 시작하거나 재시작합니다. |
| 107 | +4. `plugins/Specter/config.yml`이 자동으로 생성됩니다. 필요에 따라 수정하세요. |
| 108 | + |
| 109 | +### 직접 빌드 |
| 110 | + |
| 111 | +```bash |
| 112 | +git clone https://github.com/wjddusrb03/Specter.git |
| 113 | +cd Specter |
| 114 | +mvn clean package |
| 115 | +# target/Specter-1.0.0.jar 생성 |
| 116 | +``` |
| 117 | + |
| 118 | +--- |
| 119 | + |
| 120 | +## ⚙ 설정 파일 |
| 121 | + |
| 122 | +`plugins/Specter/config.yml`에서 모든 설정을 관리합니다. |
| 123 | + |
| 124 | +```yaml |
| 125 | +recording: |
| 126 | + enabled: true # 기록 시스템 활성화 |
| 127 | + position: |
| 128 | + min-distance: 0.5 # 위치 기록 최소 이동 거리 (블록) |
| 129 | + min-interval-ms: 100 # 위치 기록 최소 간격 (밀리초) |
| 130 | + actions: |
| 131 | + block-break: true # 블록 파괴 기록 |
| 132 | + block-place: true # 블록 설치 기록 |
| 133 | + entity-attack: true # 엔티티 공격 기록 |
| 134 | + container-open: true # 컨테이너 열기 기록 |
| 135 | + death: true # 사망 기록 |
| 136 | + session: |
| 137 | + duration-seconds: 300 # 세션 플러시 간격 (5분) |
| 138 | + |
| 139 | +storage: |
| 140 | + retention: |
| 141 | + hot-hours: 24 # 빠른 접근 보관 기간 |
| 142 | + warm-days: 7 # 일반 보관 기간 |
| 143 | + cold-days: 30 # 장기 보관 기간 |
| 144 | + death-days: 90 # 사망 기록 보관 기간 |
| 145 | + max-storage-mb: 5120 # 최대 저장 용량 (MB) |
| 146 | + |
| 147 | +gameplay: |
| 148 | + death-echo: |
| 149 | + enabled: true # 사망 유령 활성화 |
| 150 | + duration-minutes: 30 # 사망 유령 지속 시간 |
| 151 | + max-per-chunk: 5 # 청크당 최대 사망 유령 수 |
| 152 | + echo-message: |
| 153 | + enabled: true # 유령 메시지 활성화 |
| 154 | + duration-days: 7 # 메시지 유지 기간 |
| 155 | + max-per-player: 10 # 플레이어당 최대 메시지 수 |
| 156 | + |
| 157 | +security: |
| 158 | + alerts: |
| 159 | + enabled: true # 보안 알림 활성화 |
| 160 | + |
| 161 | +rendering: |
| 162 | + max-total-ghosts: 200 # 전체 최대 고스트 수 |
| 163 | + max-ghosts-per-viewer: 30 # 뷰어당 최대 고스트 수 |
| 164 | +``` |
| 165 | +
|
| 166 | +--- |
| 167 | +
|
| 168 | +## 🔑 권한 노드 |
| 169 | +
|
| 170 | +| 권한 | 기본값 | 설명 | |
| 171 | +|------|--------|------| |
| 172 | +| `specter.use` | `true` | 기본 명령어 사용 | |
| 173 | +| `specter.self` | `true` | 자기 재생 | |
| 174 | +| `specter.deaths` | `true` | 사망 유령 토글 | |
| 175 | +| `specter.message` | `true` | 유령 메시지 작성 | |
| 176 | +| `specter.admin.replay` | `op` | 타인 기록 재생 | |
| 177 | +| `specter.admin.area` | `op` | 영역 기록 재생 | |
| 178 | +| `specter.admin.watch` | `op` | 실시간 감시 | |
| 179 | +| `specter.admin.alerts` | `op` | 보안 알림 관리 | |
| 180 | +| `specter.admin.reload` | `op` | 설정 재로드 | |
| 181 | +| `specter.admin.*` | `op` | 모든 관리자 권한 | |
| 182 | + |
| 183 | +--- |
| 184 | + |
| 185 | +## 🔧 작동 원리 |
| 186 | + |
| 187 | +### 기록 시스템 |
| 188 | + |
| 189 | +``` |
| 190 | +플레이어 행동 → RecordingListener (MONITOR) → RecordingBuffer (메모리) |
| 191 | + ↓ (5분마다 자동 플러시) |
| 192 | + StorageManager |
| 193 | + ├─ SQLite (세션 메타데이터, 인덱스) |
| 194 | + └─ .echo 파일 (GZIP 압축 바이너리) |
| 195 | +``` |
| 196 | +
|
| 197 | +- **델타 기반 기록**: 위치가 0.5블록 이상 변경되었을 때만 기록 (성능 최적화) |
| 198 | +- **바이너리 포맷**: `"ECHO"` 매직 넘버 + 버전 + [액션타입 + 타임스탬프 + 데이터]* 구조 |
| 199 | +- **GZIP 압축**: 원본 대비 70~90% 용량 절감 |
| 200 | +
|
| 201 | +### 재생 시스템 |
| 202 | +
|
| 203 | +``` |
| 204 | +/specter self → PlaybackEngine (비동기 데이터 로드) |
| 205 | + ↓ |
| 206 | + PlaybackSession (틱 루프) |
| 207 | + ↓ |
| 208 | + GhostEntity (ArmorStand + TextDisplay + 파티클) |
| 209 | + ↓ |
| 210 | + 뷰어에게만 표시 (per-player visibility) |
| 211 | +``` |
| 212 | +
|
| 213 | +### 보안 감지 시스템 |
| 214 | +
|
| 215 | +| 감지 유형 | 기준 | |
| 216 | +|-----------|------| |
| 217 | +| `MASS_BREAK` | 짧은 시간 내 대량 블록 파괴 | |
| 218 | +| `XRAY_PATTERN` | 다이아몬드/에메랄드 등 희귀 광물 연속 채굴 | |
| 219 | +| `SPEED_ANOMALY` | 비정상적 이동 속도 | |
| 220 | +| `CONTAINER_RAID` | 짧은 시간 내 다수의 컨테이너 접근 | |
| 221 | +| `LAVA_PLACE` | 의심스러운 위치에 용암 배치 | |
| 222 | +
|
| 223 | +--- |
| 224 | +
|
| 225 | +## 📸 스크린샷 |
| 226 | +
|
| 227 | +> 스크린샷은 추후 추가 예정입니다. 직접 서버에서 사용해보세요! |
| 228 | +
|
| 229 | +--- |
| 230 | +
|
| 231 | +## ❓ 자주 묻는 질문 |
| 232 | +
|
| 233 | +**Q: Spigot에서도 작동하나요?** |
| 234 | +> A: 아닙니다. Paper 전용 API(Adventure, TextDisplay 등)를 사용하므로 **Paper 1.21.4 이상**에서만 작동합니다. |
| 235 | +
|
| 236 | +**Q: 서버 성능에 영향이 있나요?** |
| 237 | +> A: 최소한으로 설계되었습니다. 위치 기록은 델타 방식, DB 쓰기는 비동기 배치 처리, 고스트는 뷰어에게만 렌더링됩니다. 대규모 서버에서도 안정적으로 운영할 수 있습니다. |
| 238 | +
|
| 239 | +**Q: 저장 용량이 걱정됩니다.** |
| 240 | +> A: `config.yml`에서 `max-storage-mb`와 보관 기간을 조절할 수 있습니다. GZIP 압축으로 용량을 크게 절감합니다. |
| 241 | +
|
| 242 | +**Q: 고스트가 다른 플레이어에게도 보이나요?** |
| 243 | +> A: 아닙니다. 고스트는 재생을 요청한 플레이어에게만 보입니다. 다른 플레이어의 게임 경험에 영향을 주지 않습니다. |
| 244 | +
|
| 245 | +**Q: 기존 EchoWorld 데이터와 호환되나요?** |
| 246 | +> A: 바이너리 포맷(`"ECHO"` 헤더)은 동일하므로 `.echo` 파일은 호환됩니다. 단, 플러그인 폴더명이 변경되었으므로 데이터 폴더를 수동으로 이동해야 할 수 있습니다. |
| 247 | +
|
| 248 | +--- |
| 249 | +
|
| 250 | +## 🐛 문제 신고 / 기여 |
| 251 | +
|
| 252 | +버그를 발견하셨거나, 개선 아이디어가 있으시다면 언제든지 알려주세요! |
| 253 | +
|
| 254 | +### 문제 신고 방법 |
| 255 | +
|
| 256 | +1. [Issues](../../issues) 탭에서 **New Issue**를 클릭합니다. |
| 257 | +2. 아래 내용을 포함해주세요: |
| 258 | + - **문제 설명**: 어떤 상황에서 어떤 문제가 발생했는지 |
| 259 | + - **재현 방법**: 문제를 재현하는 단계 |
| 260 | + - **서버 환경**: Paper 버전, Java 버전, 다른 플러그인 목록 |
| 261 | + - **에러 로그**: 콘솔에 오류가 출력되었다면 함께 첨부해주세요 |
| 262 | +
|
| 263 | +### 기능 요청 |
| 264 | +
|
| 265 | +새로운 기능이 필요하시다면 Issues에 `[기능 요청]` 태그를 붙여 제안해주세요. |
| 266 | +어떤 의견이든 환영합니다! 🙌 |
| 267 | +
|
| 268 | +--- |
| 269 | +
|
| 270 | +## 📄 라이선스 |
| 271 | +
|
| 272 | +이 프로젝트는 [MIT License](LICENSE)를 따릅니다. |
| 273 | +
|
| 274 | +--- |
| 275 | +
|
| 276 | +<p align="center"> |
| 277 | + <b>⭐ 마음에 드셨다면 Star를 눌러주세요! ⭐</b> |
| 278 | +</p> |
0 commit comments