Skip to content

Instantly share code, notes, and snippets.

@NTT1906
Forked from LucienHH/BedrockP2P.js
Created May 23, 2025 08:12
Show Gist options
  • Select an option

  • Save NTT1906/8aeca324e5e4be557d58c09b26a98f42 to your computer and use it in GitHub Desktop.

Select an option

Save NTT1906/8aeca324e5e4be557d58c09b26a98f42 to your computer and use it in GitHub Desktop.

Revisions

  1. @LucienHH LucienHH created this gist Jan 20, 2024.
    104 changes: 104 additions & 0 deletions BedrockP2P.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,104 @@
    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();