03 ║ BRIDGE PROTOCOL
브리지 프로토콜
클라 모드와 서버 플러그인은 fullmoon:v1 커스텀 채널 하나로
이야기해요. 스펙 전문은 저장소의 docs/BRIDGE.md에 있고, 여기서는
왜 이렇게 만들었는지만 짧게 봐요.
와이어 포맷: varint 프레임 + JSON 한 객체
페이로드는 마인크래프트 표준 부호 없는 varint 길이 뒤에 UTF-8 JSON 한
객체가 붙은 모양이에요. 맨 위에는 항상 type이 있어요. varint는
Fabric 모드의 FriendlyByteBuf.writeByteArray와 같게 맞춰 뒀어요.
처음엔 양쪽 프레이밍이 달라서 패킷이 사라졌고, 그걸 고친 뒤에 이 모양으로
고정했어요.
// 페이로드 한 개. type이 무슨 메시지인지 알려 줘요 {"type":"tp_request", "id":"palace_gate"}
handshake: hello 다음에 welcome
클라는 접속하자마자 hello{proto, client, version}을 보내고,
서버는 welcome{proto, waypoints[]}로 웨이포인트 목록을 줘요.
5초 안에 welcome이 없으면 클라는 그 접속 동안 브리지를 켜지 않아요.
모드가 깔렸는데 서버가 예전 버전이면, 어중간하게 켜 두지 않으려고 이렇게
나눴어요.
Bukkit은 클라의 채널 등록이 끝나기 전에 보낸 서버→클라 패킷을 그냥 버려요. 그래서 서버는 hello를 받아도 바로 답하지 않고, 등록됐는지 스케줄러로 본 다음에 보내요. main 스레드에서 기다리면 그 등록 처리가 막혀서, 스레드는 재우지 않아요.
클라는 좌표를 보내지 않아요
프로토콜은 공개돼 있어서 채널 메시지를 흉내낼 수는 있어요. 그래서 서버는 클라가 보낸 값을 그대로 믿지 않고, 자기 목록과 권한으로 다시 봐요.
- 좌표는 클라가 보내지 않아요.
tp_request에는 서버 목록에 있는 id만 들어가요. 아무 좌표로나 이동하는 메시지는 프로토콜에 없어요. - 확인할 순서는 항상 같아요. 권한 → 4초 쿨다운 → 같은 월드인지 → 목록에 있는지. 클라가 뭐라고 했든 매번 이 순서로 봐요.
- 거절도 답으로 보내요. 안 되면
tp_result{ok:false, reason}이 돌아와서, UI가 성공한 것처럼 그리지 않아요. - 모드가 없어도 같은 검사를 타요.
/워프명령도 같은 목록, 같은 확인을 써요. 할 수 있는 일은 같고, 보여 주는 화면만 달라요.