코드와 산출물 jar 에는 애초에 외부 서버 주소가 없었으나(rendezvous 기본값이 빈 문자열), 설계 문서에 참고 대상의 제작자명과 저장소 경로가 남아 있었다. 기술적 관찰 사실은 설계 판단의 근거로 필요하므로 유지하되 "기존 구현" 으로 중립화했다. 더불어 이 프로젝트가 남의 인프라에 얹혀 가지 않는다는 점을 README 에 명시했다. rendezvous 는 빈 값으로 시작해 사용자가 직접 띄운 서버만 쓰며, 유일하게 남는 외부 호출인 STUN 기본값도 제거하는 방법을 함께 적었다. 검증: 작업 트리와 양쪽 산출물 jar 전수 검색 0건, 테스트 57개 전부 통과. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
12
README.md
12
README.md
@@ -52,6 +52,18 @@ java -jar mc_p2p_mod-<버전>-rendezvous.jar 25580 40000-40100
|
||||
서버를 띄웠으면 게임에서 `http://127.0.0.1:25585` 를 열고 주소를 넣고 저장한다.
|
||||
예: `p2p.example.com:25580`
|
||||
|
||||
### 외부 서버를 쓰지 않는다
|
||||
|
||||
이 모드에는 **다른 사람의 시그널링·중계 서버 주소가 기본값으로 들어 있지 않다.** `rendezvous`
|
||||
는 비어 있는 상태로 시작하고, 사용자가 직접 띄운 서버를 넣어야 비로소 동작한다. 남의 인프라에
|
||||
얹혀 가는 구성을 아예 만들 수 없게 한 것이다.
|
||||
|
||||
남는 외부 호출은 `stun` 기본값 하나뿐이다(`stun.l.google.com:19302`). 공인 주소를 알아내는 데만
|
||||
쓰이고 게임 트래픽은 지나가지 않는다. 그래도 완전히 없애고 싶으면 두 가지 방법이 있다.
|
||||
|
||||
- 같은 공유기 안에서만 쓸 거라면 `stun` 을 빈 값으로 둔다. 외부 호출이 0 이 된다.
|
||||
- 인터넷을 넘어야 하면 직접 띄운 STUN 서버(coturn 등)를 적는다.
|
||||
|
||||
---
|
||||
|
||||
## 방 만들기 (호스트)
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
|
||||
## 2. "jar 하나로 모든 버전" 이 왜 어려운가
|
||||
|
||||
기존 P2P 모드들(참고 대상: `KITE2459/kfcudp-instant-p2p`)은 Stonecutter 로 17개 버전을
|
||||
각각 빌드한다. 게을러서가 아니라, 마인크래프트 클래스를 참조하면 그 방법밖에 없기 때문이다.
|
||||
기존에 배포되는 P2P 모드들은 Stonecutter 로 17개 버전을 각각 빌드한다. 게을러서가 아니라,
|
||||
마인크래프트 클래스를 참조하면 그 방법밖에 없기 때문이다.
|
||||
|
||||
> 이 문서에서 "기존 구현" 이라고 적은 것은 착수 전 조사 단계에서 살펴본 배포본 한 종을
|
||||
> 가리킨다. 설계 판단의 근거를 남기기 위해 관찰한 사실만 적었고, 제작자·저장소·서버 주소는
|
||||
> 적지 않는다. 코드를 가져오지 않았고 그들의 인프라에 접속하지도 않는다.
|
||||
|
||||
결정적인 단절이 2026년에 생겼다. **마인크래프트 26.1부터 코드가 비난독화되면서 Fabric 의
|
||||
Yarn/intermediary 매핑이 폐지됐다.**
|
||||
@@ -79,7 +83,7 @@ GUI 코드가 한 줄도 필요 없다.
|
||||
### 얻은 것
|
||||
|
||||
- 버전별 빌드 17개 → 1개
|
||||
- Stonecutter 조건부 주석 (참고 모드의 `RoomListScreen.java` 한 파일에만 96개) → 0개
|
||||
- Stonecutter 조건부 주석 (기존 구현은 GUI 한 파일에만 96개) → 0개
|
||||
- 믹스인 14개 → 0개. 다른 모드와 충돌할 지점도 함께 사라졌다.
|
||||
- Fabric Loom·매핑·마인크래프트 jar 다운로드 없음 → 빌드가 몇 초로 끝나고 CI 매트릭스도 1칸
|
||||
- 게임 API 를 안 건드리므로 새 마인크래프트 버전이 나와도 할 일이 없다
|
||||
@@ -105,7 +109,7 @@ GUI 코드가 한 줄도 필요 없다.
|
||||
| NAT traversal | 직접 구현 | libwebrtc 내장 (검증 충분) |
|
||||
|
||||
**순수 자바 QUIC을 선택했다.** 크기가 42배 차이 나고, 아키텍처 제약이 사라지는 것이 결정적이다.
|
||||
참고 모드의 WebRTC 빌드는 `linux-aarch64` 를 번들에서 빠뜨려서 ARM 리눅스에서 아예 실패하는데,
|
||||
기존 구현의 WebRTC 빌드는 `linux-aarch64` 를 번들에서 빠뜨려서 ARM 리눅스에서 아예 실패하는데,
|
||||
네이티브가 없으면 그런 실수를 할 여지 자체가 없다. "jar 하나로 모든 버전" 목표와도 맞는다.
|
||||
QUIC 은 암호화·혼잡제어·다중화를 프로토콜 한 겹에서 주므로 DTLS+SCTP+ICE 조합보다 얇다.
|
||||
|
||||
@@ -144,7 +148,7 @@ siphash 뿐이고 모두 순수 자바다. 클래스 파일 major 55 = Java 11
|
||||
때문이다. 최악의 대기가 600ms 인 대신 구현이 훨씬 단순하다.
|
||||
`P2PSocket.awaitPath` 에 이 판단을 적어 두었고, 갈아타기는 아래 남은 과제로 넘겼다.
|
||||
|
||||
참고 모드는 이걸 다르게 풀었다. 1차는 TURN 후보를 아예 만들지 않고, 실패하면 2차에 릴레이를
|
||||
기존 구현은 이걸 다르게 풀었다. 1차는 TURN 후보를 아예 만들지 않고, 실패하면 2차에 릴레이를
|
||||
허용해 재협상한다. 목적은 같지만 세션을 두 번 만들고, 양쪽이 같은 단계로 맞춰야 해서
|
||||
"조인자의 OFFER 재협상 횟수로 호스트가 단계를 유추" 하는 조율이 들어간다. 유예 방식은
|
||||
세션 하나로 끝난다.
|
||||
@@ -224,7 +228,7 @@ JDK 안에서 끝내면 그 변수가 사라진다.
|
||||
2. **실제 NAT 뒤에서의 홀펀칭 성공률 측정.** 같은 기기 안 테스트에는 NAT 가 없다. 대칭 NAT·
|
||||
CGNAT 비율에 따라 중계 의존도가 결정되므로 숫자를 봐야 다음 판단을 할 수 있다.
|
||||
3. **시그널링 TLS.** 지금은 평문 TCP 라 이 경로를 장악한 중간자가 인증서 지문을 바꿔칠 수
|
||||
있다. 참고 모드도 같은 약점을 갖고 있다(기본 `ws://`). TLS 를 씌우거나 초대코드에서
|
||||
있다. 기존 구현도 같은 약점을 갖고 있다(기본 `ws://`). TLS 를 씌우거나 초대코드에서
|
||||
파생한 키로 시그널링 메시지를 인증하면 된다. 후자가 서버 인증서 없이 되므로 더 맞을 수 있다.
|
||||
4. **중계 → 직결 승격.** 4절에서 미룬 것. 중계로 먼저 붙여 대기를 0 으로 만들고, 홀펀칭이
|
||||
성공하면 조용히 갈아탄다. QUIC 의 연결 마이그레이션(CID 유지)을 쓰면 재핸드셰이크 없이
|
||||
@@ -254,4 +258,8 @@ JDK 안에서 끝내면 그 변수가 사라진다.
|
||||
- [NAT Traversal — iroh](https://docs.iroh.computer/concepts/nat-traversal) — 중계 우선 + 직결 승격, 성공률
|
||||
- [How Tailscale is improving NAT traversal](https://tailscale.com/blog/nat-traversal-improvements-pt-1) — DERP 폴백 모델
|
||||
- [Kwik](https://github.com/ptrd/kwik) — 순수 자바 QUIC
|
||||
- 참고 구현: `KITE2459/kfcudp-instant-p2p` (CC0) — 문제 정의와 UX 를 참고했다. 코드는 가져오지 않았다.
|
||||
|
||||
이 목록 외에, 착수 전 조사 단계에서 배포 중인 P2P 모드 한 종을 분석해 문제 정의와 UX 를
|
||||
참고했다. 본문에서 "기존 구현" 이라고 쓴 것이 그것이다. 제작자·저장소·서버 주소는 의도적으로
|
||||
적지 않는다. 코드를 가져오지 않았고, 그들의 시그널링·STUN·TURN 서버를 쓰지도 않는다 —
|
||||
이 프로젝트는 사용자가 직접 띄운 서버만 사용한다(README 의 시그널링 서버 항목 참고).
|
||||
|
||||
Reference in New Issue
Block a user