installer: multi-role host/participant split + auto-platform + EULA + port UX

step2:
- 멀티 선택 시 호스트 / 참가자 sub-choice 추가. 호스트 는 기존 멀티 흐름 그대로,
  참가자 는 step3 (서버 설치) 를 건너뛰고 step4 client install 만 진행.

step4 client install:
- 플랫폼 설치/생략 선택 화면(sub41) 제거. 음악퀴즈 platform.type 이 vanilla 가
  아니면 무조건 자동 설치, vanilla 면 자동 건너뜀. 사용자 결정 없음.
- 참가자 모드에서는 ClientInstallPayload.skipMap=true 로 보내 client 측
  saves/ 에 맵을 풀지 않는다 (서버에 이미 있음).
- types.ts 에 skipMap 필드 추가. main.ts client:install 핸들러에서 분기.

step3 EULA modal:
- eula.txt 의 내용과 무관하게 항상 minecraft.net 의 공식 서버 EULA 페이지를
  받아 iframe 에 표시. readEula() 분기 제거.

step3 포트포워딩 결과:
- 성공(preForwarded/upnpOk) 시 "친구는 <address> 주소로 서버에 접속할 수
  있습니다" 처럼 외부 주소를 강조해 표시.
- 포트가 25565 면 :포트 를 생략하고 ip 만 보여줌 (마인크래프트 자바판
  기본 포트라 클라이언트에서도 생략 가능).

step5:
- 서버 마무리 액션 (바로가기/서버 실행 토글) 은 호스트 만 노출. 참가자는
  서버를 띄우지 않으므로 런처 토글만 보인다.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-16 22:06:48 +09:00
parent 848fac500e
commit 49f320fa71
4 changed files with 109 additions and 103 deletions

View File

@@ -42,7 +42,12 @@
"singleTitle": "싱글",
"singleHint": "싱글 맵으로 혼자 플레이할때",
"multiTitle": "멀티",
"multiHint": "버킷 서버로 친구들과 같이 플레이할때"
"multiHint": "버킷 서버로 친구들과 같이 플레이할때",
"roleHeading": "호스트 / 참가자",
"hostTitle": "호스트",
"hostHint": "내가 서버를 직접 열고 친구들을 초대할 때",
"participantTitle": "참가자",
"participantHint": "친구가 연 서버에 접속만 할 때 (맵은 받지 않음)"
},
"step3": {
"heading": "서버 관련 설정",
@@ -90,8 +95,7 @@
},
"eulaModal": {
"title": "Minecraft EULA 동의",
"fromFile": "서버 파일에 포함된 eula.txt 내용입니다.",
"fromMojang": "서버 파일에 eula.txt가 없어 minecraft.net의 EULA를 표시합니다 (<a href=\"{{url}}\" target=\"_blank\">{{url}}</a>).",
"fromMojang": "마인크래프트 서버를 실행하려면 아래 EULA에 동의해야 합니다 (<a href=\"{{url}}\" target=\"_blank\">{{url}}</a>).",
"loadFailed": "EULA 페이지를 불러올 수 없습니다. 직접 확인해 주세요: <a href=\"https://www.minecraft.net/en-us/eula\" target=\"_blank\">https://www.minecraft.net/en-us/eula</a>"
},
"sub34": {
@@ -107,26 +111,16 @@
"portLabel": "포트",
"recheck": "재점검",
"checking": "확인 중...",
"preForwarded": "이미 외부 접속 가능: {{ip}}:{{port}}",
"upnpOk": "UPnP로 자동 개방 완료: {{ip}}:{{port}}",
"preForwarded": "포트포워딩 성공! 친구는 <strong>{{address}}</strong> 주소로 서버에 접속할 수 있습니다. (이미 외부 개방되어 있음)",
"upnpOk": "포트포워딩 성공! 친구는 <strong>{{address}}</strong> 주소로 서버에 접속할 수 있습니다. (UPnP로 자동 개방 완료)",
"manualHint": "직접 포트포워딩을 해주세요.",
"manualDetail": "<br><small>외부 IP: {{ip}}, 포트: {{port}}</small>",
"manualDetail": "<br><small>외부 주소: {{address}}</small>",
"checkFailed": "점검 실패: {{message}}",
"ipUnknown": "확인 불가"
}
},
"step4": {
"heading": "클라이언트 설정",
"sub41": {
"heading": "플랫폼",
"vanillaInfo": "선택한 음악퀴즈의 플랫폼: <strong>vanilla</strong>",
"vanillaNoInstall": "바닐라이므로 별도 설치는 필요 없습니다.",
"info": "선택한 음악퀴즈의 플랫폼: <strong>{{platform}}</strong>",
"installTitle": "권장 플랫폼 설치",
"installHint": "{{platform}} 설치",
"skipTitle": "기본 마인크래프트로 설치",
"skipHint": "설치하지 않고 바닐라로 진행합니다."
},
"sub42": {
"heading": "다운로드 및 적용",
"description": "클라이언트 설정",
@@ -196,7 +190,7 @@
"labelServerFile": "서버 파일",
"labelMap": "맵",
"skipServerZip": "서버 파일(serverPath)이 비어 있어 서버 zip 다운로드를 건너뜁니다.",
"skipMapZip": "맵 파일(mapPath)이 비어 있어 맵 다운로드를 건너뜁니다.",
"skipMapZip": "맵 다운로드를 건너뜁니다 (mapPath 비어 있음 또는 참가자 모드).",
"skipModsFolder": "modsFolder가 비어 있어 모드 다운로드를 건너뜁니다.",
"modsIndexFetch": "모드 목록 조회: {{url}}",
"modsFolderEmpty": "/file/mods/{{folder}}/ 안에 .jar 파일이 없습니다.",