Skip to content

Instantly share code, notes, and snippets.

@LucienHH
Created January 20, 2024 19:26
Show Gist options
  • Save LucienHH/dab431394dabc38026ee1dd81cd0cdbc to your computer and use it in GitHub Desktop.
Save LucienHH/dab431394dabc38026ee1dd81cd0cdbc to your computer and use it in GitHub Desktop.
Standard peer-to-peer WebRTC connection via Minecraft Bedrock's signalling channel
const WebSocket = require('ws');
const { RTCPeerConnection } = require('werift');
const token = ""
const networkId = "";
const randomID = () => Math.floor(Math.random() * 10000000000000000000)
const sessionId = randomID()
const offerId = randomID()
const main = async () => {
const ws = new WebSocket('wss://signal.franchise.minecraft-services.net/ws/v1.0/signaling/9806856835729287287', {
headers: { Authorization: token }
});
let resolve;
const promise = new Promise((res) => {
resolve = res;
});
ws.on('message', (data) => {
const message = JSON.parse(String(data));
switch (message.Type) {
case 1: {
const [type, id, ...rest] = message.Message.split(' ');
if (type === 'CONNECTRESPONSE') {
console.log(`Client <- Peer SDP answer`);
peer.setRemoteDescription({ type: 'answer', sdp: rest.join(' ') })
}
if (type === 'CANDIDATEADD') {
console.log(`Client <- Peer ICE candidate: ${rest.join(' ')}`);
peer.addIceCandidate({ candidate: rest.join(' ') })
.catch((error) => console.error('Error adding ICE candidate:', error));
}
break;
}
case 2: {
const payload = JSON.parse(message.Message);
resolve(payload);
break;
}
}
});
const data = await promise;
const peer = new RTCPeerConnection({
iceServers: [
{
urls: 'stun:relay.communication.microsoft.com:3478',
credential: data.Password,
username: data.Username
},
{
urls: 'turn:relay.communication.microsoft.com:3478',
credential: data.Password,
username: data.Username
},
]
});
peer.createDataChannel('test')
peer.onnegotiationneeded = async () => {
const offer = await peer.createOffer()
const pattern = /o=- \d+ 0 IN IP4 0\.0\.0\.0/;
const newOLine = `o=- ${offerId} 2 IN IP4 127.0.0.1`;
offer.sdp = offer.sdp.replace(pattern, newOLine);
console.log(`Client -> Peer SDP offer`);
await peer.setLocalDescription(offer)
const message = `{"Message": "CONNECTREQUEST ${sessionId} ${offer.sdp}","To":"${networkId}","Type":1}`
ws.send(message)
}
peer.onicecandidate = function (evt) {
if (evt.candidate) {
console.log(`Client -> Peer ICE candidate: ${evt.candidate.candidate}`);
const message = `{"Message":"CANDIDATEADD ${sessionId} ${evt.candidate.candidate}","To":${networkId},"Type":1}`
ws.send(message)
}
};
};
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment