music_quiz: dialog 기반 정답 입력 + 큐 기반 first-submit-wins 추가

정답 입력 UI 를 dialog 로 제공 (mq:dialog/answer), #minecraft:quick_actions 태그
등록으로 빠른행동키에서 바로 열 수 있게 함. 동시 제출 시 먼저 제출한 사람이 정답으로
인정되도록 mq:answer/ 에 submit_seq 기반 FIFO 큐 + 매크로 기반 제출자 lookup 으로
처리. tick/stop/setanswer 도 새 큐 흐름에 맞춰 업데이트.
This commit is contained in:
Claude (owner)
2026-05-13 22:20:58 +09:00
parent cea3d29c7d
commit 7adcda68de
12 changed files with 124 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"mq:answer"
]
}

View File

@@ -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)'}"
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,2 @@
# queue entry 의 seq 점수를 가진 플레이어(@s) 컨텍스트로 judge 실행
$execute as @a[scores={submit_seq=$(seq)},limit=1] run function mq:answer/judge

View File

@@ -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

View File

@@ -0,0 +1,4 @@
# trigger input 으로 호출됨 — 다음 trigger 사용을 위해 즉시 재활성화 후 dialog 표시
scoreboard players reset @s input
scoreboard players enable @s input
dialog show @s mq:answer

View File

@@ -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

View File

@@ -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

View File

@@ -13,6 +13,11 @@ scoreboard players set test buttons -1
scoreboard players reset @a answer 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 remove ready
scoreboard objectives add ready trigger scoreboard objectives add ready trigger
@@ -31,8 +36,15 @@ scoreboard objectives add hint trigger
scoreboard objectives remove replay scoreboard objectives remove replay
scoreboard objectives add replay trigger 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 setdisplay sidebar
scoreboard objectives remove score scoreboard objectives remove score
scoreboard objectives add score dummy {"text":"점수","bold":true} scoreboard objectives add score dummy {"text":"점수","bold":true}

View File

@@ -12,6 +12,15 @@ scoreboard players set skip buttons -1
scoreboard players set hint buttons -1 scoreboard players set hint buttons -1
scoreboard players set replay 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 scoreboard players set init main 5
function mq:quiz/play_sound function mq:quiz/play_sound

View File

@@ -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 2.. run function mq:repeat/timer
execute if score init main matches 5..6 run function mq:repeat/check_answer 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