Files
mc_datapack/README.md
Claude (owner) 2b61af28a8 music_quiz: 무대 의존 제거 + 정적 데이터 스토리지화 + 매 틱 게이팅
- 무대 한정 코드 제거: repeat/map/ (트리/조명), images/image_custom (파이브가이즈),
  load.mcfunction의 map 스코어보드·fill·counter 초기화
- 매 틱 디스패치를 init 상태로 게이팅:
  · timer는 init>=2, check_answer는 init in {5,6}에서만 호출
  · idle(init=0) 틱의 함수 호출 8개 → 4개
- 곡 50개를 매크로 체인(250+ 명령/회) → 스토리지 리스트 O(1) 룩업으로 전환
  mq:init/songs가 mq:main.songs를 적재, setanswer는 index-1로 인덱스 룩업
- 버튼/트리거 정의를 mq:init/buttons / mq:init/triggers로 분리해
  mq:main.button_defs · trigger_defs 스토리지 리스트로 관리
- repeat/triggers/trigger.mcfunction: 투표 후처리 산술 블록 중 변하지 않는
  max_player·rest_player 재계산 제거, $(n)_player 갱신만 1라인
- 작가용 메모 수정.txt 제거
- README.md: 변경 사항·새 구조·스토리지 스키마 반영

566 lines -, 154 lines +.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 15:45:35 +09:00

255 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# mc_datapack
마인크래프트 자작 데이터팩 모음 저장소.
현재 포함된 데이터팩:
- `music_quiz/` — 음악퀴즈 데이터팩
---
## music_quiz — 음악퀴즈 데이터팩
플레이어가 노래를 듣고 정답을 맞히는 멀티플레이 음악 퀴즈.
관리자가 버튼/대화창으로 라운드를 진행하고, 참가자는 트리거 명령으로
정답·스킵·힌트·다시듣기 투표에 참여한다.
### 호환 버전
- **Minecraft 26.1.2** (pack_format `75`) 기준.
- 1.21.6에서 도입된 `dialog` 시스템, 1.21+의 단수형 `function/` 태그 폴더,
매크로 함수(`function ... with storage`) 기능을 사용한다.
- 텍스트 컴포넌트는 JSON 표기로 작성돼 있으며, 1.21.5 이후의 SNBT 파서와도
호환된다 (JSON은 SNBT의 부분집합).
### 의존 Bukkit 플러그인
데이터팩 자체만으로는 동작하지 않고, 다음 Bukkit 플러그인이 서버에 설치돼
있어야 한다:
- **YP** (`yp playall song<n>`) — 음원 재생용. 명령 블록을 통해 호출된다.
- **TS** (`ts placeloc <image>.jpg ...`) — 정답 이미지 표시용.
서버 측 상태는 `status` 스코어보드의 `yp`, `ts`, `skript` 값으로 추적하며,
플러그인 미설치 시 `mq:check/server`가 안내 타이틀을 띄운다.
### 게임 흐름과 상태 (`init` 스코어보드)
게임 전체 상태는 `main` 스코어보드의 가상 플레이어 `init` 값으로 관리한다.
| `init` | 단계 |
|--------|------|
| `0` | 정지/대기 (기본 상태) |
| `1` | 게임 시작 — page1 대화창에서 `ready` 트리거 대기 |
| `2` | 카운트다운 (3·2·1) |
| `4` | 곡 셋업 (한 틱 사이) |
| `5` | 곡 재생 + 정답 입력 단계 |
| `6` | 정답 공개·점수 부여 |
| `10` | 엔딩 시퀀스 |
`main` 스코어보드의 `timer`는 활성 상태에서만 증가하는 카운터로,
`mq:repeat/timer`가 이를 보고 상태 전이를 처리한다. 매 틱 디스패치는
`init` 값에 따라 게이팅된다.
### 트리거 명령
다음 명령은 `trigger` 타입 스코어보드로 등록돼 있어 어드벤처 모드의
일반 플레이어도 사용할 수 있다.
- `trigger ready` — 시작 안내 대화창에서 시작 확정
- `trigger cancel` — 시작 취소
- `trigger stop` — 다수결 종료
- `trigger skip` — 다수결 스킵 (현재 곡 패스)
- `trigger hint` — 다수결 힌트 요청 (자음 절반 가리기 — `func:hint`)
- `trigger replay` — 다수결 다시 듣기
스킵/힌트/리플레이는 `mq:repeat/triggers/trigger` 매크로 안에서
`max_player = ceil(전체/2)` 다수결 계산을 거친 뒤 실행된다. 트리거
정의 자체는 `mq:init/triggers`에서 storage 리스트로 관리된다.
### 입력 버튼
관리자가 사용하는 6개의 물리 스톤 버튼. 좌표·표면 방향·실행 명령은
`mq:init/buttons`에서 storage 리스트(`mq:main button_defs`)로 관리되며,
`mq:repeat/buttons/handler`가 매 틱 storage 인덱스로 `btn` 매크로를 호출한다.
- `start` / `stop` / `skip` / `hint` / `replay` / `test`
버튼 본체는 `interaction` 엔티티 + `redstone_block`-`red_wool` 토글
패턴으로 디바운스를 처리한다.
### 파일 구조
```
music_quiz/
├── pack.mcmeta # pack_format 75
└── data/
├── minecraft/tags/function/
│ ├── load.json # → mq:load
│ └── tick.json # → mq:tick
├── func/function/ # 공용 헬퍼 (length/half/shuffle/text_list/join…)
│ ─ mq:commands/hint에서 사용
└── mq/
├── function/
│ ├── load.mcfunction # 스코어보드·storage 초기화, init/* 호출
│ ├── tick.mcfunction # 매 틱 서브함수 디스패치 (init 게이팅)
│ ├── tellraw.mcfunction # 매크로 prefix 메시지 헬퍼
│ ├── init/ # 정적 데이터를 storage 로 적재
│ │ ├── songs.mcfunction # mq:main songs 리스트
│ │ ├── buttons.mcfunction # mq:main button_defs 리스트
│ │ └── triggers.mcfunction # mq:main trigger_defs 리스트
│ ├── check/server.mcfunction # YP / TS 설치 확인
│ ├── commands/ # start·stop·skip·hint·replay·test
│ ├── quiz/ # 게임 진행 로직
│ │ ├── start·select·play·correct·end·setanswer.mcfunction
│ │ └── macro/ # 매크로 진입점 (summon·setanswer·command_block)
│ ├── repeat/ # tick에서 호출되는 매 틱 처리
│ │ ├── players·check_answer·timer·check_server.mcfunction
│ │ ├── buttons/{handler,btn}.mcfunction
│ │ └── triggers/{handler,trigger}.mcfunction
│ ├── players/login.mcfunction
│ └── images/{image,image_set,image_delete}.mcfunction
├── dialog/page{1,2,3}.json
└── advancement/player/login.json
```
### 사용 스코어보드 / 스토리지
스코어보드:
- `main` — 게임 핵심 상태 (`init`, `index`, `max_index`, `timer`, `score`, `song_idx`)
- `status` — 외부 의존(YP·TS·Skript) 및 글로벌 타이머
- `buttons` — 물리 버튼 상태 머신
- `answer` — 플레이어별 정답 입력값 (`1`=정답, `2`=오답)
- `func.temp` — 산술용 임시 상수 (`two=2` 등)
- `leave_game``custom:leave_game` 통계 (재접속 감지)
- `score` — 사이드바 표시용 점수
- `ready` / `cancel` / `stop` / `skip` / `hint` / `replay` — 플레이어 트리거
스토리지:
- `mq:main` — 게임 전역 데이터
- `title`, `max_index`, `spawn` — 설정
- `answer` = `{title, author, alias}` — 현재 곡 정답
- `command_block` — 명령 블록 좌표/볼륨, 이미지 표시 영역, 작업용 alias 사본
- `songs` — 곡 목록 (`mq:init/songs` 가 채움)
- `button_defs` — 버튼 정의 (`mq:init/buttons` 가 채움)
- `trigger_defs` — 트리거 정의 (`mq:init/triggers` 가 채움)
- `mq:tmp` — setanswer 룩업용 임시 인덱스
- `func:temp``func:` 헬퍼 함수용 임시 NBT
### 곡 목록 수정
곡은 `data/mq/function/init/songs.mcfunction` 한 파일에 정의된다.
한 줄에 한 곡씩, 리스트로 append 한다:
```
data modify storage mq:main songs append value {title:"...", author:"...", alias:["...","..."]}
```
곡 순서가 게임 내 순서이며, `alias` 배열에 적은 문자열은 정답 판정에서
동의어로 인식된다. 곡 수를 늘리거나 줄이면 `mq:function/load.mcfunction`
`max_index` 기본값(50)도 함께 맞추는 것이 좋다.
### 설치
1. 서버 월드 폴더 `datapacks/``music_quiz/` 디렉터리째 복사.
2. YP, TS 플러그인 설치 확인.
3. 서버 `/reload` — 리로드 성공 메시지가 채팅에 표시되면 정상.
4. 좌표 `144, 62, -225` 부근에 6개 버튼이 자동 배치된다.
5. `start` 버튼을 눌러 게임 시작.
### 좌표 의존성 (주의)
다음 좌표가 데이터팩 안에 박혀 있어, 다른 월드에서 그대로 사용하려면
값을 바꿔야 한다:
- 명령 블록: `144 59 -219``mq:load``command_block` 초기값
- 플레이어 스폰: `144 61 -219` (`yaw 180`) — `mq:load``spawn` 초기값
- 버튼 좌표: `140..148, 62, -225` / `144, 62, -213``mq:init/buttons`
- 이미지 표시 영역: `131 77 -262` ~ `157 91 -262``mq:load``command_block.x1..z2`
---
## 변경 이력
### 2026-05-13 — 26.1.2 호환 + 1차 정리 (`b1babad`)
이전 푸시본(`6841b7a 이전퀴즈 데이터팩`)을 26.1.2 기준으로 정비.
- `pack_format` 69 → 75 (MC 26.1.2 / 1.21.11)
- `mq:load`, `mq:players/login`, `mq:commands/start`, `mq:commands/stop`,
`mq:quiz/start`, `mq:quiz/end`, `mq:repeat/buttons/btn` 등에 남아 있던
`# say ...` / `# stopsound` 사문화 디버그 주석 제거
### 2026-05-13 — 무대 의존 제거 + 최적화 (이번 커밋)
특정 맵 좌표에만 동작하던 장식 로직을 들어내고, 매 틱 부하와 정적
데이터 관리를 정비했다.
#### 삭제 (특정 맵 한정)
- `repeat/map/` 디렉터리 통째 — 무대 트리/조명 애니메이션 (`tree`, `lamp1`)
- `images/image_custom.mcfunction` — 파이브가이즈 간판 (호출자 없음)
- `data/mq/수정.txt` — 작가용 TODO 메모
- `load.mcfunction``map` 스코어보드 초기화, `tree map -1`, `lamp1 map -1`,
`fill 94 78 -279 194 78 -279 minecraft:red_wool`
- `tick.mcfunction``function mq:repeat/map/tree`, `function mq:repeat/map/lamp1`
#### 매 틱 부하 감소
- `tick.mcfunction` 디스패치를 `init` 상태로 게이팅:
- `repeat/timer``init >= 2` 일 때만
- `repeat/check_answer``init in {5, 6}` 일 때만
- `check_server` / `players` / `buttons/handler` / `triggers/handler`
항상 호출 (게임 비활성 상태에서도 시작 버튼·로그인 처리 필요)
- idle 틱(`init=0`)에서 함수 호출 8개 → 4개. 정답 스캔과 카운트다운 reset
로직이 빠진다.
#### 곡 관리 단순화
기존: `quiz/setanswer.mcfunction` 안에 50곡의 `function mq:quiz/macro/setanswer { index:N, title:..., author:..., alias:... }`
나열돼 있어, 매번 50개 매크로 호출 × 5라인 (`if score index matches N`
가드 포함) = 약 250 명령이 평가됐다.
변경:
- 곡 데이터를 `mq:init/songs` 에서 `mq:main.songs` 리스트로 한 번 적재
- `quiz/setanswer.mcfunction``index - 1` 을 계산해 `mq:tmp.idx` 에 저장
- `quiz/macro/setanswer.mcfunction` 은 매크로 한 줄로 룩업:
`data modify storage mq:main answer set from storage mq:main songs[$(idx)]`
- 호출당 3 라인의 storage 복사로 끝남 (50× → O(1))
#### 버튼/트리거 정의 분리
- 버튼 6개의 좌표·실행 명령을 `mq:init/buttons` 에서 `mq:main.button_defs`
리스트로 적재. `repeat/buttons/handler` 는 인덱스로 매크로 호출만 한다.
- 트리거 4개(stop/skip/hint/replay)도 동일하게 `mq:init/triggers`
`mq:main.trigger_defs` 로 분리.
- 버튼/트리거를 추가·제거할 때 `repeat/*/handler` 가 아닌 `init/*`
편집하면 된다.
#### 다수결 산술 dedup
`repeat/triggers/trigger.mcfunction` 에서 투표 갱신 전후로 `real_max_player`,
`rest_player`, `max_player` 를 두 번 계산했다. 이 값들은 (참가자 수에만
의존하므로) 한 틱 안에서 바뀌지 않는다. 갱신되는 것은 `$(n)_player`
(투표 수)뿐이라 — 후처리 블록은 `$(n)_player` 재계산 한 줄로 축약.
트리거당 5 라인 절감 × 4 트리거.
#### 다듬지 않은 부분 (의도된 동작)
- `mq:commands/test``mq:repeat/timer` 의 3중 `playsound` — 음량 강조용
스택 호출.
- `mq:quiz/play``auto 1b``0b` 토글 두 줄 — 명령 블록 강제 재발화
패턴.
- `mq:repeat/buttons/btn` 내부 상태머신 — 상태 -2/-1/0/1/2 전이 의미가
엮여 있어 라인 단축 시 디바운스가 깨질 위험이 있어 유지.
- `func:` 헬퍼는 `mq:commands/hint` 가 사용 중이므로 유지.
---
## 원격 저장소
- `https://git.tkrmagid.kr/tkrmagid/mc_datapack.git`