diff --git a/README.md b/README.md index a908b1d..a6cf272 100644 --- a/README.md +++ b/README.md @@ -22,16 +22,19 @@ - 텍스트 컴포넌트는 JSON 표기로 작성돼 있으며, 1.21.5 이후의 SNBT 파서와도 호환된다 (JSON은 SNBT의 부분집합). -### 의존 Bukkit 플러그인 +### 100% 바닐라 — 의존 플러그인 없음 -데이터팩 자체만으로는 동작하지 않고, 다음 Bukkit 플러그인이 서버에 설치돼 -있어야 한다: +음원 재생과 정답 이미지 표시는 모두 바닐라 명령으로 처리한다. 음원과 +페인팅 텍스처는 [minecraft_launcher](https://git.tkrmagid.kr/tkrmagid/minecraft_launcher) +가 만들어주는 리소스팩(`musicquiz` 네임스페이스)에서 가져온다. -- **YP** (`yp playall song`) — 음원 재생용. 명령 블록을 통해 호출된다. -- **TS** (`ts placeloc .jpg ...`) — 정답 이미지 표시용. +- 음원: `/playsound musicquiz:track_NN @s ~ ~ ~ ` + (예: `musicquiz:track_01`). 채널은 기본 `weather` — `stopsound` 와 함께 묶여 있다. +- 정답 이미지: `painting_variant musicquiz:cover_NN` 을 `/summon painting` 으로 + 벽에 띄우고, 다음 곡 직전 `kill @e[type=painting,tag=mq_cover]` 로 제거. -서버 측 상태는 `status` 스코어보드의 `yp`, `ts`, `skript` 값으로 추적하며, -플러그인 미설치 시 `mq:check/server`가 안내 타이틀을 띄운다. +리소스팩 트랙 번호와 `mq:init/songs` 리스트의 순서가 1:1로 일치해야 한다. +1번째 곡 → `track_01` / `cover_01`, … (2자리 zero-pad). ### 게임 흐름과 상태 (`init` 스코어보드) @@ -42,7 +45,6 @@ | `0` | 정지/대기 (기본 상태) | | `1` | 게임 시작 — page1 대화창에서 `ready` 트리거 대기 | | `2` | 카운트다운 (3·2·1) | -| `4` | 곡 셋업 (한 틱 사이) | | `5` | 곡 재생 + 정답 입력 단계 | | `6` | 정답 공개·점수 부여 | | `10` | 엔딩 시퀀스 | @@ -95,21 +97,28 @@ music_quiz/ │ ├── tick.mcfunction # 매 틱 서브함수 디스패치 (init 게이팅) │ ├── tellraw.mcfunction # 매크로 prefix 메시지 헬퍼 │ ├── init/ # 사용자 설정·정적 데이터 (수정 포인트) - │ │ ├── config.mcfunction # 주제·곡 개수·스폰·명령 블록 좌표 - │ │ ├── songs.mcfunction # 곡 목록 + │ │ ├── config.mcfunction # 주제·스폰·오디오·페인팅·marker 설정 + │ │ ├── songs.mcfunction # 곡 목록 + max_index 자동계산 │ │ ├── buttons.mcfunction # 버튼 좌표·실행 명령 │ │ └── triggers.mcfunction # 다수결 트리거 정의 - │ ├── 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) + │ │ ├── start·select·setanswer·correct·end.mcfunction + │ │ ├── play_sound·stop_sound.mcfunction # /playsound · /stopsound 래퍼 + │ │ └── macro/ # 매크로 진입점 + │ │ ├── setanswer.mcfunction # songs[$(idx)] → answer + track/cover id + │ │ ├── play_sound.mcfunction # $playsound 매크로 + │ │ ├── stop_sound.mcfunction # $stopsound 매크로 + │ │ └── summon{,2}.mcfunction # 정답 marker 엔티티 + alias 체인 + │ ├── images/ # 정답 페인팅 표시·제거 + │ │ ├── show.mcfunction # cover painting 소환 + │ │ ├── clear.mcfunction # cover painting 일괄 제거 + │ │ └── macro/show.mcfunction # $summon painting 매크로 │ ├── repeat/ # tick에서 호출되는 매 틱 처리 - │ │ ├── players·check_answer·timer·check_server.mcfunction + │ │ ├── players·check_answer·timer.mcfunction │ │ ├── buttons/{handler,btn}.mcfunction │ │ └── triggers/{handler,trigger}.mcfunction - │ ├── players/login.mcfunction - │ └── images/{image,image_set,image_delete}.mcfunction + │ └── players/login.mcfunction ├── dialog/page{1,2,3}.json └── advancement/player/login.json ``` @@ -119,7 +128,6 @@ music_quiz/ 스코어보드: - `main` — 게임 핵심 상태 (`init`, `index`, `max_index`, `timer`, `score`, `song_idx`) -- `status` — 외부 의존(YP·TS·Skript) 및 글로벌 타이머 - `buttons` — 물리 버튼 상태 머신 - `answer` — 플레이어별 정답 입력값 (`1`=정답, `2`=오답) - `func.temp` — 산술용 임시 상수 (`two=2` 등) @@ -131,12 +139,13 @@ music_quiz/ - `mq:main` — 게임 전역 데이터 - `title`, `max_index`, `spawn` — 설정 - - `answer` = `{title, author, alias}` — 현재 곡 정답 - - `command_block` — 명령 블록 좌표/볼륨, 이미지 표시 영역, 작업용 alias 사본 + - `audio` = `{namespace, source, volume, pitch}` — `/playsound` 파라미터 + - `image` = `{namespace, x, y, z, facing}` — 정답 페인팅 좌표 + - `marker` = `{x, y, z}` — 정답 입력 marker 엔티티 위치 + - `answer` = `{title, author, alias, track, cover}` — 현재 곡 정답 - `songs` — 곡 목록 (`mq:init/songs` 가 채움) - - `button_defs` — 버튼 정의 (`mq:init/buttons` 가 채움) - - `trigger_defs` — 트리거 정의 (`mq:init/triggers` 가 채움) -- `mq:tmp` — setanswer 룩업용 임시 인덱스 + - `button_defs` / `trigger_defs` — 버튼·트리거 정의 +- `mq:tmp` — setanswer·play_sound·페인팅 호출용 임시 페이로드 (idx, pad, num, playsound, painting, marker_call) - `func:temp` — `func:` 헬퍼 함수용 임시 NBT ### 설정 (한 곳에서 수정) @@ -144,11 +153,13 @@ music_quiz/ 세계마다 다른 값은 모두 `data/mq/function/init/` 폴더에서 편집한다. `/reload` 후 반영된다. -- **`init/config.mcfunction`** — 주제, 곡 개수, 스폰 위치, 음원 명령 블록 - 좌표, 정답 이미지 표시 영역. `title` 은 `[ … ]` 채팅 접두사로도 사용된다. -- **`init/songs.mcfunction`** — 곡 목록 (한 줄에 한 곡씩 append). - `alias` 배열의 문자열은 정답 판정 시 동의어로 인정된다. 곡 수를 바꾸면 - `init/config.mcfunction` 의 `max_index` 도 함께 맞춰야 한다. +- **`init/config.mcfunction`** — 주제, 스폰 위치, 오디오 설정(`audio`), + 정답 페인팅 좌표(`image`), marker 엔티티 좌표. `title` 은 `[ … ]` + 채팅 접두사로도 사용된다. +- **`init/songs.mcfunction`** — 곡 목록 (한 줄에 한 곡씩 append). `alias` + 배열의 문자열은 정답 판정 시 동의어로 인정된다. **곡의 순서가 리소스팩 + 트랙 번호와 1:1 매칭** 되므로 순서 변경 시 리소스팩도 함께 재생성해야 + 한다. `max_index` 는 리스트 길이로 자동 계산된다. - **`init/buttons.mcfunction`** — 6개 물리 버튼의 좌표·표면 방향·실행 명령. - **`init/triggers.mcfunction`** — 다수결 트리거(`stop`/`skip`/`hint`/`replay`) 표시 이름·실행 명령. @@ -163,7 +174,8 @@ JSON 텍스트 컴포넌트가 storage 참조를 일관되게 지원하지 않 ### 설치 1. 서버 월드 폴더 `datapacks/`에 `music_quiz/` 디렉터리째 복사. -2. YP, TS 플러그인 설치 확인. +2. minecraft_launcher 에서 생성한 `musicquiz` 리소스팩을 클라이언트에 적용 + (런처가 자동 처리). 3. 서버 `/reload` — 리로드 성공 메시지가 채팅에 표시되면 정상. 4. 좌표 `144, 62, -225` 부근에 6개 버튼이 자동 배치된다. 5. `start` 버튼을 눌러 게임 시작. @@ -171,12 +183,12 @@ JSON 텍스트 컴포넌트가 storage 참조를 일관되게 지원하지 않 ### 좌표 의존성 (주의) 다음 좌표가 데이터팩 안에 박혀 있어, 다른 월드에서 그대로 사용하려면 -값을 바꿔야 한다: +`init/config.mcfunction` 의 값을 바꿔야 한다: -- 명령 블록: `144 59 -219` — `mq:load` 의 `command_block` 초기값 -- 플레이어 스폰: `144 61 -219` (`yaw 180`) — `mq:load` 의 `spawn` 초기값 +- 정답 입력 marker: `144 59 -219` — `marker.{x,y,z}` +- 정답 페인팅: `144 84 -261` (facing south) — `image.{x,y,z,facing}` +- 플레이어 스폰: `144 61 -219` (yaw 180) — `spawn` - 버튼 좌표: `140..148, 62, -225` / `144, 62, -213` — `mq:init/buttons` -- 이미지 표시 영역: `131 77 -262` ~ `157 91 -262` — `mq:load` 의 `command_block.x1..z2` --- @@ -191,70 +203,81 @@ JSON 텍스트 컴포넌트가 storage 참조를 일관되게 지원하지 않 `mq:quiz/start`, `mq:quiz/end`, `mq:repeat/buttons/btn` 등에 남아 있던 `# say ...` / `# stopsound` 사문화 디버그 주석 제거 -### 2026-05-13 — 무대 의존 제거 + 최적화 (이번 커밋) +### 2026-05-13 — 무대 의존 제거 + 최적화 (`2b61af2`) 특정 맵 좌표에만 동작하던 장식 로직을 들어내고, 매 틱 부하와 정적 데이터 관리를 정비했다. -#### 삭제 (특정 맵 한정) +- `repeat/map/` (무대 트리/조명 애니메이션) 삭제 +- `images/image_custom.mcfunction` (호출자 없는 사문화 코드) 삭제 +- `tick.mcfunction` 디스패치를 `init` 상태로 게이팅 (idle 틱 함수 호출 8→4) +- 곡 데이터를 `mq:init/songs` 의 `mq:main.songs` 리스트로 한 번 적재. + 매크로 룩업 한 줄로 50× → O(1) 복사 +- 버튼/트리거 정의를 `mq:init/buttons` / `mq:init/triggers` 의 storage + 리스트로 분리. handler 는 인덱스로 매크로 호출만 한다. +- 다수결 산술 dedup (트리거당 5 라인 절감 × 4 트리거) -- `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` +### 2026-05-13 — 설정 통합 (`b236118`) -#### 매 틱 부하 감소 +세계별 수정 포인트를 한 파일로 모았다. -- `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 - 로직이 빠진다. +- `init/config.mcfunction` 신설 — 주제·곡 개수·스폰·명령 블록 좌표를 한곳에 +- `mq:tellraw` 가 `mq:main.title` 을 읽도록 변경 ([ 주제 ] 접두사 동기화) -#### 곡 관리 단순화 +### 2026-05-13 — 바닐라 마이그레이션 (이번 커밋) -기존: `quiz/setanswer.mcfunction` 안에 50곡의 `function mq:quiz/macro/setanswer { index:N, title:..., author:..., alias:... }` 가 -나열돼 있어, 매번 50개 매크로 호출 × 5라인 (`if score index matches N` -가드 포함) = 약 250 명령이 평가됐다. +YP / TS Bukkit 플러그인 의존을 제거하고, 음원과 정답 이미지를 바닐라 +명령으로 재구현했다. [minecraft_launcher](https://git.tkrmagid.kr/tkrmagid/minecraft_launcher) +가 생성하는 `musicquiz` 리소스팩과 한 쌍으로 동작한다. -변경: +#### 삭제 -- 곡 데이터를 `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)) +- `mq:check/server` + `mq:repeat/check_server` — 플러그인 설치 확인 로직 +- `mq:quiz/macro/command_block` — `data modify block … Command` + `auto` + 토글 패턴 (YP `playall` 호출용) +- `mq:quiz/play` — 명령 블록 강제 재발화 함수 +- `mq:images/image{,_set,_delete}` — TS `placeloc` / `removeall` 호출 +- `status` 스코어보드 (`yp`, `ts`, `skript`, `timer`) — 플러그인 hello 패킷 + 대기에만 쓰이던 객체 -#### 버튼/트리거 정의 분리 +#### 신설 -- 버튼 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/*` 만 - 편집하면 된다. +- **음원** — `mq:quiz/play_sound` → `mq:quiz/macro/play_sound`: + `$execute as @a at @s run playsound $(namespace):$(track) $(source) @s ~ ~ ~ $(volume) $(pitch)` +- **음원 정지** — `mq:quiz/stop_sound` → `mq:quiz/macro/stop_sound`: + `$stopsound @a $(source)` (모든 stopsound 호출 합쳐서 매크로화) +- **정답 페인팅** — `mq:images/show` → `mq:images/macro/show`: + `$summon minecraft:painting $(x) $(y) $(z) {variant:"$(namespace):$(cover)",facing:$(facing)b,Tags:["mq","mq_cover"]}` +- **정답 페인팅 제거** — `mq:images/clear`: `kill @e[type=painting,tag=mq_cover]` -#### 다수결 산술 dedup +#### 스토리지 재구성 -`repeat/triggers/trigger.mcfunction` 에서 투표 갱신 전후로 `real_max_player`, -`rest_player`, `max_player` 를 두 번 계산했다. 이 값들은 (참가자 수에만 -의존하므로) 한 틱 안에서 바뀌지 않는다. 갱신되는 것은 `$(n)_player` -(투표 수)뿐이라 — 후처리 블록은 `$(n)_player` 재계산 한 줄로 축약. -트리거당 5 라인 절감 × 4 트리거. +- `command_block` 컴파운드(좌표·볼륨·이미지 영역·alias 사본을 한데 묶었던 + 것) 폐기 +- `audio` = `{namespace, source, volume, pitch}` 신설 — `/playsound` 인자 +- `image` = `{namespace, x, y, z, facing}` 신설 — `/summon painting` 좌표 +- `marker` = `{x, y, z}` 신설 — 정답 입력 marker 위치 +- `answer.track` / `answer.cover` 필드 추가 — 라운드별 리소스팩 ID + (`track_NN` / `cover_NN`) +- `max_index` 는 `mq:init/songs` 끝에서 `songs` 배열 길이로 자동 계산 + (수동 동기화 필요 없음) -#### 다듬지 않은 부분 (의도된 동작) +#### 트랙 번호 padding -- `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` 가 사용 중이므로 유지. +mcfunction 은 문자열 zero-pad 가 없으므로, `quiz/select` 에서 +`index ∈ 1..9` 일 때만 `mq:tmp.pad="0"` 로 분기시키고, 매크로 안에서 +`"track_$(pad)$(num)"` 로 조립한다. + +#### 기타 + +- `tick.mcfunction` 에서 `mq:repeat/check_server` 제거 (매 틱 함수 호출 + 4→3 으로 추가 감소) +- `commands/start` / `commands/stop` / `commands/replay` 의 하드코딩된 + `stopsound @a weather` 를 모두 `function mq:quiz/stop_sound` 로 교체 + — 채널 변경 시 `audio.source` 한 곳만 수정하면 됨 +- `setanswer` 호출 경로 단축: 기존 `select → macro/command_block → + play(auto-toggle) → setanswer → macro/setanswer + macro/summon` → + 현재 `select → setanswer → macro/setanswer → macro/summon → play_sound` --- diff --git a/music_quiz/data/mq/function/check/server.mcfunction b/music_quiz/data/mq/function/check/server.mcfunction deleted file mode 100644 index 61d192a..0000000 --- a/music_quiz/data/mq/function/check/server.mcfunction +++ /dev/null @@ -1,3 +0,0 @@ -title @a times 0t 20t 0t -title @a subtitle {"text":"이 맵은 버킷 서버에서 열어야 합니다."} -title @a title {"text":"오류 발생!","color":"red"} diff --git a/music_quiz/data/mq/function/commands/replay.mcfunction b/music_quiz/data/mq/function/commands/replay.mcfunction index 2bb164f..59383f1 100644 --- a/music_quiz/data/mq/function/commands/replay.mcfunction +++ b/music_quiz/data/mq/function/commands/replay.mcfunction @@ -5,5 +5,5 @@ execute if score init main matches 1..4 run return run function mq:tellraw {"tex execute if score init main matches 6.. run return run function mq:tellraw {"text":"아직 다음노래가 재생되지 않았습니다.","color":"red",msg:'""'} execute if score init main matches 10 run return run function mq:tellraw {"text":"퀴즈가 종료되었습니다.","color":"red",msg:'""'} -execute if score init main matches 5 run stopsound @a weather -execute if score init main matches 5 run function mq:quiz/macro/command_block with storage mq:main command_block +execute if score init main matches 5 run function mq:quiz/stop_sound +execute if score init main matches 5 run function mq:quiz/play_sound diff --git a/music_quiz/data/mq/function/commands/start.mcfunction b/music_quiz/data/mq/function/commands/start.mcfunction index 1f7c470..d2a7220 100644 --- a/music_quiz/data/mq/function/commands/start.mcfunction +++ b/music_quiz/data/mq/function/commands/start.mcfunction @@ -2,7 +2,7 @@ execute if score init main matches 10 run return run function mq:tellraw {"text" setblock ~ ~ ~ minecraft:air -stopsound @a weather +function mq:quiz/stop_sound $scoreboard players set max_index main $(max_index) scoreboard players set init main 1 diff --git a/music_quiz/data/mq/function/commands/stop.mcfunction b/music_quiz/data/mq/function/commands/stop.mcfunction index 9699a6d..f2ba1d6 100644 --- a/music_quiz/data/mq/function/commands/stop.mcfunction +++ b/music_quiz/data/mq/function/commands/stop.mcfunction @@ -1,8 +1,3 @@ -scoreboard players set timer status 0 -scoreboard players set skript status 0 -scoreboard players set yp status 0 -scoreboard players set ts status 0 - scoreboard players set index main 0 $scoreboard players set max_index main $(max_index) scoreboard players set score main 0 @@ -43,8 +38,6 @@ scoreboard objectives remove score scoreboard objectives add score dummy {"text":"점수","bold":true} scoreboard objectives setdisplay sidebar score -data modify storage mq:main command_block.index set value 1 - dialog clear @a bossbar set mq:process name [{"text":"진행도: ","color": "yellow","bold": true},{"score":{"name":"index","objective": "main"},"color": "yellow","bold": true},{"text":"/","color": "yellow","bold": true},{"score":{"name":"max_index","objective": "main"},"color": "yellow","bold": true}] @@ -55,9 +48,12 @@ bossbar set mq:process visible false bossbar set mq:process style notched_10 bossbar set mq:process players @a -data modify storage mq:main command_block.name set value "음악퀴즈" -function mq:quiz/macro/summon with storage mq:main command_block +# 대기 상태 marker 1개만 소환 (answer.title="음악퀴즈" 가 sentinel) +data modify storage mq:main answer set value {title:"음악퀴즈", alias:[]} +data modify storage mq:tmp marker_call set from storage mq:main marker +data modify storage mq:tmp marker_call.name set value "음악퀴즈" +data modify storage mq:tmp marker_call.alias set value [] +function mq:quiz/macro/summon with storage mq:tmp marker_call -stopsound @a weather - -function mq:images/image_delete with storage mq:main command_block +function mq:quiz/stop_sound +function mq:images/clear diff --git a/music_quiz/data/mq/function/images/clear.mcfunction b/music_quiz/data/mq/function/images/clear.mcfunction new file mode 100644 index 0000000..01210ae --- /dev/null +++ b/music_quiz/data/mq/function/images/clear.mcfunction @@ -0,0 +1 @@ +kill @e[type=minecraft:painting,tag=mq_cover] diff --git a/music_quiz/data/mq/function/images/image.mcfunction b/music_quiz/data/mq/function/images/image.mcfunction deleted file mode 100644 index 538f8df..0000000 --- a/music_quiz/data/mq/function/images/image.mcfunction +++ /dev/null @@ -1,3 +0,0 @@ -$data modify storage mq:main command_block.image set value "ts placeloc song$(index).jpg world SOUTH $(x1) $(y1) $(z1) $(x2) $(y2) $(z2) 1 솔리드스킵" - -function mq:images/image_set with storage mq:main command_block diff --git a/music_quiz/data/mq/function/images/image_delete.mcfunction b/music_quiz/data/mq/function/images/image_delete.mcfunction deleted file mode 100644 index aa84659..0000000 --- a/music_quiz/data/mq/function/images/image_delete.mcfunction +++ /dev/null @@ -1,4 +0,0 @@ -$data modify block $(x) $(y) $(z) Command set value "ts removeall" - -$data modify block $(x) $(y) $(z) auto set value 1b -$data modify block $(x) $(y) $(z) auto set value 0b diff --git a/music_quiz/data/mq/function/images/image_set.mcfunction b/music_quiz/data/mq/function/images/image_set.mcfunction deleted file mode 100644 index 73c4d68..0000000 --- a/music_quiz/data/mq/function/images/image_set.mcfunction +++ /dev/null @@ -1,4 +0,0 @@ -$data modify block $(x) $(y) $(z) Command set value "$(image)" - -$data modify block $(x) $(y) $(z) auto set value 1b -$data modify block $(x) $(y) $(z) auto set value 0b diff --git a/music_quiz/data/mq/function/images/macro/show.mcfunction b/music_quiz/data/mq/function/images/macro/show.mcfunction new file mode 100644 index 0000000..ec54eb8 --- /dev/null +++ b/music_quiz/data/mq/function/images/macro/show.mcfunction @@ -0,0 +1 @@ +$summon minecraft:painting $(x) $(y) $(z) {variant:"$(namespace):$(cover)",facing:$(facing)b,Tags:["mq","mq_cover"]} diff --git a/music_quiz/data/mq/function/images/show.mcfunction b/music_quiz/data/mq/function/images/show.mcfunction new file mode 100644 index 0000000..bed4b7d --- /dev/null +++ b/music_quiz/data/mq/function/images/show.mcfunction @@ -0,0 +1,3 @@ +data modify storage mq:tmp painting set from storage mq:main image +data modify storage mq:tmp painting.cover set from storage mq:main answer.cover +function mq:images/macro/show with storage mq:tmp painting diff --git a/music_quiz/data/mq/function/init/config.mcfunction b/music_quiz/data/mq/function/init/config.mcfunction index 6e30a24..2c41573 100644 --- a/music_quiz/data/mq/function/init/config.mcfunction +++ b/music_quiz/data/mq/function/init/config.mcfunction @@ -1,26 +1,23 @@ # 음악퀴즈 주제 — tellraw 접두사([ 이름 ])와 사이드바 표시에 사용 data modify storage mq:main title set value "음악퀴즈" -# 곡 개수 — init/songs.mcfunction 의 곡 수와 일치시킬 것 -data modify storage mq:main max_index set value 50 - # 플레이어 접속 시 텔레포트 위치 (x y z, r=yaw, f=pitch) data modify storage mq:main spawn set value {x: 144, y: 61, z: -219, r: 180, f: 0} -# 음원 재생용 명령 블록 위치 + 정답 이미지 표시 영역 -# x,y,z — 명령 블록 좌표 -# r — 명령 블록 정면 방향 (EAST | WEST | SOUTH | NORTH) -# volume — yp playall 명령에 넘기는 음량 -# x1,y1,z1 — 이미지 표시 영역 한쪽 모서리 -# x2,y2,z2 — 이미지 표시 영역 반대 모서리 -data modify storage mq:main command_block set value { \ - name: "", \ - image: "", \ - alias: [], \ - index: 1, \ - volume: 30, \ - x: 144, y: 59, z: -219, \ - r: "SOUTH", \ - x1: 131, y1: 77, z1: -262, \ - x2: 157, y2: 91, z2: -262 \ -} +# 음원 재생 — minecraft_launcher 리소스팩의 musicquiz:track_NN 사운드 이벤트 +# namespace — 리소스팩 네임스페이스 (기본 "musicquiz") +# source — /playsound 채널. stopsound 와 동일해야 함 (기본 "weather") +# volume — 기본 음량. 곡별 override 는 init/songs.mcfunction 의 volume 필드 사용 +# pitch — 1.0 = 원본 속도 +data modify storage mq:main audio set value {namespace: "musicquiz", source: "weather", volume: 1.0, pitch: 1.0} + +# 정답 페인팅 — minecraft_launcher 리소스팩의 musicquiz:cover_NN painting_variant +# namespace — painting_variant 네임스페이스 (기본 "musicquiz") +# x,y,z — 페인팅 entity 좌표 (벽면 앞쪽 블록 위치) +# facing — 페인팅이 바라보는 방향: south=0 / west=1 / north=2 / east=3 +data modify storage mq:main image set value {namespace: "musicquiz", x: 144, y: 84, z: -261, facing: 0b} + +# 정답 입력용 marker entity 소환 좌표 +data modify storage mq:main marker set value {x: 144, y: 59, z: -219} + +# 곡 개수 max_index 는 init/songs.mcfunction 의 길이로 자동 계산됨 diff --git a/music_quiz/data/mq/function/init/songs.mcfunction b/music_quiz/data/mq/function/init/songs.mcfunction index a0851fb..10b2655 100644 --- a/music_quiz/data/mq/function/init/songs.mcfunction +++ b/music_quiz/data/mq/function/init/songs.mcfunction @@ -1,3 +1,9 @@ +# 곡 한 개 = 한 줄. +# 필수 — title, author, alias +# 선택 — volume (이 곡만의 /playsound 음량. 미지정시 init/config.mcfunction +# 의 audio.volume 사용) +# 곡 순서가 리소스팩의 track_NN / cover_NN 인덱스와 1:1 매칭된다. +# 예) {title:"Quiet Song", author:"...", alias:[...], volume:2.0} data modify storage mq:main songs set value [] data modify storage mq:main songs append value {title:"Lose My Mind", author:"Don Toliver", alias:["루즈 마이 마인드","루스 마이 마인드","ㅣㅐㄴㄷ ㅡㅛ ㅡㅑㅜㅇ"]} data modify storage mq:main songs append value {title:"The Chase", author:"Hearts2Hearts", alias:["더 체이즈","더 체이스","솓 촘ㄴㄷ"]} @@ -49,3 +55,6 @@ data modify storage mq:main songs append value {title:"XOXZ", author:"IVE", alia data modify storage mq:main songs append value {title:"여름이었다", author:"H1-KEY", alias:[]} data modify storage mq:main songs append value {title:"LOV3", author:"식케이", alias:["럽3","ㅣㅐㅍ3"]} data modify storage mq:main songs append value {title:"Drive", author:"Ed Sheeran", alias:["드라이브","ㅇ걒ㄷ"]} + +# 곡 개수는 songs 배열 길이에서 자동 계산됨 +execute store result storage mq:main max_index int 1 run data get storage mq:main songs diff --git a/music_quiz/data/mq/function/load.mcfunction b/music_quiz/data/mq/function/load.mcfunction index 196ac18..9845e29 100644 --- a/music_quiz/data/mq/function/load.mcfunction +++ b/music_quiz/data/mq/function/load.mcfunction @@ -1,4 +1,4 @@ -data modify storage mq:main answer set value {author: "", title: "", alias: []} +data modify storage mq:main answer set value {title:"", author:"", alias:[]} data merge storage func:temp {} data merge storage mq:tmp {} @@ -10,24 +10,17 @@ function mq:init/triggers function mq:tellraw {"text":"서버 리로드 성공!","color":"white","msg":'""'} scoreboard objectives remove func.temp -scoreboard objectives remove status scoreboard objectives remove main scoreboard objectives remove buttons scoreboard objectives remove answer scoreboard objectives remove leave_game scoreboard objectives add func.temp dummy -scoreboard objectives add status dummy scoreboard objectives add main dummy scoreboard objectives add buttons dummy scoreboard objectives add answer dummy scoreboard objectives add leave_game custom:leave_game -scoreboard players set timer status 0 -scoreboard players set skript status 0 -scoreboard players set yp status 0 -scoreboard players set ts status 0 - scoreboard players set two func.temp 2 bossbar add mq:process [{"text":"진행도: ","color": "yellow","bold": true},{"text":"0","color": "yellow","bold": true},{"text":"/","color": "yellow","bold": true},{"text":"0","color": "yellow","bold": true}] diff --git a/music_quiz/data/mq/function/quiz/correct.mcfunction b/music_quiz/data/mq/function/quiz/correct.mcfunction index ec103de..a667333 100644 --- a/music_quiz/data/mq/function/quiz/correct.mcfunction +++ b/music_quiz/data/mq/function/quiz/correct.mcfunction @@ -29,4 +29,4 @@ scoreboard players set replay buttons -3 scoreboard players set timer main 1 -function mq:images/image with storage mq:main command_block +function mq:images/show diff --git a/music_quiz/data/mq/function/quiz/macro/command_block.mcfunction b/music_quiz/data/mq/function/quiz/macro/command_block.mcfunction deleted file mode 100644 index 74f783d..0000000 --- a/music_quiz/data/mq/function/quiz/macro/command_block.mcfunction +++ /dev/null @@ -1,3 +0,0 @@ -$data modify block $(x) $(y) $(z) Command set value "yp playall song$(index) $(volume)" - -function mq:quiz/play with storage mq:main command_block diff --git a/music_quiz/data/mq/function/quiz/macro/play_sound.mcfunction b/music_quiz/data/mq/function/quiz/macro/play_sound.mcfunction new file mode 100644 index 0000000..b0def6a --- /dev/null +++ b/music_quiz/data/mq/function/quiz/macro/play_sound.mcfunction @@ -0,0 +1 @@ +$execute as @a at @s run playsound $(namespace):$(track) $(source) @s ~ ~ ~ $(volume) $(pitch) diff --git a/music_quiz/data/mq/function/quiz/macro/setanswer.mcfunction b/music_quiz/data/mq/function/quiz/macro/setanswer.mcfunction index 11c1bc2..b36889d 100644 --- a/music_quiz/data/mq/function/quiz/macro/setanswer.mcfunction +++ b/music_quiz/data/mq/function/quiz/macro/setanswer.mcfunction @@ -1,3 +1,3 @@ $data modify storage mq:main answer set from storage mq:main songs[$(idx)] -$data modify storage mq:main command_block.name set from storage mq:main songs[$(idx)].title -$data modify storage mq:main command_block.alias set from storage mq:main songs[$(idx)].alias +$data modify storage mq:main answer.track set value "track_$(pad)$(num)" +$data modify storage mq:main answer.cover set value "cover_$(pad)$(num)" diff --git a/music_quiz/data/mq/function/quiz/macro/stop_sound.mcfunction b/music_quiz/data/mq/function/quiz/macro/stop_sound.mcfunction new file mode 100644 index 0000000..7f1364b --- /dev/null +++ b/music_quiz/data/mq/function/quiz/macro/stop_sound.mcfunction @@ -0,0 +1 @@ +$stopsound @a $(source) diff --git a/music_quiz/data/mq/function/quiz/macro/summon.mcfunction b/music_quiz/data/mq/function/quiz/macro/summon.mcfunction index 560c658..ecade67 100644 --- a/music_quiz/data/mq/function/quiz/macro/summon.mcfunction +++ b/music_quiz/data/mq/function/quiz/macro/summon.mcfunction @@ -1,8 +1,9 @@ -$execute unless data storage mq:main {command_block:{name:"음악퀴즈"}} run summon minecraft:marker $(x) $(y) $(z) {Tags:["mq","default"],CustomName:"정답입력시작"} +$execute unless data storage mq:main {answer:{title:"음악퀴즈"}} run summon minecraft:marker $(x) $(y) $(z) {Tags:["mq","default"],CustomName:"정답입력시작"} $summon minecraft:marker $(x) $(y) $(z) {Tags:["mq","default"],CustomName:"$(name)"} -execute store result score length func.temp run data get storage mq:main command_block.alias -execute if score length func.temp matches 1.. run data modify storage mq:main command_block.name set from storage mq:main command_block.alias[0] -execute if score length func.temp matches 1.. run data remove storage mq:main command_block.alias[0] -execute if score length func.temp matches 1.. run function mq:quiz/macro/summon2 with storage mq:main command_block -$execute unless data storage mq:main {command_block:{name:"음악퀴즈"}} run summon minecraft:marker $(x) $(y) $(z) {Tags:["mq","default"],CustomName:"정답입력종료"} +execute store result score length func.temp run data get storage mq:tmp marker_call.alias +execute if score length func.temp matches 1.. run data modify storage mq:tmp marker_call.name set from storage mq:tmp marker_call.alias[0] +execute if score length func.temp matches 1.. run data remove storage mq:tmp marker_call.alias[0] +execute if score length func.temp matches 1.. run function mq:quiz/macro/summon2 with storage mq:tmp marker_call + +$execute unless data storage mq:main {answer:{title:"음악퀴즈"}} run summon minecraft:marker $(x) $(y) $(z) {Tags:["mq","default"],CustomName:"정답입력종료"} diff --git a/music_quiz/data/mq/function/quiz/macro/summon2.mcfunction b/music_quiz/data/mq/function/quiz/macro/summon2.mcfunction index d92f90c..062d8e1 100644 --- a/music_quiz/data/mq/function/quiz/macro/summon2.mcfunction +++ b/music_quiz/data/mq/function/quiz/macro/summon2.mcfunction @@ -1,6 +1,6 @@ $summon minecraft:marker $(x) $(y) $(z) {Tags:["mq","default"],CustomName:"$(name)"} -execute store result score length func.temp run data get storage mq:main command_block.alias -execute if score length func.temp matches 1.. run data modify storage mq:main command_block.name set from storage mq:main command_block.alias[0] -execute if score length func.temp matches 1.. run data remove storage mq:main command_block.alias[0] -execute if score length func.temp matches 1.. run function mq:quiz/macro/summon2 with storage mq:main command_block \ No newline at end of file +execute store result score length func.temp run data get storage mq:tmp marker_call.alias +execute if score length func.temp matches 1.. run data modify storage mq:tmp marker_call.name set from storage mq:tmp marker_call.alias[0] +execute if score length func.temp matches 1.. run data remove storage mq:tmp marker_call.alias[0] +execute if score length func.temp matches 1.. run function mq:quiz/macro/summon2 with storage mq:tmp marker_call diff --git a/music_quiz/data/mq/function/quiz/play.mcfunction b/music_quiz/data/mq/function/quiz/play.mcfunction deleted file mode 100644 index f6ce5a1..0000000 --- a/music_quiz/data/mq/function/quiz/play.mcfunction +++ /dev/null @@ -1,6 +0,0 @@ -scoreboard players set init main 4 - -$data modify block $(x) $(y) $(z) auto set value 1b -$data modify block $(x) $(y) $(z) auto set value 0b - -function mq:quiz/setanswer diff --git a/music_quiz/data/mq/function/quiz/play_sound.mcfunction b/music_quiz/data/mq/function/quiz/play_sound.mcfunction new file mode 100644 index 0000000..be1f1a7 --- /dev/null +++ b/music_quiz/data/mq/function/quiz/play_sound.mcfunction @@ -0,0 +1,5 @@ +data modify storage mq:tmp playsound set from storage mq:main audio +data modify storage mq:tmp playsound.track set from storage mq:main answer.track +# 곡 단위 volume override — songs[i].volume 가 없으면 audio.volume 그대로 유지 (no-op) +data modify storage mq:tmp playsound.volume set from storage mq:main answer.volume +function mq:quiz/macro/play_sound with storage mq:tmp playsound diff --git a/music_quiz/data/mq/function/quiz/select.mcfunction b/music_quiz/data/mq/function/quiz/select.mcfunction index 1b1fb00..317ba0a 100644 --- a/music_quiz/data/mq/function/quiz/select.mcfunction +++ b/music_quiz/data/mq/function/quiz/select.mcfunction @@ -1,14 +1,20 @@ -scoreboard players add init main 3 scoreboard players set timer main 0 execute if score index main >= max_index main run return run function mq:quiz/end with storage mq:main scoreboard players add index main 1 -execute store result storage mq:main command_block.index int 1 run scoreboard players get index main -# 보스바 bossbar set mq:process name [{"text":"진행도: ","color": "yellow","bold": true},{"score":{"name":"index","objective": "main"},"color": "yellow","bold": true},{"text":"/","color": "yellow","bold": true},{"score":{"name":"max_index","objective": "main"},"color": "yellow","bold": true}] bossbar set mq:process players @a execute store result bossbar mq:process value run scoreboard players get index main -function mq:quiz/macro/command_block with storage mq:main command_block +# tmp.{idx (0-based, songs[] 인덱스), num (1-based, track_NN), pad ("0"|"")} 구성 +execute store result storage mq:tmp num int 1 run scoreboard players get index main +scoreboard players operation song_idx func.temp = index main +scoreboard players remove song_idx func.temp 1 +execute store result storage mq:tmp idx int 1 run scoreboard players get song_idx func.temp + +execute if score index main matches 1..9 run data modify storage mq:tmp pad set value "0" +execute unless score index main matches 1..9 run data modify storage mq:tmp pad set value "" + +function mq:quiz/setanswer diff --git a/music_quiz/data/mq/function/quiz/setanswer.mcfunction b/music_quiz/data/mq/function/quiz/setanswer.mcfunction index e51148d..4cd712d 100644 --- a/music_quiz/data/mq/function/quiz/setanswer.mcfunction +++ b/music_quiz/data/mq/function/quiz/setanswer.mcfunction @@ -1,13 +1,17 @@ -scoreboard players operation song_idx func.temp = index main -scoreboard players remove song_idx func.temp 1 -execute store result storage mq:tmp idx int 1 run scoreboard players get song_idx func.temp - +# songs[$(idx)] → answer 로 복사하고, 트랙/커버 id 부여 function mq:quiz/macro/setanswer with storage mq:tmp +# 정답 marker entity 소환 (좌표 + name/alias 합쳐서 macro 호출) +data modify storage mq:tmp marker_call set from storage mq:main marker +data modify storage mq:tmp marker_call.name set from storage mq:main answer.title +data modify storage mq:tmp marker_call.alias set from storage mq:main answer.alias +function mq:quiz/macro/summon with storage mq:tmp marker_call + scoreboard players set stop buttons -1 scoreboard players set skip buttons -1 scoreboard players set hint buttons -1 scoreboard players set replay buttons -1 scoreboard players set init main 5 -function mq:quiz/macro/summon with storage mq:main command_block + +function mq:quiz/play_sound diff --git a/music_quiz/data/mq/function/quiz/stop_sound.mcfunction b/music_quiz/data/mq/function/quiz/stop_sound.mcfunction new file mode 100644 index 0000000..43b9631 --- /dev/null +++ b/music_quiz/data/mq/function/quiz/stop_sound.mcfunction @@ -0,0 +1 @@ +function mq:quiz/macro/stop_sound with storage mq:main audio diff --git a/music_quiz/data/mq/function/repeat/check_server.mcfunction b/music_quiz/data/mq/function/repeat/check_server.mcfunction deleted file mode 100644 index 31fb95a..0000000 --- a/music_quiz/data/mq/function/repeat/check_server.mcfunction +++ /dev/null @@ -1,12 +0,0 @@ -execute if score timer status matches 20.. \ - if score skript status matches 0 \ - if score yp status matches 0 \ - if score ts status matches 0 \ - run return run function mq:check/server - -execute if score timer status matches 0.. run scoreboard players add timer status 1 -execute if score timer status matches 1..10 run scoreboard players set skript status 0 -execute if score timer status matches 1..10 run scoreboard players set yp status 0 -execute if score timer status matches 1..10 run scoreboard players set ts status 0 - -execute if score timer status matches 21.. run scoreboard players set timer status -1 diff --git a/music_quiz/data/mq/function/repeat/timer.mcfunction b/music_quiz/data/mq/function/repeat/timer.mcfunction index dfad7eb..adbb1d1 100644 --- a/music_quiz/data/mq/function/repeat/timer.mcfunction +++ b/music_quiz/data/mq/function/repeat/timer.mcfunction @@ -26,7 +26,7 @@ execute if score init main matches 2 if score timer main matches 100.. run funct # next song timer execute if score init main matches 6 if score timer main matches 300 run title @a title {"text":""} -execute if score init main matches 6 if score timer main matches 290 run function mq:images/image_delete with storage mq:main command_block +execute if score init main matches 6 if score timer main matches 290 run function mq:images/clear execute if score init main matches 6 if score timer main matches 300.. run function mq:quiz/select with storage mq:main # endding timer diff --git a/music_quiz/data/mq/function/tick.mcfunction b/music_quiz/data/mq/function/tick.mcfunction index 37a4666..75b4c15 100644 --- a/music_quiz/data/mq/function/tick.mcfunction +++ b/music_quiz/data/mq/function/tick.mcfunction @@ -1,4 +1,3 @@ -function mq:repeat/check_server function mq:repeat/players function mq:repeat/buttons/handler function mq:repeat/triggers/handler