-
Notifications
You must be signed in to change notification settings - Fork 39
Description
I propose adding /heartbeat.jsp endpoint to the sessionserver endpoint, for the purpose of supporting minecraft classic
Here is a barebones implementation of that endpoint in python
from flask import Flask, request
from urllib.parse import unquote_plus
import hashlib
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_host=1)
@app.route("/authlib-injector/sessionserver/heartbeat.jsp", methods=["GET", "POST"]) # supports both
def heartbeat():
vals = request.values
port = vals.get("port", "25565")
maxp = vals.get("max", "1")
name = unquote_plus(vals.get("name", "Minecraft Server"))
public = vals.get("public", "False")
version = vals.get("version", "7")
salt = vals.get("salt", "")
users = vals.get("users", "0")
ip = request.remote_addr
print(f"{name} ({ip}:{port}) - {salt} users: {users}/{maxp}, pub: {public}, v{version}")
key = hashlib.md5((salt + "Notch").encode("utf-8")).hexdigest()
print(f"Notch's key: {key}")
return f"http://minecraft.net/classic/play/foobar", 200, {"Content-Type": "text/plain"} # mc server accepts anything, this is not important
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
Heartbeat should be sent every 45 seconds by vanilla, we could require getting one every 5 minutes or server will be seen as offline. Drasl must remember IP port and salt.
Authentication works like so: mppass = md5(serverSalt + playerName)
More details here:
https://minecraft.wiki/w/Classic_server_protocol
https://www.grahamedgecombe.com/talks/minecraft.pdf
Historically, the server will at this point be listed on minecraft.net server list with a link (same link as server gets from heartbeat) that takes you to the minecraft applet
minecraft.net will populate the launch parameters for the applet for you, including the mppass for your account which you need correct to join the server. SessionID/accessToken is unused in these versions for authorizing, only mpPass matters.
Launcher will need to support using the custom endpoint to get mppass to launch with, because obviously the old solution is no longer going to work since we don't run game from browser anymore.
I propose an endpoint for this which launchers can implement
GET (sessionServer)/getMpPass?ip=1.2.3.4&port=optional_int_default_25565&player=Dinnerbone
Authorization: Bearer (token)
Returns 200 and body of mppass value e.g.
fd37a1c594b....
If ip/player is not specified, 400. If ip and port combo are not seen as being online (no ping in last 2-5 minutes) then 404. Empty bodies in both error cases.