2 Commits

Author SHA1 Message Date
tkrmagid-desktop
5e80385ab0 수정 2026-06-04 22:06:49 +09:00
tkrmagid-desktop
f211b16224 수정 2026-05-23 17:40:05 +09:00
75 changed files with 470 additions and 236 deletions

116
README.md
View File

@@ -16,29 +16,13 @@
### 호환 버전 ### 호환 버전
- **Minecraft 26.1.2** (`pack.mcmeta``min_format`/`max_format` 모두 - **Minecraft 26.1.2** (pack_format `75`) 기준.
`[101, 1]`).
- 1.21.6에서 도입된 `dialog` 시스템, 1.21+의 단수형 `function/` 태그 폴더, - 1.21.6에서 도입된 `dialog` 시스템, 1.21+의 단수형 `function/` 태그 폴더,
매크로 함수(`function ... with storage`) 기능을 사용한다. 매크로 함수(`function ... with storage`) 기능을 사용한다.
- 텍스트 컴포넌트는 JSON 표기로 작성돼 있으며, 1.21.5 이후의 SNBT 파서와도 - 텍스트 컴포넌트는 JSON 표기로 작성돼 있으며, 1.21.5 이후의 SNBT 파서와도
호환된다 (JSON은 SNBT의 부분집합). 호환된다 (JSON은 SNBT의 부분집합).
### 외부 모드 의존성 (서버/클라) ### 100% 바닐라 — 의존 플러그인 없음
서버 측 검증이 들어가 있어 다음 두 모드가 반드시 깔려 있어야 `/start`
진행된다. 미설치 시 `commands/start` 의 게이트가 사유와 함께 차단한다.
- **`mc_chat_answer_mod` v1.3.7+** — 서버 전용. 채팅으로 정답 입력을
받는다. presence 는 `#server mq_chat_mod` 점수로 매 tick 표시되며,
`SERVER_STARTED` / `END_DATA_PACK_RELOAD` / `PlayerJoin` / `ServerTick`
네 지점에서 갱신된다.
https://git.tkrmagid.kr/tkrmagid/mc_chat_answer_mod/releases/tag/v1.3.7
- **`mc_video_player_mod`** — 클라이언트 + 서버 모두 필요. 서버 컴포넌트가
`#server mq_video_mod` 를 1 로 갱신하고, 클라 join handshake 가 도착하면
`<player> mq_video_mod` 를 1 로 set. `/start` 는 서버 부재 시 단일 차단,
특정 플레이어 부재 시 본인에게 안내 + 게임 시작 차단.
### 100% 바닐라 — 의존 플러그인 없음 (모드 외)
음원 재생과 정답 이미지 표시는 모두 바닐라 명령으로 처리한다. 음원과 음원 재생과 정답 이미지 표시는 모두 바닐라 명령으로 처리한다. 음원과
페인팅 텍스처는 [minecraft_launcher](https://git.tkrmagid.kr/tkrmagid/minecraft_launcher) 페인팅 텍스처는 [minecraft_launcher](https://git.tkrmagid.kr/tkrmagid/minecraft_launcher)
@@ -87,44 +71,20 @@
### 입력 버튼 ### 입력 버튼
관리자가 사용하는 6개의 물리 스톤 버튼. 좌표·표면 방향·실행 명령·라벨 관리자가 사용하는 6개의 물리 스톤 버튼. 좌표·표면 방향·실행 명령은
`mq:init/buttons`에서 storage 리스트(`mq:main button_defs`)로 관리되며, `mq:init/buttons`에서 storage 리스트(`mq:main button_defs`)로 관리되며,
`mq:repeat/buttons/handler`가 매 틱 storage 인덱스로 `btn_prep` `mq:repeat/buttons/handler`가 매 틱 storage 인덱스로 `btn` 매크로를 호출한다.
`btn` 매크로 체인을 호출한다.
- `start` / `stop` / `skip` / `hint` / `replay` / `test` - `start` / `stop` / `skip` / `hint` / `replay` / `test`
버튼 본체는 보이는 `stone_button` 블록 + 클릭을 받는 `interaction` 엔티티 버튼 본체는 `interaction` 엔티티 + `redstone_block`-`red_wool` 토글
3 타일 (블록 면 바깥, 플레이어 쪽으로 살짝 튀어나오게) + 버튼 바로 아래 패턴으로 디바운스를 처리한다.
벽면에 부착되는 `text_display` 라벨 1 개로 구성된다. interaction 폭이
`width × width` 정사각형으로 강제되기 때문에 stone_button hitbox 의 가로
0.375 를 0.125 폭 × 3 타일로 덮고, 깊이는 두께(0.125) 만큼 밖으로 밀어
vanilla stone_button 클릭이 동시에 발화되지 않도록 한다. 라벨은 `bold`
적용 text component 로 직접 렌더링된다.
`button_defs` 항목의 필드:
- 필수: `n` (이름·태그), `x,y,z`, `f` (facing), `c` (실행 명령)
- 옵션: `label`, `label_color` (기본 `black`), `label_font` (기본
`minecraft:default`), `label_scale` (기본 `1.0`). `btn_prep` 에서
defaults + `merge from` 패턴으로 기본값이 자동 채워진다.
클릭 처리는 항상 `interaction` 경로로 흐르므로 `on target as @s` 로 누른
플레이어가 식별되고, 다수결(`trigger $(n)`) 투표가 성립한다.
`interaction` / `text_display` 는 데이터팩이 직접 소환·관리한다 —
`buttons` 점수가 `-1` (초기화) 일 때마다 같은 태그의 기존 entity 를
정리하고 정확한 개수만 (재)소환한다. `/reload``commands/stop`
호출해 `buttons` 점수를 `-1` 로 재설정하므로 리로드 시 자동 보장된다.
`/kill @e` 로 지워졌어도 다음 `/reload` 한 번으로 복구. 월드 회로
(커맨드블럭) 의존은 없다.
### 파일 구조 ### 파일 구조
``` ```
music_quiz/ music_quiz/
├── pack.mcmeta # min_format/max_format [101, 1] ├── pack.mcmeta # pack_format 75
├── pack.png
└── data/ └── data/
├── minecraft/tags/function/ ├── minecraft/tags/function/
│ ├── load.json # → mq:load │ ├── load.json # → mq:load
@@ -139,7 +99,7 @@ music_quiz/
│ ├── init/ # 사용자 설정·정적 데이터 (수정 포인트) │ ├── init/ # 사용자 설정·정적 데이터 (수정 포인트)
│ │ ├── config.mcfunction # 주제·스폰·오디오·페인팅·marker 설정 │ │ ├── config.mcfunction # 주제·스폰·오디오·페인팅·marker 설정
│ │ ├── songs.mcfunction # 곡 목록 + max_index 자동계산 │ │ ├── songs.mcfunction # 곡 목록 + max_index 자동계산
│ │ ├── buttons.mcfunction # 버튼 좌표·실행 명령·라벨 │ │ ├── buttons.mcfunction # 버튼 좌표·실행 명령
│ │ └── triggers.mcfunction # 다수결 트리거 정의 │ │ └── triggers.mcfunction # 다수결 트리거 정의
│ ├── commands/ # start·stop·skip·hint·replay·test │ ├── commands/ # start·stop·skip·hint·replay·test
│ ├── quiz/ # 게임 진행 로직 │ ├── quiz/ # 게임 진행 로직
@@ -148,20 +108,18 @@ music_quiz/
│ │ └── macro/ # 매크로 진입점 │ │ └── macro/ # 매크로 진입점
│ │ ├── setanswer.mcfunction # songs[$(idx)] → answer + track/cover id │ │ ├── setanswer.mcfunction # songs[$(idx)] → answer + track/cover id
│ │ ├── play_sound.mcfunction # $playsound 매크로 │ │ ├── play_sound.mcfunction # $playsound 매크로
│ │ ── stop_sound.mcfunction # $stopsound 매크로 │ │ ── stop_sound.mcfunction # $stopsound 매크로
│ │ └── summon{,2}.mcfunction # 정답 marker 엔티티 + alias 체인
│ ├── images/ # 정답 페인팅 표시·제거 │ ├── images/ # 정답 페인팅 표시·제거
│ │ ├── show.mcfunction # cover painting 소환 │ │ ├── show.mcfunction # cover painting 소환
│ │ ├── clear.mcfunction # cover painting 일괄 제거 │ │ ├── clear.mcfunction # cover painting 일괄 제거
│ │ └── macro/show.mcfunction # $summon painting 매크로 │ │ └── macro/show.mcfunction # $summon painting 매크로
│ ├── repeat/ # tick에서 호출되는 매 틱 처리 │ ├── repeat/ # tick에서 호출되는 매 틱 처리
│ │ ├── players·check_answer·timer.mcfunction │ │ ├── players·check_answer·timer.mcfunction
│ │ ├── timers/{init2,init6,init10}.mcfunction # init 단계별 timer 디스패치 분할 │ │ ├── buttons/{handler,btn}.mcfunction
│ │ ├── buttons/{handler,btn_prep,btn}.mcfunction
│ │ └── triggers/{handler,trigger}.mcfunction │ │ └── triggers/{handler,trigger}.mcfunction
── answer/ # 채팅 정답 입력 정규화/판정 (chat_answer 모드 경로) ── players/login.mcfunction
│ └── players/{login,mod_active_notice}.mcfunction
├── dialog/page{1,2,3}.json ├── dialog/page{1,2,3}.json
├── painting_variant/{cover_01..50,gif}.json
└── advancement/player/login.json └── advancement/player/login.json
``` ```
@@ -216,59 +174,31 @@ JSON 텍스트 컴포넌트가 storage 참조를 일관되게 지원하지 않
### 설치 ### 설치
1. 서버 월드 폴더 `datapacks/``music_quiz/` 디렉터리째 복사. 1. 서버 월드 폴더 `datapacks/``music_quiz/` 디렉터리째 복사.
2. 서버 mods 폴더에 `mc_chat_answer_mod` v1.3.7+ 와 `mc_video_player_mod` 2. minecraft_launcher 에서 생성한 `musicquiz` 리소스팩을 클라이언트에 적용
jar 설치. `mc_video_player_mod` 는 클라이언트 측에도 설치 필요.
3. minecraft_launcher 에서 생성한 `musicquiz` 리소스팩을 클라이언트에 적용
(런처가 자동 처리). (런처가 자동 처리).
4. 서버 `/reload` — 리로드 성공 메시지가 채팅에 표시되면 정상. 3. 서버 `/reload` — 리로드 성공 메시지가 채팅에 표시되면 정상.
5. `mq:init/buttons` 에 정의된 좌표 부근에 6개 버튼이 자동 배치된다. 4. 좌표 `144, 62, -225` 부근에 6개 버튼이 자동 배치된다.
6. `start` 버튼을 눌러 게임 시작 — 모드 미설치 시 사유와 함께 차단된다. 5. `start` 버튼을 눌러 게임 시작.
### 좌표 의존성 (주의) ### 좌표 의존성 (주의)
다음 좌표 데이터팩 안에 박혀 있어 다른 월드에서 쓰려면 직접 바꿔야 다음 좌표 데이터팩 안에 박혀 있어, 다른 월드에서 그대로 사용하려면
한다. 현재 박혀 있는 좌표는 본인 월드 기준이므로 그대로 옮겨가면 동작 `init/config.mcfunction` 의 값을 바꿔야 한다:
안 한다.
- 정답 페인팅 / 입력 marker / 플레이어 스폰 — `init/config.mcfunction` - 정답 입력 marker: `144 59 -219``marker.{x,y,z}`
- 버튼 좌표·facing — `init/buttons.mcfunction` (`button_defs``x,y,z,f`) - 정답 페인팅: `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`
--- ---
## 변경 이력 ## 변경 이력
### 2026-05-19 — v1.0.25: 버튼 hitbox/라벨 미세조정 + 곡목록·좌표 갱신
- `repeat/buttons/btn.mcfunction`: interaction hitbox 미세조정 (`width`
0.13 가운데 타일로 micro-gap 보정, `height` 0.26, 깊이 오프셋
0.07/0.93, text_display Y `~-0.5` 로 라벨 위치 조정).
- 셀렉터 정렬 `[type=...,tag=mq,tag=$(n)]` → `[distance=0..,tag=mq,
tag=$(n),type=...]`.
- `init/songs.mcfunction`: 아이유 17 곡 셋으로 교체 (alias 빈 배열).
- `init/buttons.mcfunction`: 버튼 좌표 본인 월드 기준으로 갱신,
`label` 필드 추가 ("게임시작" / "정지" / "넘기기" / "힌트" /
"다시듣기" / "소리 테스트").
- `repeat/timer.mcfunction` 분할 → `repeat/timers/{init2,init6,init10}`.
- `commands/start.mcfunction` 에 `mq_video_mod` 게이트 추가 (서버 부재
단일 차단 + 플레이어별 부재 안내). `load.mcfunction` 에 `mq_video_mod`
objective + `#server` 0 materialize 추가.
### 2026-05-18 ~ 19 — v1.0.19 ~ v1.0.24: 버튼 인프라 안정화
- v1.0.19/20/21: `btn_prep` defaults+merge 패턴, `positioned $(x).0`
로 +0.5 보정 회피, interaction 3 타일 분할, `text_display` 도입.
- v1.0.23: 채팅정답 모드 false negative 의 진짜 fix — 데이터팩 게이트는
유지하고 모드 (`mc_chat_answer_mod` v1.3.7) 의 presence pulse 를
4 지점으로 확장.
- v1.0.24: `text_display` Y 보정 (`~-1` → `~-0.25`) + 라벨 bold + v1.0.21
의 interaction 깊이 부호 반전 수정.
### 2026-05-13 — 26.1.2 호환 + 1차 정리 (`b1babad`) ### 2026-05-13 — 26.1.2 호환 + 1차 정리 (`b1babad`)
이전 푸시본(`6841b7a 이전퀴즈 데이터팩`)을 26.1.2 기준으로 정비. 이전 푸시본(`6841b7a 이전퀴즈 데이터팩`)을 26.1.2 기준으로 정비.
- `pack_format` 69 → 75 (MC 26.1.2 / 1.21.11). 이후 `min_format`/ - `pack_format` 69 → 75 (MC 26.1.2 / 1.21.11)
`max_format` 가 `[101, 1]` 로 갱신됨 (현재).
- `mq:load`, `mq:players/login`, `mq:commands/start`, `mq:commands/stop`, - `mq:load`, `mq:players/login`, `mq:commands/start`, `mq:commands/stop`,
`mq:quiz/start`, `mq:quiz/end`, `mq:repeat/buttons/btn` 등에 남아 있던 `mq:quiz/start`, `mq:quiz/end`, `mq:repeat/buttons/btn` 등에 남아 있던
`# say ...` / `# stopsound` 사문화 디버그 주석 제거 `# say ...` / `# stopsound` 사문화 디버그 주석 제거

View File

@@ -15,7 +15,7 @@
{ {
"type": "minecraft:plain_message", "type": "minecraft:plain_message",
"contents": { "contents": {
"text": "\n1. 정답입력시에 채팅으로 입력해주시면 됩니다.\n[ 띄어쓰기, 영어 대소문자, 특수문자 ]\n상관없이 입력하셔도 인식 됩니다.\n\n2. 모든 소리는 날씨 소리로 조절할수 있습니다.\n\n3. 게임시작후 버튼들은 과반수(절반이상)가 눌러야 작동합니다.\n\n4. 힌트는 특수문자 제외 정답의 절반이 가려져서 나옵니다.\n힌트는 여러번 받을수 있고,\n받을때마다 가려지는 부분이 달라집니다." "text": "\n1. 정답입력시에 채팅으로 입력해주시면 됩니다.\n[ 띄어쓰기, 영어 대소문자 ]\n상관없이 입력하셔도 인식 됩니다.\n\n2. 모든 소리는 주크박스/소리 블록 채널로 조절할수 있습니다.\n\n3. 게임시작후 버튼들은 과반수(절반이상)가 눌러야 작동합니다.\n\n4. 힌트는 특수문자 제외 정답의 절반이 가려져서 나옵니다.\n힌트는 여러번 받을수 있고,\n받을때마다 가려지는 부분이 달라집니다."
}, },
"width": 300 "width": 300
} }

View File

@@ -8,3 +8,4 @@ execute if score init main matches 10 run return run function mq:tellraw {"text"
# warn-off execute-group # warn-off execute-group
execute if score init main matches 5 run function mq:quiz/stop_sound 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 execute if score init main matches 5 run function mq:quiz/play_sound

View File

@@ -74,3 +74,5 @@ kill @e[distance=0..,tag=mq,type=minecraft:text_display]
function mq:quiz/stop_sound function mq:quiz/stop_sound
function mq:images/clear function mq:images/clear
function mq:videos/clear
function mq:videos/cache/clear

View File

@@ -1,6 +1,8 @@
stopsound @a block minecraft:block.stone_button.click_on stopsound @a block minecraft:block.stone_button.click_on
function mq:tellraw {"text":"띵!!!","color":"white","msg":'""'} function mq:tellraw {"text":"띵!!!","color":"white","msg":'""'}
$stopsound @a player $(namespace):bell
# warn-off execute-group # warn-off execute-group
execute as @a at @s run playsound minecraft:block.note_block.bell weather @s ~ ~ ~ 1 0.9 $execute as @a at @s run playsound $(namespace):bell $(source) @s ~ ~ ~ 1 0.9
execute as @a at @s run playsound minecraft:block.note_block.bell weather @s ~ ~ ~ 1 0.9 $execute as @a at @s run playsound $(namespace):bell $(source) @s ~ ~ ~ 1 0.9
execute as @a at @s run playsound minecraft:block.note_block.bell weather @s ~ ~ ~ 1 0.9 $execute as @a at @s run playsound $(namespace):bell $(source) @s ~ ~ ~ 1 0.9

View File

@@ -9,6 +9,7 @@
# label_color : 텍스트 색 (예 "black", "red", "#FFAA00"). 기본 "black". # label_color : 텍스트 색 (예 "black", "red", "#FFAA00"). 기본 "black".
# label_font : 텍스트 폰트 (예 "minecraft:default"). 기본 "minecraft:default". # label_font : 텍스트 폰트 (예 "minecraft:default"). 기본 "minecraft:default".
# label_scale : 텍스트 크기 (Vector3f 한 축, 3축 동일). 기본 "1.0". # label_scale : 텍스트 크기 (Vector3f 한 축, 3축 동일). 기본 "1.0".
# label_addY : 추가할 높이. 기본 "-0.1".
# #
# interaction entity 의 위치/크기와 text_display 의 위치/회전은 facing 만 # interaction entity 의 위치/크기와 text_display 의 위치/회전은 facing 만
# 보면 결정됨 — 매번 손으로 ox/oy/oz 를 적지 않는다. 실제 오프셋 테이블은 # 보면 결정됨 — 매번 손으로 ox/oy/oz 를 적지 않는다. 실제 오프셋 테이블은
@@ -20,4 +21,4 @@ data modify storage mq:main button_defs append value {n:"stop", x:2771, y:86,
data modify storage mq:main button_defs append value {n:"skip", x:2769, y:86, z:5968, f:"north", c:"function mq:commands/skip", label:"넘기기"} data modify storage mq:main button_defs append value {n:"skip", x:2769, y:86, z:5968, f:"north", c:"function mq:commands/skip", label:"넘기기"}
data modify storage mq:main button_defs append value {n:"hint", x:2767, y:86, z:5968, f:"north", c:"function mq:commands/hint", label:"힌트"} data modify storage mq:main button_defs append value {n:"hint", x:2767, y:86, z:5968, f:"north", c:"function mq:commands/hint", label:"힌트"}
data modify storage mq:main button_defs append value {n:"replay", x:2765, y:86, z:5968, f:"north", c:"function mq:commands/replay", label:"다시듣기"} data modify storage mq:main button_defs append value {n:"replay", x:2765, y:86, z:5968, f:"north", c:"function mq:commands/replay", label:"다시듣기"}
data modify storage mq:main button_defs append value {n:"test", x:2769, y:87, z:5957, f:"south", c:"function mq:commands/test", label:"소리 테스트"} data modify storage mq:main button_defs append value {n:"test", x:2769, y:87, z:5957, f:"south", c:"function mq:commands/test with storage mq:main audio", label:"소리\n테스트", label_addY: "-0.2"}

View File

@@ -6,17 +6,29 @@ data modify storage mq:main spawn set value {x: 2769, y: 85, z: 5963, r: 0, f: 0
# 음원 재생 — minecraft_launcher 리소스팩의 musicquiz:track_NN 사운드 이벤트 # 음원 재생 — minecraft_launcher 리소스팩의 musicquiz:track_NN 사운드 이벤트
# namespace — 리소스팩 네임스페이스 (기본 "musicquiz") # namespace — 리소스팩 네임스페이스 (기본 "musicquiz")
# source — /playsound 채널. stopsound 와 동일해야 함. 노래는 "player" 채널로 # source — /playsound 채널. stopsound 와 동일해야 함. 노래는 "record" 채널로
# 재생 (음성/플레이어 채널 슬라이더로 음량 제어). 타이머/UI 비프는 # 재생 (주크박스/소리 블록 채널 슬라이더로 음량 제어).
# 별도로 weather 채널 사용.
# volume — 기본 음량. 곡별 override 는 init/songs.mcfunction 의 volume 필드 사용 # volume — 기본 음량. 곡별 override 는 init/songs.mcfunction 의 volume 필드 사용
# pitch — 1.0 = 원본 속도 # pitch — 1.0 = 원본 속도
data modify storage mq:main audio set value {namespace: "musicquiz", source: "player", volume: 1.0, pitch: 1.0} data modify storage mq:main audio set value {namespace: "musicquiz", source: "record", volume: 1.0, pitch: 1.0}
# 정답 페인팅 — 데이터팩의 mq:cover_NN painting_variant (텍스처는 리소스팩 musicquiz:cover_NN) # 정답 페인팅 — 데이터팩의 mq:cover_NN painting_variant (텍스처는 리소스팩 musicquiz:cover_NN)
# namespace — painting_variant 네임스페이스 (기본 "mq") # namespace — painting_variant 네임스페이스 (기본 "mq")
# x,y,z — 페인팅 entity 좌표 (벽면 앞쪽 블록 위치) # x,y,z — 페인팅 entity 좌표 (벽면 앞쪽 블록 위치)
# facing — 페인팅이 바라보는 방향: south=0 / west=1 / north=2 / east=3 # facing — 페인팅이 바라보는 방향: south=0 / west=1 / north=2 / east=3
data modify storage mq:main image set value {namespace: "mq", x: 2775, y: 85, z: 5982, facing: 2b} data modify storage mq:main image set value {namespace: "mq", x: 2782, y: 88, z: 5979, facing: 2b}
# 정답 영상 — 모드의 영상 재생 관련
# namespace — 영상 아이디를 제외한 주소 (마지막에 /는 없어야함)
# x,y,z — 영상 블럭 좌표 (벽면 앞쪽 블록 위치)
# w,h — 영상 가로세로 크키 (왼쪽아래 기준)
# facing — 영상이 바라보는 방향: south / west / north / east
# sound — 영상 소리 설정 (0~100, 음소거: -1)
data modify storage mq:main video set value { \
namespace: "https://video.tkrmagid.kr/api/video/1/2", \
cmd_x: 2769, cmd_y: 73, cmd_z: 5965, \
x: 2731, y: 96, z: 6034, facing: "north", w: 25,h: 14, \
sound: -1 \
}
# 곡 개수 max_index 는 init/songs.mcfunction 의 길이로 자동 계산됨 # 곡 개수 max_index 는 init/songs.mcfunction 의 길이로 자동 계산됨

View File

@@ -2,25 +2,25 @@
# 필수 — title, author, alias, volume # 필수 — title, author, alias, volume
# volume: /playsound 음량. 1.0 = 기본. 곡마다 음량 조절 가능. # volume: /playsound 음량. 1.0 = 기본. 곡마다 음량 조절 가능.
# 곡 순서가 리소스팩의 track_NN / cover_NN 인덱스와 1:1 매칭된다. # 곡 순서가 리소스팩의 track_NN / cover_NN 인덱스와 1:1 매칭된다.
# 예) {title:"Quiet Song", author:"...", alias:[...], volume:2.0} # 예) {title:"Quiet Song", author:"...", alias:[...], description:"...", volume:0.5}
data modify storage mq:main songs set value [] data modify storage mq:main songs set value []
data modify storage mq:main songs append value {title:"푸르던", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"푸르던", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"금요일에 만나요", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"금요일에 만나요", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"나의 옛날이야기", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"나의 옛날이야기", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"비밀의 화원", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"비밀의 화원", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"겨울잠", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"겨울잠", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"이런엔딩", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"이런엔딩", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"이름에게", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"이름에게", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"드라마", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"드라마", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"가을아침", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"가을아침", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"Rain Drop", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"Rain Drop", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"에필로그", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"에필로그", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"무릎", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"무릎", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"마음", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"마음", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"잠 못 드는 밤 비는 내리고", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"잠 못 드는 밤 비는 내리고", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"정거장", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"정거장", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"자장가", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"자장가", author:"아이유", alias:[], description:"", volume:1.0}
data modify storage mq:main songs append value {title:"사랑이 지나가면", author:"아이유", alias:[]} data modify storage mq:main songs append value {title:"사랑이 지나가면", author:"아이유", alias:[], description:"", volume:1.0}
# 곡 개수는 songs 배열 길이에서 자동 계산됨 # 곡 개수는 songs 배열 길이에서 자동 계산됨
execute store result storage mq:main max_index int 1 run data get storage mq:main songs execute store result storage mq:main max_index int 1 run data get storage mq:main songs

View File

@@ -1,4 +1,4 @@
data modify storage mq:main answer set value {title:"", author:"", alias:[]} data modify storage mq:main answer set value {title:"", author:"", alias:[], description:""}
data merge storage func:temp {} data merge storage func:temp {}
data merge storage mq:tmp {} data merge storage mq:tmp {}
@@ -45,3 +45,5 @@ bossbar add mq:process [{"text":"진행도: ","color": "yellow","bold": true},{"
function mq:commands/stop with storage mq:main function mq:commands/stop with storage mq:main
function mq:players/login with storage mq:main spawn function mq:players/login with storage mq:main spawn
function mq:videos/cache/clear

View File

@@ -5,6 +5,7 @@ scoreboard players set @s answer 2
function mq:tellraw {"text":"","color":"black","msg":""} function mq:tellraw {"text":"","color":"black","msg":""}
function mq:tellraw {"text":"","color":"black",msg:[{"text":"정답: ","color": "aqua"},{"storage":"mq:main","nbt":"answer.title","color": "yellow","bold": true}]} function mq:tellraw {"text":"","color":"black",msg:[{"text":"정답: ","color": "aqua"},{"storage":"mq:main","nbt":"answer.title","color": "yellow","bold": true}]}
function mq:tellraw {"text":"","color":"black",msg:[{"text":"가수: ","color":"aqua"},{"storage":"mq:main","nbt":"answer.author","color": "yellow","bold": true}]} function mq:tellraw {"text":"","color":"black",msg:[{"text":"가수: ","color":"aqua"},{"storage":"mq:main","nbt":"answer.author","color": "yellow","bold": true}]}
function mq:tellraw {"text":"","color":"black",msg:[{"text":"설명: ","color":"aqua"},{"storage":"mq:main","nbt":"answer.description","color": "yellow","bold": false}]}
execute if score skip buttons matches -2 run function mq:tellraw {"text":"","color":"black",msg:[{"text":"정답자: ","color": "aqua"},{"text":"스킵","color": "yellow","bold": true}]} execute if score skip buttons matches -2 run function mq:tellraw {"text":"","color":"black",msg:[{"text":"정답자: ","color": "aqua"},{"text":"스킵","color": "yellow","bold": true}]}
execute unless score skip buttons matches -2 run function mq:tellraw {"text":"","color":"black",msg:[{"text":"정답자: ","color": "aqua"},{"selector":"@s","color": "yellow","bold": true}]} execute unless score skip buttons matches -2 run function mq:tellraw {"text":"","color":"black",msg:[{"text":"정답자: ","color": "aqua"},{"selector":"@s","color": "yellow","bold": true}]}
function mq:tellraw {"text":"","color":"black",msg:[{"text": "( 15초뒤 다음문제로 넘어갑니다. )","color": "gray"}]} function mq:tellraw {"text":"","color":"black",msg:[{"text": "( 15초뒤 다음문제로 넘어갑니다. )","color": "gray"}]}
@@ -30,3 +31,4 @@ scoreboard players set replay buttons -3
scoreboard players set timer main 1 scoreboard players set timer main 1
function mq:images/show function mq:images/show
function mq:videos/show

View File

@@ -3,3 +3,8 @@ data modify storage mq:tmp playsound.track set from storage mq:main answer.track
# 곡 단위 volume override — songs[i].volume 가 없으면 audio.volume 그대로 유지 (no-op) # 곡 단위 volume override — songs[i].volume 가 없으면 audio.volume 그대로 유지 (no-op)
data modify storage mq:tmp playsound.volume set from storage mq:main answer.volume 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 function mq:quiz/macro/play_sound with storage mq:tmp playsound
# volume 테스트 (replay 이용)
# function mq:quiz/stop_sound
# data modify storage mq:main answer.volume set value 0.5
# function mq:quiz/play_sound

View File

@@ -20,3 +20,4 @@ execute if score index main matches 1..9 run data modify storage mq:tmp pad set
execute unless score index main matches 1..9 run data modify storage mq:tmp pad set value "" execute unless score index main matches 1..9 run data modify storage mq:tmp pad set value ""
function mq:quiz/setanswer function mq:quiz/setanswer
function mq:videos/cache/add

View File

@@ -1,6 +1,6 @@
# warn-off-file always-pass-condition # warn-off-file always-pass-condition
# 버튼 1개에 대한 매 tick 처리. # 버튼 1개에 대한 매 tick 처리.
# 매크로 인자(mq:tmp.btn): n, x, y, z, f, c, label, label_color, label_font, label_scale # 매크로 인자(mq:tmp.btn): n, x, y, z, f, c, label, label_color, label_font, label_scale, label_addY
# buttons 점수 상태: # buttons 점수 상태:
# ..-2 : 비활성 (버튼 블록 제거, interaction 응답 차단) # ..-2 : 비활성 (버튼 블록 제거, interaction 응답 차단)
# -1 : 초기화 단계 (버튼 블록 + interaction × 3 + text_display 보장 후 0) # -1 : 초기화 단계 (버튼 블록 + interaction × 3 + text_display 보장 후 0)
@@ -80,25 +80,25 @@ $execute if score $(n) buttons matches -1 run kill @e[distance=0..,tag=mq,tag=$(
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"south"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.37 ~0.37 ~0.07 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"south"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.37 ~0.37 ~0.07 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"south"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.5 ~0.37 ~0.07 {Tags:["mq","$(n)"],width:0.13f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"south"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.5 ~0.37 ~0.07 {Tags:["mq","$(n)"],width:0.13f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"south"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.63 ~0.37 ~0.07 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"south"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.63 ~0.37 ~0.07 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 unless data storage mq:tmp btn{label:""} if data storage mq:tmp btn{f:"south"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:text_display ~0.5 ~-0.5 ~0.01 {Tags:["mq","$(n)"],Rotation:[0f,0f],background:0,text:{text:"$(label)",color:"$(label_color)",font:"$(label_font)",bold:true},transformation:{scale:[$(label_scale)f,$(label_scale)f,$(label_scale)f],translation:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]}} $execute if score $(n) buttons matches -1 unless data storage mq:tmp btn{label:""} if data storage mq:tmp btn{f:"south"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:text_display ~0.5 ~-0.5 ~0.01 {Tags:["mq","$(n)"],Rotation:[0f,0f],background:0,text:{text:"$(label)",color:"$(label_color)",font:"$(label_font)",bold:true},transformation:{scale:[$(label_scale)f,$(label_scale)f,$(label_scale)f],translation:[0f,$(label_addY)f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]}}
# north: 깊이축=z(+0.8125, 플레이어 쪽), 가로축=x, 3 타일 + 라벨 # north: 깊이축=z(+0.8125, 플레이어 쪽), 가로축=x, 3 타일 + 라벨
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"north"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.37 ~0.37 ~0.93 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"north"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.37 ~0.37 ~0.93 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"north"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.5 ~0.37 ~0.93 {Tags:["mq","$(n)"],width:0.13f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"north"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.5 ~0.37 ~0.93 {Tags:["mq","$(n)"],width:0.13f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"north"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.63 ~0.37 ~0.93 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"north"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.63 ~0.37 ~0.93 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 unless data storage mq:tmp btn{label:""} if data storage mq:tmp btn{f:"north"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:text_display ~0.5 ~-0.5 ~0.99 {Tags:["mq","$(n)"],Rotation:[180f,0f],background:0,text:{text:"$(label)",color:"$(label_color)",font:"$(label_font)",bold:true},transformation:{scale:[$(label_scale)f,$(label_scale)f,$(label_scale)f],translation:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]}} $execute if score $(n) buttons matches -1 unless data storage mq:tmp btn{label:""} if data storage mq:tmp btn{f:"north"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:text_display ~0.5 ~-0.5 ~0.99 {Tags:["mq","$(n)"],Rotation:[180f,0f],background:0,text:{text:"$(label)",color:"$(label_color)",font:"$(label_font)",bold:true},transformation:{scale:[$(label_scale)f,$(label_scale)f,$(label_scale)f],translation:[0f,$(label_addY)f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]}}
# east: 깊이축=x(+0.1875, 플레이어 쪽), 가로축=z, 3 타일 + 라벨 # east: 깊이축=x(+0.1875, 플레이어 쪽), 가로축=z, 3 타일 + 라벨
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"east"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.07 ~0.37 ~0.37 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"east"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.07 ~0.37 ~0.37 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"east"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.07 ~0.37 ~0.5 {Tags:["mq","$(n)"],width:0.13f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"east"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.07 ~0.37 ~0.5 {Tags:["mq","$(n)"],width:0.13f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"east"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.07 ~0.37 ~0.63 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"east"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.07 ~0.37 ~0.63 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 unless data storage mq:tmp btn{label:""} if data storage mq:tmp btn{f:"east"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:text_display ~0.01 ~-0.5 ~0.5 {Tags:["mq","$(n)"],Rotation:[-90f,0f],background:0,text:{text:"$(label)",color:"$(label_color)",font:"$(label_font)",bold:true},transformation:{scale:[$(label_scale)f,$(label_scale)f,$(label_scale)f],translation:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]}} $execute if score $(n) buttons matches -1 unless data storage mq:tmp btn{label:""} if data storage mq:tmp btn{f:"east"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:text_display ~0.01 ~-0.5 ~0.5 {Tags:["mq","$(n)"],Rotation:[-90f,0f],background:0,text:{text:"$(label)",color:"$(label_color)",font:"$(label_font)",bold:true},transformation:{scale:[$(label_scale)f,$(label_scale)f,$(label_scale)f],translation:[0f,$(label_addY)f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]}}
# west: 깊이축=x(+0.8125, 플레이어 쪽), 가로축=z, 3 타일 + 라벨 # west: 깊이축=x(+0.8125, 플레이어 쪽), 가로축=z, 3 타일 + 라벨
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"west"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.93 ~0.37 ~0.37 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"west"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.93 ~0.37 ~0.37 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"west"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.93 ~0.37 ~0.5 {Tags:["mq","$(n)"],width:0.13f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"west"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.93 ~0.37 ~0.5 {Tags:["mq","$(n)"],width:0.13f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"west"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.93 ~0.37 ~0.63 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b} $execute if score $(n) buttons matches -1 if data storage mq:tmp btn{f:"west"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:interaction ~0.93 ~0.37 ~0.63 {Tags:["mq","$(n)"],width:0.125f,height:0.26f,response:0b}
$execute if score $(n) buttons matches -1 unless data storage mq:tmp btn{label:""} if data storage mq:tmp btn{f:"west"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:text_display ~0.99 ~-0.5 ~0.5 {Tags:["mq","$(n)"],Rotation:[90f,0f],background:0,text:{text:"$(label)",color:"$(label_color)",font:"$(label_font)",bold:true},transformation:{scale:[$(label_scale)f,$(label_scale)f,$(label_scale)f],translation:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]}} $execute if score $(n) buttons matches -1 unless data storage mq:tmp btn{label:""} if data storage mq:tmp btn{f:"west"} positioned $(x).0 $(y).0 $(z).0 run summon minecraft:text_display ~0.99 ~-0.5 ~0.5 {Tags:["mq","$(n)"],Rotation:[90f,0f],background:0,text:{text:"$(label)",color:"$(label_color)",font:"$(label_font)",bold:true},transformation:{scale:[$(label_scale)f,$(label_scale)f,$(label_scale)f],translation:[0f,$(label_addY)f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f]}}
$execute if score $(n) buttons matches -1 run scoreboard players set $(n) buttons 0 $execute if score $(n) buttons matches -1 run scoreboard players set $(n) buttons 0
@@ -109,8 +109,9 @@ $execute if score $(n) buttons matches -1 run scoreboard players set $(n) button
# (나머지는 target 부재로 체인 중단). limit=1 을 두면 MC 가 임의로 1개를 # (나머지는 target 부재로 체인 중단). limit=1 을 두면 MC 가 임의로 1개를
# 골라 잘못된 entity 만 검사하므로 limit 두지 않음. # 골라 잘못된 entity 만 검사하므로 limit 두지 않음.
$execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] on target as @s positioned $(x).0 $(y).0 $(z).0 run playsound minecraft:block.stone_button.click_on block @s ~ ~ ~ 1 1 $execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] on target as @s positioned $(x).0 $(y).0 $(z).0 run playsound minecraft:block.stone_button.click_on block @s ~ ~ ~ 1 1
$execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] on target as @s positioned $(x).0 $(y).0 $(z).0 if score init main matches 0 run $(c) $execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] on target if data storage mq:tmp btn{n:"test"} run $(c)
$execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] on target as @s positioned $(x).0 $(y).0 $(z).0 unless score init main matches 0 run trigger $(n) $execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] on target unless data storage mq:tmp btn{n:"test"} as @s positioned $(x).0 $(y).0 $(z).0 if score init main matches 0 run $(c)
$execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] on target unless data storage mq:tmp btn{n:"test"} as @s positioned $(x).0 $(y).0 $(z).0 unless score init main matches 0 run trigger $(n)
# ---- 처리 후 attack/interaction NBT 클리어 (다음 tick 중복 발화 방지) ---- # ---- 처리 후 attack/interaction NBT 클리어 (다음 tick 중복 발화 방지) ----
$execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] at @s run data remove entity @s attack $execute as @e[distance=0..,tag=mq,tag=$(n),type=minecraft:interaction] at @s run data remove entity @s attack

View File

@@ -6,6 +6,7 @@
# label_color : 기본 "black" # label_color : 기본 "black"
# label_font : 기본 "minecraft:default" # label_font : 기본 "minecraft:default"
# label_scale : 기본 "1.0" (Vector3f 의 한 축, 3축 동일하게 사용됨) # label_scale : 기본 "1.0" (Vector3f 의 한 축, 3축 동일하게 사용됨)
# label_addY : 기본 "-0.1"
# #
# 구현: defaults 컴파운드를 먼저 만들고 entry (mq:tmp.btn) 를 그 위에 merge # 구현: defaults 컴파운드를 먼저 만들고 entry (mq:tmp.btn) 를 그 위에 merge
# 한 뒤 다시 mq:tmp.btn 으로 되돌린다. data modify ... merge from 은 source # 한 뒤 다시 mq:tmp.btn 으로 되돌린다. data modify ... merge from 은 source
@@ -16,6 +17,6 @@
# 방식이었으나 MC 26.1.2 parser 가 해당 라인을 거부했음. merge 방식은 문제 # 방식이었으나 MC 26.1.2 parser 가 해당 라인을 거부했음. merge 방식은 문제
# 난 execute-unless-data 구문 자체를 제거.) # 난 execute-unless-data 구문 자체를 제거.)
data modify storage mq:tmp btn_default set value {label:"",label_color:"black",label_font:"minecraft:default",label_scale:"1.0"} data modify storage mq:tmp btn_default set value {label:"",label_color:"black",label_font:"minecraft:default",label_scale:"1.0",label_addY:"-0.1"}
data modify storage mq:tmp btn_default merge from storage mq:tmp btn data modify storage mq:tmp btn_default merge from storage mq:tmp btn
data modify storage mq:tmp btn set from storage mq:tmp btn_default data modify storage mq:tmp btn set from storage mq:tmp btn_default

View File

@@ -6,10 +6,10 @@ execute unless score init main matches 2 \
run scoreboard players set timer main 0 run scoreboard players set timer main 0
# start title timer # start title timer
execute if score init main matches 2 run function mq:repeat/timers/init2 execute if score init main matches 2 run function mq:repeat/timers/init2 with storage mq:main audio
# next song timer # next song timer
execute if score init main matches 6 run function mq:repeat/timers/init6 execute if score init main matches 6 run function mq:repeat/timers/init6
# endding timer # endding timer
execute if score init main matches 10 run function mq:repeat/timers/init10 execute if score init main matches 10 run function mq:repeat/timers/init10 with storage mq:main audio

View File

@@ -1,3 +1,15 @@
execute if score timer main matches 300 run title @a title {"text":""} # warn-off-file execute-group
execute if score timer main matches 290 run function mq:images/clear execute if score timer main matches 60 run function mq:tellraw {"text":"퀴즈가 종료되었습니다.","color":"white","msg":""}
execute if score timer main matches 300.. run function mq:quiz/select with storage mq:main $execute if score timer main matches 60 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
$execute if score timer main matches 60 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
$execute if score timer main matches 60 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 180 run function mq:tellraw {"text":"퀴즈를 다시 시작하시려면 종료를 눌러주세요.","color":"white","msg":""}
execute if score timer main matches 120 as @a at @s run scoreboard players set stop buttons -1
$execute if score timer main matches 120 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
$execute if score timer main matches 120 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
$execute if score timer main matches 120 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 120 run function mq:tellraw {"text":"플레이 해주셔서 감사합니다.","color":"white","msg":""}
$execute if score timer main matches 180 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
$execute if score timer main matches 180 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
$execute if score timer main matches 180 as @a at @s run playsound minecraft:ui.button.click $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 200.. run scoreboard players set init main 11

View File

@@ -1,15 +1,15 @@
# warn-off-file execute-group # warn-off-file execute-group
execute if score timer main matches 20 run title @a title {"text":"3"} execute if score timer main matches 20 run title @a title {"text":"3"}
execute if score timer main matches 20 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 20 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 20 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 20 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 20 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 20 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 40 run title @a title {"text":"2"} execute if score timer main matches 40 run title @a title {"text":"2"}
execute if score timer main matches 40 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 40 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 40 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 40 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 40 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 40 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 60 run title @a title {"text":"1"} execute if score timer main matches 60 run title @a title {"text":"1"}
execute if score timer main matches 60 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 60 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 60 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 60 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 60 as @a at @s run playsound minecraft:block.note_block.iron_xylophone weather @s ~ ~ ~ 1 1 $execute if score timer main matches 60 as @a at @s run playsound minecraft:block.note_block.iron_xylophone $(source) @s ~ ~ ~ 1 1
execute if score timer main matches 100 run title @a title {"text":""} execute if score timer main matches 100 run title @a title {"text":""}
execute if score timer main matches 100.. run function mq:quiz/select with storage mq:main execute if score timer main matches 100.. run function mq:quiz/select with storage mq:main

View File

@@ -1,15 +1,5 @@
# warn-off-file execute-group execute if score timer main matches 300 run title @a title {"text":""}
execute if score timer main matches 60 run function mq:tellraw {"text":"퀴즈가 종료되었습니다.","color":"white","msg":""} # warn-off execute-group
execute if score timer main matches 60 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1 execute if score timer main matches 290 run function mq:images/clear
execute if score timer main matches 60 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1 execute if score timer main matches 290 run function mq:videos/clear
execute if score timer main matches 60 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1 execute if score timer main matches 300.. run function mq:quiz/select with storage mq:main
execute if score timer main matches 180 run function mq:tellraw {"text":"퀴즈를 다시 시작하시려면 종료를 눌러주세요.","color":"white","msg":""}
execute if score timer main matches 120 as @a at @s run scoreboard players set stop buttons -1
execute if score timer main matches 120 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1
execute if score timer main matches 120 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1
execute if score timer main matches 120 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1
execute if score timer main matches 120 run function mq:tellraw {"text":"플레이 해주셔서 감사합니다.","color":"white","msg":""}
execute if score timer main matches 180 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1
execute if score timer main matches 180 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1
execute if score timer main matches 180 as @a at @s run playsound minecraft:ui.button.click weather @s ~ ~ ~ 1 1
execute if score timer main matches 200.. run scoreboard players set init main 11

View File

@@ -0,0 +1,9 @@
data modify storage mq:tmp video set from storage mq:main video
scoreboard players operation cache_idx func.temp = index main
scoreboard players add cache_idx func.temp 1
execute store result storage mq:tmp video.cache_num int 1 run scoreboard players get cache_idx func.temp
execute store result storage mq:tmp video.num int 1 run scoreboard players get index main
data modify storage mq:tmp video.cmd set value "cache"
function mq:videos/macro/cmd with storage mq:tmp video

View File

@@ -0,0 +1 @@
function mq:videos/macro/custom {cmd: "videoCache clear"}

View File

@@ -0,0 +1,4 @@
data modify storage mq:tmp video set from storage mq:main video
execute store result storage mq:tmp video.num int 1 run scoreboard players get index main
data modify storage mq:tmp video.cmd set value "delete"
function mq:videos/macro/cmd with storage mq:tmp video

View File

@@ -0,0 +1,18 @@
$execute if data storage mq:tmp {video:{cmd:"delete"}} run setblock $(cmd_x) $(cmd_y) $(cmd_z) minecraft:command_block[conditional=false,facing=up]{ \
Command:"videoDelete $(x) $(y) $(z)", \
auto:0b \
}
$execute if data storage mq:tmp {video:{cmd:"num"}} run setblock $(cmd_x) $(cmd_y) $(cmd_z) minecraft:command_block[conditional=false,facing=up]{ \
Command:"videoPlace $(x) $(y) $(z) $(facing) $(w) $(h) $(sound) video_$(num)", \
auto:0b \
}
$execute if data storage mq:tmp {video:{cmd:"cache"}} run setblock $(cmd_x) $(cmd_y) $(cmd_z) minecraft:command_block[conditional=false,facing=up]{ \
Command:"videoCache add video_$(num) $(namespace)/$(cache_num)", \
auto:0b \
}
$execute if data storage mq:tmp {video:{cmd:"cmd"}} run setblock $(cmd_x) $(cmd_y) $(cmd_z) minecraft:command_block[conditional=false,facing=up]{ \
Command:"$(cmd_value)", \
auto:0b \
}
$data modify block $(cmd_x) $(cmd_y) $(cmd_z) auto set value 1b

View File

@@ -0,0 +1,6 @@
function mq:videos/clear
data modify storage mq:tmp video set from storage mq:main video
execute store result storage mq:tmp video.num int 1 run scoreboard players get index main
data modify storage mq:tmp video.cmd set value "custom"
$data modify storage mq:tmp video.cmd_value set value "$(cmd)"
function mq:videos/macro/cmd with storage mq:tmp video

View File

@@ -0,0 +1,5 @@
function mq:videos/clear
data modify storage mq:tmp video set from storage mq:main video
execute store result storage mq:tmp video.num int 1 run scoreboard players get index main
data modify storage mq:tmp video.cmd set value "num"
function mq:videos/macro/cmd with storage mq:tmp video

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_01", "asset_id": "musicquiz:cover_01",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_01", "author": "musicquiz",
"author": "musicquiz" "title": "cover_01"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_02", "asset_id": "musicquiz:cover_02",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_02", "author": "musicquiz",
"author": "musicquiz" "title": "cover_02"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_03", "asset_id": "musicquiz:cover_03",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_03", "author": "musicquiz",
"author": "musicquiz" "title": "cover_03"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_04", "asset_id": "musicquiz:cover_04",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_04", "author": "musicquiz",
"author": "musicquiz" "title": "cover_04"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_05", "asset_id": "musicquiz:cover_05",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_05", "author": "musicquiz",
"author": "musicquiz" "title": "cover_05"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_06", "asset_id": "musicquiz:cover_06",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_06", "author": "musicquiz",
"author": "musicquiz" "title": "cover_06"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_07", "asset_id": "musicquiz:cover_07",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_07", "author": "musicquiz",
"author": "musicquiz" "title": "cover_07"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_08", "asset_id": "musicquiz:cover_08",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_08", "author": "musicquiz",
"author": "musicquiz" "title": "cover_08"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_09", "asset_id": "musicquiz:cover_09",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_09", "author": "musicquiz",
"author": "musicquiz" "title": "cover_09"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_10", "asset_id": "musicquiz:cover_10",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_10", "author": "musicquiz",
"author": "musicquiz" "title": "cover_10"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_11", "asset_id": "musicquiz:cover_11",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_11", "author": "musicquiz",
"author": "musicquiz" "title": "cover_11"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_12", "asset_id": "musicquiz:cover_12",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_12", "author": "musicquiz",
"author": "musicquiz" "title": "cover_12"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_13", "asset_id": "musicquiz:cover_13",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_13", "author": "musicquiz",
"author": "musicquiz" "title": "cover_13"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_14", "asset_id": "musicquiz:cover_14",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_14", "author": "musicquiz",
"author": "musicquiz" "title": "cover_14"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_15", "asset_id": "musicquiz:cover_15",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_15", "author": "musicquiz",
"author": "musicquiz" "title": "cover_15"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_16", "asset_id": "musicquiz:cover_16",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_16", "author": "musicquiz",
"author": "musicquiz" "title": "cover_16"
} }

View File

@@ -1,7 +1,7 @@
{ {
"asset_id": "musicquiz:cover_17", "asset_id": "musicquiz:cover_17",
"width": 2, "width": 5,
"height": 2, "height": 5,
"title": "cover_17", "author": "musicquiz",
"author": "musicquiz" "title": "cover_17"
} }

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_18",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_18"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_19",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_19"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_20",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_20"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_21",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_21"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_22",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_22"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_23",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_23"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_24",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_24"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_25",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_25"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_26",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_26"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_27",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_27"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_28",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_28"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_29",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_29"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_30",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_30"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_31",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_31"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_32",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_32"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_33",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_33"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_34",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_34"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_35",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_35"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_36",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_36"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_37",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_37"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_38",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_38"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_39",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_39"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_40",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_40"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_41",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_41"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_42",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_42"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_43",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_43"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_44",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_44"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_45",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_45"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_46",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_46"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_47",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_47"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_48",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_48"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_49",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_49"
}

View File

@@ -0,0 +1,7 @@
{
"asset_id": "musicquiz:cover_50",
"width": 5,
"height": 5,
"author": "musicquiz",
"title": "cover_50"
}

View File

@@ -1,7 +1,5 @@
{ {
"asset_id": "musicquiz:gif", "asset_id": "musicquiz:gif",
"width": 2, "width": 1,
"height": 2, "height": 1
"title": "gif",
"author": "musicquiz"
} }