From 7adcda68de1db9596f3eae77cbfb5e314066d292 Mon Sep 17 00:00:00 2001 From: "Claude (owner)" Date: Wed, 13 May 2026 22:20:58 +0900 Subject: [PATCH] =?UTF-8?q?music=5Fquiz:=20dialog=20=EA=B8=B0=EB=B0=98=20?= =?UTF-8?q?=EC=A0=95=EB=8B=B5=20=EC=9E=85=EB=A0=A5=20+=20=ED=81=90=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=20first-submit-wins=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 정답 입력 UI 를 dialog 로 제공 (mq:dialog/answer), #minecraft:quick_actions 태그 등록으로 빠른행동키에서 바로 열 수 있게 함. 동시 제출 시 먼저 제출한 사람이 정답으로 인정되도록 mq:answer/ 에 submit_seq 기반 FIFO 큐 + 매크로 기반 제출자 lookup 으로 처리. tick/stop/setanswer 도 새 큐 흐름에 맞춰 업데이트. --- .../minecraft/tags/dialog/quick_actions.json | 6 +++++ music_quiz/data/mq/dialog/answer.json | 26 +++++++++++++++++++ .../function/answer/iter_aliases.mcfunction | 10 +++++++ .../data/mq/function/answer/judge.mcfunction | 17 ++++++++++++ .../answer/macro/find_submitter.mcfunction | 2 ++ .../mq/function/answer/macro/match.mcfunction | 3 +++ .../data/mq/function/answer/open.mcfunction | 4 +++ .../mq/function/answer/process.mcfunction | 17 ++++++++++++ .../data/mq/function/answer/submit.mcfunction | 14 ++++++++++ .../data/mq/function/commands/stop.mcfunction | 12 +++++++++ .../mq/function/quiz/setanswer.mcfunction | 9 +++++++ music_quiz/data/mq/function/tick.mcfunction | 4 +++ 12 files changed, 124 insertions(+) create mode 100644 music_quiz/data/minecraft/tags/dialog/quick_actions.json create mode 100644 music_quiz/data/mq/dialog/answer.json create mode 100644 music_quiz/data/mq/function/answer/iter_aliases.mcfunction create mode 100644 music_quiz/data/mq/function/answer/judge.mcfunction create mode 100644 music_quiz/data/mq/function/answer/macro/find_submitter.mcfunction create mode 100644 music_quiz/data/mq/function/answer/macro/match.mcfunction create mode 100644 music_quiz/data/mq/function/answer/open.mcfunction create mode 100644 music_quiz/data/mq/function/answer/process.mcfunction create mode 100644 music_quiz/data/mq/function/answer/submit.mcfunction diff --git a/music_quiz/data/minecraft/tags/dialog/quick_actions.json b/music_quiz/data/minecraft/tags/dialog/quick_actions.json new file mode 100644 index 0000000..8e4c352 --- /dev/null +++ b/music_quiz/data/minecraft/tags/dialog/quick_actions.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "mq:answer" + ] +} diff --git a/music_quiz/data/mq/dialog/answer.json b/music_quiz/data/mq/dialog/answer.json new file mode 100644 index 0000000..f5d958b --- /dev/null +++ b/music_quiz/data/mq/dialog/answer.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:simple_input_form", + "title": { + "text": "정답 입력", + "bold": true + }, + "inputs": [ + { + "type": "minecraft:text", + "key": "text", + "label": { + "text": "정답" + }, + "width": 300, + "max_length": 64, + "initial": "" + } + ], + "can_close_with_escape": true, + "pause": false, + "after_action": "close", + "action": { + "type": "minecraft:dynamic/run_command", + "template": "function mq:answer/submit {text:'$(text)'}" + } +} diff --git a/music_quiz/data/mq/function/answer/iter_aliases.mcfunction b/music_quiz/data/mq/function/answer/iter_aliases.mcfunction new file mode 100644 index 0000000..c6a80c4 --- /dev/null +++ b/music_quiz/data/mq/function/answer/iter_aliases.mcfunction @@ -0,0 +1,10 @@ +# aliases 배열 첫 원소와 비교 → 매치 시 즉시 종료, 아니면 pop 후 재귀 +execute store result score alen func.temp run data get storage mq:tmp aliases +execute if score alen func.temp matches 0 run return 0 + +data modify storage mq:tmp judge.answer set from storage mq:tmp aliases[0] +function mq:answer/macro/match with storage mq:tmp judge +data remove storage mq:tmp aliases[0] + +execute if score @s answer matches 1 run return 0 +function mq:answer/iter_aliases diff --git a/music_quiz/data/mq/function/answer/judge.mcfunction b/music_quiz/data/mq/function/answer/judge.mcfunction new file mode 100644 index 0000000..3f7e298 --- /dev/null +++ b/music_quiz/data/mq/function/answer/judge.mcfunction @@ -0,0 +1,17 @@ +# 제출자(@s) 로 실행됨 — answer.title 및 alias 들과 비교 +# 매치되면 @s answer = 1 → check_answer 가 정답처리 흐름으로 진입 +# 매치 안되면 @s answer = 2 → check_answer 가 reset 처리 (1회 비교 후 초기화) + +# 1) 제목과 비교 +data modify storage mq:tmp judge.answer set from storage mq:main answer.title +function mq:answer/macro/match with storage mq:tmp judge + +# 2) 제목 매치 실패 시 alias 들과 순차 비교 (조기 종료) +execute unless score @s answer matches 1 run data modify storage mq:tmp aliases set from storage mq:main answer.alias +execute unless score @s answer matches 1 run function mq:answer/iter_aliases + +# 3) 끝까지 매치 실패면 오답 처리 (check_answer 가 reset) +execute unless score @s answer matches 1 run scoreboard players set @s answer 2 + +# 4) 처리 완료 — 이 제출자의 submit_seq 정리 (다음 큐 항목과 혼동 방지) +scoreboard players reset @s submit_seq diff --git a/music_quiz/data/mq/function/answer/macro/find_submitter.mcfunction b/music_quiz/data/mq/function/answer/macro/find_submitter.mcfunction new file mode 100644 index 0000000..02f9756 --- /dev/null +++ b/music_quiz/data/mq/function/answer/macro/find_submitter.mcfunction @@ -0,0 +1,2 @@ +# queue entry 의 seq 점수를 가진 플레이어(@s) 컨텍스트로 judge 실행 +$execute as @a[scores={submit_seq=$(seq)},limit=1] run function mq:answer/judge diff --git a/music_quiz/data/mq/function/answer/macro/match.mcfunction b/music_quiz/data/mq/function/answer/macro/match.mcfunction new file mode 100644 index 0000000..0eb8d79 --- /dev/null +++ b/music_quiz/data/mq/function/answer/macro/match.mcfunction @@ -0,0 +1,3 @@ +# judge.input 과 judge.answer 가 같으면 @s answer = 1 +# 매크로 치환으로 answer 필드를 NBT predicate 의 리터럴로 박아넣음 +$execute if data storage mq:tmp judge {input:"$(answer)"} run scoreboard players set @s answer 1 diff --git a/music_quiz/data/mq/function/answer/open.mcfunction b/music_quiz/data/mq/function/answer/open.mcfunction new file mode 100644 index 0000000..57d10ec --- /dev/null +++ b/music_quiz/data/mq/function/answer/open.mcfunction @@ -0,0 +1,4 @@ +# trigger input 으로 호출됨 — 다음 trigger 사용을 위해 즉시 재활성화 후 dialog 표시 +scoreboard players reset @s input +scoreboard players enable @s input +dialog show @s mq:answer diff --git a/music_quiz/data/mq/function/answer/process.mcfunction b/music_quiz/data/mq/function/answer/process.mcfunction new file mode 100644 index 0000000..c77bd65 --- /dev/null +++ b/music_quiz/data/mq/function/answer/process.mcfunction @@ -0,0 +1,17 @@ +# tick 에서 매 tick 호출됨 — 큐의 가장 먼저 제출된 항목 1개를 처리 +# 1 tick 당 1건 처리 — 동시 다발 제출은 FIFO 순서로 자동 직렬화됨 +execute store result score qlen func.temp run data get storage mq:input queue +execute if score qlen func.temp matches 0 run return 0 + +# 첫번째 항목 = 가장 먼저 제출된 것 +data modify storage mq:tmp judge set value {input:"", answer:""} +data modify storage mq:tmp judge.input set from storage mq:input queue[0].text + +# 매크로로 해당 seq 를 가진 플레이어 찾아서 judge 실행 +data modify storage mq:tmp _find set value {seq:0} +data modify storage mq:tmp _find.seq set from storage mq:input queue[0].seq + +# 항목 제거 (한 번 비교했으면 큐에서 빼기) +data remove storage mq:input queue[0] + +function mq:answer/macro/find_submitter with storage mq:tmp _find diff --git a/music_quiz/data/mq/function/answer/submit.mcfunction b/music_quiz/data/mq/function/answer/submit.mcfunction new file mode 100644 index 0000000..3f9ce5b --- /dev/null +++ b/music_quiz/data/mq/function/answer/submit.mcfunction @@ -0,0 +1,14 @@ +# 정답 dialog 제출 핸들러 — 매크로 인자 {text:"..."} 받음 +# 퀴즈 진행 중(init=5) 이 아니면 제출 무시 +execute unless score init main matches 5 run return 0 + +# 제출 순번 부여 — seq 는 setanswer 에서 0 으로 초기화됨 +# 동일 tick 내 동시 제출도 명령 실행 순서대로 1씩 증가하여 고유한 seq 가 부여됨 +scoreboard players add seq func.temp 1 +scoreboard players operation @s submit_seq = seq func.temp + +# 큐에 {text, seq} append — process 는 queue[0] (가장 먼저 제출된 것) 부터 처리 +data modify storage mq:tmp new_entry set value {text:"", seq:0} +execute store result storage mq:tmp new_entry.seq int 1 run scoreboard players get @s submit_seq +$data modify storage mq:tmp new_entry.text set value "$(text)" +data modify storage mq:input queue append from storage mq:tmp new_entry diff --git a/music_quiz/data/mq/function/commands/stop.mcfunction b/music_quiz/data/mq/function/commands/stop.mcfunction index f2ba1d6..f328905 100644 --- a/music_quiz/data/mq/function/commands/stop.mcfunction +++ b/music_quiz/data/mq/function/commands/stop.mcfunction @@ -13,6 +13,11 @@ scoreboard players set test buttons -1 scoreboard players reset @a answer +# 정답 입력 큐 / 제출 순번 초기화 +data remove storage mq:input queue +scoreboard players reset @a submit_seq +scoreboard players set seq func.temp 0 + # 트리거 시작 scoreboard objectives remove ready scoreboard objectives add ready trigger @@ -31,8 +36,15 @@ scoreboard objectives add hint trigger scoreboard objectives remove replay scoreboard objectives add replay trigger + +scoreboard objectives remove input +scoreboard objectives add input trigger # 트리거 끝 +# 제출자 식별용 순번 점수 (queue entry 의 seq 와 매칭) +scoreboard objectives remove submit_seq +scoreboard objectives add submit_seq dummy + scoreboard objectives setdisplay sidebar scoreboard objectives remove score scoreboard objectives add score dummy {"text":"점수","bold":true} diff --git a/music_quiz/data/mq/function/quiz/setanswer.mcfunction b/music_quiz/data/mq/function/quiz/setanswer.mcfunction index 4cd712d..1bf71b3 100644 --- a/music_quiz/data/mq/function/quiz/setanswer.mcfunction +++ b/music_quiz/data/mq/function/quiz/setanswer.mcfunction @@ -12,6 +12,15 @@ scoreboard players set skip buttons -1 scoreboard players set hint buttons -1 scoreboard players set replay buttons -1 +# 이전 문제의 미처리 정답 입력 정리 + 새 문제의 input trigger 활성화 +data remove storage mq:input queue +scoreboard players reset @a submit_seq +scoreboard players set seq func.temp 0 +scoreboard players enable @a input + +# 정답 입력 안내 (클릭 시 trigger input → tick 에서 dialog 오픈) +function mq:tellraw {"text":"","color":"black",msg:[{"text":"[ 정답 입력 ]","color":"green","bold":true,"click_event":{"action":"run_command","command":"/trigger input set 1"},"hover_event":{"action":"show_text","value":{"text":"클릭하여 정답 입력창 열기","color":"gray"}}}]} + scoreboard players set init main 5 function mq:quiz/play_sound diff --git a/music_quiz/data/mq/function/tick.mcfunction b/music_quiz/data/mq/function/tick.mcfunction index 75b4c15..a796785 100644 --- a/music_quiz/data/mq/function/tick.mcfunction +++ b/music_quiz/data/mq/function/tick.mcfunction @@ -4,3 +4,7 @@ function mq:repeat/triggers/handler execute if score init main matches 2.. run function mq:repeat/timer execute if score init main matches 5..6 run function mq:repeat/check_answer + +# 정답 입력 다이얼로그: init=5 (곡 재생 중) 일 때만 열림 / 제출 처리 +execute if score init main matches 5 as @a[scores={input=1..}] run function mq:answer/open +execute if score init main matches 5 run function mq:answer/process