Nethernet support for joining worlds#533
Conversation
|
Thanks for working on this, please advise when it's ready for review |
|
Most the work is done apart from some bits but would probably be good to start moving parts of this out of here into other areas. Mainly moving the contents of ./nethernet, I'd think it'd make sense to have this in a prismarine-nethernet repo maybe? Same with the Xbox Session API, I think we could get away with putting this in pauth unless you think we should separate an Xbox API to another repo? |
|
|
||
| client.conLog?.(`Connecting to ${client.options.host}:${client.options.port} ${ad.motd} (${ad.levelName}), version ${ad.version} ${client.options.version !== ad.version ? ` (as ${client.options.version})` : ''}`) | ||
| } else if (client.options.transport === 'nethernet') { | ||
| client.conLog?.(`Connecting to ${client.options.networkId} ${ad.motd} (${ad.levelName})`) |
There was a problem hiding this comment.
How do we know what version to connect as here if the user does not specify/can't get via ping?
There was a problem hiding this comment.
If the user doesn't specify it defaults to the current version and the version isn't included in the Nethernet ping response
There was a problem hiding this comment.
OK, what is advertisement.version then? We may have to figure out the version after connecting to the server then like nmp can do. It should be sent in login/network_settings packet otherwise. The current code should also be matching version by protocol version num over strings but that should be fixed outside this PR
There was a problem hiding this comment.
Not entirely sure but I assume it's the version of NetherNet protocol being used as it's just a uint8. From my testing it's always been set to 3 over multiple version updates.
extremeheat
left a comment
There was a problem hiding this comment.
node-fetch can be removed in favor of native fetch now that it's also removed from prismarine-auth
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Hi, great work so far on this PR. I've developed a similar nethernet implementation that is fully working as of the latest update to minecraft. The new bedrock signalling servers use the JSON-RPC format, not the old On Realm connections (and some newer Xbox session flows), the signalling websocket sends messages in this format: {
"jsonrpc": "2.0",
"method": "NetherNetMessage",
"params": {
"fromNetherNetId": "12312312312312312",
"innerMessage": "<SignalStructure b64 payload>"
}
}And expects signals from the client in this format: {
"jsonrpc": "2.0",
"method": "NetherNetMessage",
"params": {
"netherNetId": "12312312312312312",
"message": "<SignalStructure b64 payload>"
}
}I've patched const client = bedrock.createClient({
transport: 'nethernet',
useSignalling: true,
signallingProtocol: 'jsonrpc',
//...
})Internal patch (to // new parameter 'options'
constructor(networkId, authflow, version, options = {}) {
//...
this.protocol = options.protocol || 'legacy'
}
// send new or legacy format
write(signal) {
const message = this.protocol === 'jsonrpc'
? stringify({
jsonrpc: '2.0',
method: 'NetherNetMessage',
params: {
netherNetId: String(signal.networkId),
message: signal.toString()
}
})
: stringify({ Type: MessageType.Signal, To: signal.networkId, Message: signal.toString() })
this.ws.send(message)
}
onJsonRpcMessage(message) {
const signal = parseJsonRpcSignal(message)
if (!signal) return debug('Unhandled jsonrpc message', message)
this.emit('signal', signal)
}I also modified the onMessage function to catch inbound jsonrpc messages by default when all other cases fail: default: {
if (message.jsonrpc) this.onJsonRpcMessage(message)
}Helpers: function parseSignalMessage(message) {
if (typeof message !== 'string') return null
try {
const parsed = JSON.parse(message)
const signal = parseJsonRpcSignal(parsed)
if (signal) return signal
} catch {}
return SignalStructure.fromString(message)
}
function parseJsonRpcSignal(message) {
const params = message?.params || message?.Params || message?.result || message?.Result
if (!params || typeof params !== 'object') return null
const signalText = params.message || params.Message || params.innerMessage || params.InnerMessage
if (!signalText) return null
const signal = SignalStructure.fromString(signalText)
const networkId = params.netherNetId || params.NetherNetId || params.fromNetherNetId || params.FromNetherNetId || params.fromPlayerId || params.FromPlayerId
if (networkId) signal.networkId = String(networkId)
return signal
}And in this.nethernet.signalling = new NethernetSignal(
this.connection.nethernet.networkId,
this.options.authflow,
this.options.version,
{ protocol: this.options.signallingProtocol }
)The I'd be happy to open a follow up pr against this branch if that'd be easier. Let me know! 🙂 |
|
Hi @yntha, appreciate the write up! Yeah please do that'd be very helpful as I haven't had time recently to work on this. |
|
Ready for merge into a dev branch? |
|
Looks like CI failing is that related to PR? |
Majority work for Nethernet support. Supports listening and joining over LAN, signalling via the franchise WebSocket and creating/joining an Xbox session.
To do
Closes #473