From ddae9202983d3c7d0606efad532facee8f0f0c0e Mon Sep 17 00:00:00 2001 From: Colbster937 Date: Wed, 1 Apr 2026 20:12:42 -0500 Subject: [PATCH 01/12] feat: merge 1.8 and 1.12, clean up wispcraft icon --- setup.sh | 22 ++++++++++++------- src/buffer.ts | 10 +++++++++ src/connection/fakewebsocket.ts | 6 +++--- src/connection/index.ts | 2 +- src/connection/wispcraft.png | Bin 5356 -> 0 bytes src/img/workshop.png | Bin 0 -> 2533 bytes src/img/workshop64.png | Bin 0 -> 1279 bytes src/index.ts | 4 +++- src/{1.8.ts => proxy.ts} | 36 ++++++++++++++++++++++---------- src/ui.ts | 9 ++++---- 10 files changed, 61 insertions(+), 28 deletions(-) delete mode 100644 src/connection/wispcraft.png create mode 100644 src/img/workshop.png create mode 100644 src/img/workshop64.png rename src/{1.8.ts => proxy.ts} (95%) diff --git a/setup.sh b/setup.sh index 2f82f5a..9057a3e 100755 --- a/setup.sh +++ b/setup.sh @@ -1,11 +1,17 @@ #!/bin/sh - +rm -rf dist +mkdir -p dist npm run build - cd dist -curl -L https://bafybeialxd4xd7puchx555zqrfmuaz7e7n7nh4crb3sfhvprxedx4c64fq.ipfs.dweb.link/?filename=EaglercraftX_1.8_WASM-GC_Offline_Download.zip -o eaglercraft.zip -unzip eaglercraft.zip -rm eaglercraft.zip -mv EaglercraftX_1.8_WASM-GC_Offline_Download.html index.html -sed -i 's//\|' index.html +else + sed -i '' 's|||' index.html +fi diff --git a/src/buffer.ts b/src/buffer.ts index 955aa32..095ab9a 100644 --- a/src/buffer.ts +++ b/src/buffer.ts @@ -71,6 +71,16 @@ export class Buffer { this.extend(new Buffer(data)); } + readUByte(): number { + const ret = this.get(0); + this.take(1); + return ret; + } + + writeUByte(num: number) { + this.extend(new Buffer([num & 0xff])); + } + readUShort(): number { const ret = (this.get(0) << 8) | this.get(1); this.take(2); diff --git a/src/connection/fakewebsocket.ts b/src/connection/fakewebsocket.ts index 5b00983..0bd7c72 100644 --- a/src/connection/fakewebsocket.ts +++ b/src/connection/fakewebsocket.ts @@ -8,8 +8,8 @@ import { authstore, COMMITHASH, VERSION, wispUrl } from ".."; import { Buffer } from "../buffer"; import { showUI } from "../ui"; import { epoxyWs } from "./epoxy"; -// @ts-ignore typescript sucks -import wispcraft from "./wispcraft.png"; +// @ts-ignore +import workshop from "../img/workshop64.png"; class WispWS extends EventTarget { inner: Connection; @@ -132,7 +132,7 @@ class SettingsWS extends EventTarget { }), }) ); - fetch(wispcraft) + fetch(workshop) .then((response) => response.blob()) .then((blob) => createImageBitmap(blob)) .then((image) => { diff --git a/src/connection/index.ts b/src/connection/index.ts index c075a5e..b8e8885 100644 --- a/src/connection/index.ts +++ b/src/connection/index.ts @@ -1,4 +1,4 @@ -import { EaglerProxy } from "../1.8"; +import { EaglerProxy } from "../proxy"; import { connect_tcp } from "./epoxy"; import { epoxyFetch } from "./epoxy"; import { Buffer } from "../buffer"; diff --git a/src/connection/wispcraft.png b/src/connection/wispcraft.png deleted file mode 100644 index 497d46e6994c30de156397dc63e032e632944812..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5356 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 diff --git a/src/img/workshop.png b/src/img/workshop.png new file mode 100644 index 0000000000000000000000000000000000000000..82fa6dbdbb92057833b2466157e7be1b0a8fb373 GIT binary patch literal 2533 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 literal 0 HcmV?d00001 diff --git a/src/img/workshop64.png b/src/img/workshop64.png new file mode 100644 index 0000000000000000000000000000000000000000..c1838bbb7880919b93fa15da2ce33ec003c7d2ca GIT binary patch literal 1279 zcmV;5tS-<_OT)**SxT=QK3Zum;qCQZvD6EgYK!SHW2j zbOflZth`S}5a(cpt*NM}xGk8*N%M^q1UT4ZWo2dcaNi&@;IKWkbD1K-AtAt$T(>JS_mjUuxM*_%- z*j6{qfIfuU5B6r^HDy2hLBl@a#d9OlN`2DJNC0jlJF2UzZ-TonVA2Botd+Riz>DV` zul$1lr{72bRxhKNq{^oV3zy4CfN)VLZZ?qsCi-#xmMQwFe2TEbF3vvy9&)Lj<9LuB z-sb63K7s!a(6-QJ0Hhm7Mn>jURaNasBob#hUeDe22UQ zbJMbTJZ?0;kpQS|G*}@Pr`z*&m{1_rU2Imp|j0@6zwH#|&4@>}F zHGT8hpv14gH;M_$m(fo-2IBwxorRGAOiZ4YS{&-~0j_-){hI0%7e?XkJDF zurl)X8|&}yU*>L7@{wzKQ=y4yw&#tn+20E{5&#J)5PO{R=_(ph3*)y_H>>2YshejcE0c|w z9}h@GHX3m;>LgEKGV5JkU31A6<7bIeS^zfH^*oAu#{$d-j_H1cP5@T(B*gakf$RM+ zUxyE9{{q=(U@kDW&?_V8|t^V9MM1uG5i*Wx^Cegylcz$)W@q7m+m;u45a z5HB8{SfoJH;NYP1!qyRhR7mr*Mf|t&b%-GT=C_OElrW7+3QjLr`L%GZudS_3i@tvW p009608h!|+00006Nkl> 8) & 0xff, pvn & 0xff]; + } +} + export class EaglerProxy { loggedIn: boolean = false; handshook: boolean = false; @@ -142,6 +148,8 @@ export class EaglerProxy { offlineUuid: string = ""; isPremium: boolean = false; + protocol: number = -1; + constructor( eaglerOut: BytesWriter, epoxyOut: BytesWriter, @@ -160,14 +168,20 @@ export class EaglerProxy { case State.Handshaking: switch (packet.readVarInt()) { case Serverbound.EAG_ClientVersion: + packet.readUByte(); + const l = packet.readUShort(); + for (let i = 0; i < l; i++) { + packet.readUShort(); + } + packet.readUShort() + this.protocol = packet.readUShort(); const fakever = new Packet(Clientbound.EAG_ServerVersion); { const brand = new TextEncoder().encode("Wispcraft"); fakever.writeBytes([ 0, 3, - 0, - MINECRAFT_PROTOCOL_VERSION, + ...createProtocolArray(this.protocol), brand.length, ]); fakever.extend(new Buffer(brand)); @@ -199,7 +213,7 @@ export class EaglerProxy { this.state = State.Login; let handshake = new Packet(Serverbound.Handshake); - handshake.writeVarInt(MINECRAFT_PROTOCOL_VERSION); + handshake.writeVarInt(this.protocol); handshake.writeString(this.serverAddress); handshake.writeUShort(this.serverPort); handshake.writeVarInt(State.Login); @@ -415,7 +429,7 @@ export class EaglerProxy { // pings remote server, sends json to eagler async ping() { let handshake = new Packet(Serverbound.Handshake); - handshake.writeVarInt(MINECRAFT_PROTOCOL_VERSION); + handshake.writeVarInt(47); handshake.writeString(this.serverAddress); handshake.writeUShort(this.serverPort); handshake.writeVarInt(State.Status); diff --git a/src/ui.ts b/src/ui.ts index 1f230d7..de3165d 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -1,7 +1,9 @@ import { deviceCodeAuth, getProfile, minecraftAuth } from "./auth"; import { reconnect, set_wisp_server } from "./connection/epoxy"; -import { authstore, TokenStore } from "."; +import { authstore, DEFAULT_WISP_URL, TokenStore, wispUrl } from "."; import encodeQR from "qr"; +// @ts-ignore +import workshop from "./img/workshop.png"; let keydownListeners: Array = []; const nativeAddEventListener = window.addEventListener; @@ -253,7 +255,6 @@ export function createUI() { width: 148px; height: 148px; transition: all 0.2s ease; - cursor: none; } .settings-ui #account_status svg:hover { @@ -291,7 +292,7 @@ export function createUI() {
From ff34bcd5393b892e060e49e3bdc6afd839ea90f5 Mon Sep 17 00:00:00 2001 From: Colbster937 Date: Wed, 1 Apr 2026 20:56:08 -0500 Subject: [PATCH 07/12] feat: fix packet differences across versions --- src/proxy.ts | 59 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/src/proxy.ts b/src/proxy.ts index 2b8e1f2..4b27ca5 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -23,6 +23,11 @@ enum State { Play = 0x03, } +enum PacketType { + SERVERBOUND, + CLIENTBOUND +} + // EAG_ prefixed are nonstandard enum Serverbound { /* ==HANDSHAKING== */ @@ -38,9 +43,17 @@ enum Serverbound { LoginStart = 0x00, EncryptionResponse = 0x01, /* ==PLAY== */ + PluginMessage = -0x00, +} + +enum Serverbound_1_8 { PluginMessage = 0x17, } +enum Serverbound_1_12 { + PluginMessage = 0x09, +} + enum Clientbound { /* ==HANDSHAKING== */ EAG_ServerVersion = 0x02, @@ -57,9 +70,17 @@ enum Clientbound { SetCompression = 0x03, /* ==PLAY== */ SetCompressionPlay = 0x46, + PluginMessage = -0x00, +} + +enum Clientbound_1_8 { PluginMessage = 0x3f, } +enum Clientbound_1_12 { + PluginMessage = 0x18, +} + class Packet extends Buffer { constructor(packetType: number) { super(new Uint8Array()); @@ -131,6 +152,26 @@ function createProtocolArray(pvn: number): number[] { } } +function getVersionPluginMessage(protocol: number, type: PacketType): number { + if (type == PacketType.SERVERBOUND) { + if (protocol == 47) { + return Serverbound_1_8.PluginMessage; + } else if (protocol == 340) { + return Serverbound_1_12.PluginMessage; + } else { + return Serverbound.PluginMessage + } + } else { + if (protocol == 47) { + return Clientbound_1_8.PluginMessage; + } else if (protocol == 340) { + return Clientbound_1_12.PluginMessage; + } else { + return Clientbound.PluginMessage + } + } +} + export class EaglerProxy { loggedIn: boolean = false; handshook: boolean = false; @@ -236,7 +277,7 @@ export class EaglerProxy { case State.Play: let pk = packet.readVarInt(false)!; switch (pk) { - case Serverbound.PluginMessage: + case getVersionPluginMessage(this.protocol, PacketType.SERVERBOUND): let fard = packet.copy(); fard.readVarInt(); let tag = fard.readString(); @@ -248,7 +289,7 @@ export class EaglerProxy { if (buf.length == 0) { return; } - let resp = new Packet(Clientbound.PluginMessage); + let resp = new Packet(getVersionPluginMessage(this.protocol, PacketType.CLIENTBOUND)); resp.writeString(tag); resp.extend(buf); this.eagler.write(resp); @@ -407,12 +448,14 @@ export class EaglerProxy { case State.Play: switch (packet.readVarInt(false)) { case Clientbound.SetCompressionPlay: - packet.readVarInt(); - let threshold = packet.readVarInt(); - this.decompressor.compressionThresh = threshold; - this.compressor.compressionThresh = threshold; - break; - case Clientbound.PluginMessage: + if (this.protocol <= 47) { + packet.readVarInt(); + let threshold = packet.readVarInt(); + this.decompressor.compressionThresh = threshold; + this.compressor.compressionThresh = threshold; + break; + } + case getVersionPluginMessage(this.protocol, PacketType.CLIENTBOUND): let pk = packet.copy(); pk.readVarInt(); let tag = pk.readString(); From 2336ff6bed6f1a0ef87bb0b79083f8becca8cf52 Mon Sep 17 00:00:00 2001 From: Colbster937 Date: Mon, 27 Apr 2026 16:15:02 -0500 Subject: [PATCH 08/12] feat: make settings ui function accessible --- src/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/index.ts b/src/index.ts index 69913d0..b5f7977 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import { getProfile, minecraftAuth, UserInfo } from "./auth"; import { epoxyFetch, initWisp } from "./connection/epoxy"; import { makeFakeWebSocket } from "./connection/fakewebsocket"; +import { showUI } from "./ui"; //@ts-expect-error this gets filled in by rollup export const VERSION = self.VERSION; @@ -73,6 +74,11 @@ if (localStorage["wispcraft_accounts"]) { } } +Object.defineProperty(window, "wispcraftShowSettingsUI", { + value: showUI, + writable: false +}); + // replace websocket with our own window.WebSocket = makeFakeWebSocket(); From 836fe24721ee9af0cd0ac494212d3ce64553e613 Mon Sep 17 00:00:00 2001 From: Colbster937 Date: Mon, 27 Apr 2026 16:15:22 -0500 Subject: [PATCH 09/12] feat: rename stuff --- src/proxy.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/proxy.ts b/src/proxy.ts index 4b27ca5..da6bfb7 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -24,8 +24,8 @@ enum State { } enum PacketType { - SERVERBOUND, - CLIENTBOUND + Clientbound, + Serverbound } // EAG_ prefixed are nonstandard @@ -152,22 +152,22 @@ function createProtocolArray(pvn: number): number[] { } } -function getVersionPluginMessage(protocol: number, type: PacketType): number { - if (type == PacketType.SERVERBOUND) { +function getVersionPacketId(protocol: number, type: PacketType, packet: string): number { + if (type == PacketType.Serverbound) { if (protocol == 47) { - return Serverbound_1_8.PluginMessage; + return Serverbound_1_8[packet]; } else if (protocol == 340) { - return Serverbound_1_12.PluginMessage; + return Serverbound_1_12[packet]; } else { - return Serverbound.PluginMessage + return Serverbound[packet] } } else { if (protocol == 47) { - return Clientbound_1_8.PluginMessage; + return Clientbound_1_8[packet]; } else if (protocol == 340) { - return Clientbound_1_12.PluginMessage; + return Clientbound_1_12[packet]; } else { - return Clientbound.PluginMessage + return Clientbound[packet] } } } @@ -277,7 +277,7 @@ export class EaglerProxy { case State.Play: let pk = packet.readVarInt(false)!; switch (pk) { - case getVersionPluginMessage(this.protocol, PacketType.SERVERBOUND): + case getVersionPacketId(this.protocol, PacketType.Serverbound, "PluginMessage"): let fard = packet.copy(); fard.readVarInt(); let tag = fard.readString(); @@ -289,7 +289,7 @@ export class EaglerProxy { if (buf.length == 0) { return; } - let resp = new Packet(getVersionPluginMessage(this.protocol, PacketType.CLIENTBOUND)); + let resp = new Packet(getVersionPacketId(this.protocol, PacketType.Clientbound, "PluginMessage")); resp.writeString(tag); resp.extend(buf); this.eagler.write(resp); @@ -448,14 +448,14 @@ export class EaglerProxy { case State.Play: switch (packet.readVarInt(false)) { case Clientbound.SetCompressionPlay: - if (this.protocol <= 47) { + if (this.protocol == 47) { packet.readVarInt(); let threshold = packet.readVarInt(); this.decompressor.compressionThresh = threshold; this.compressor.compressionThresh = threshold; break; } - case getVersionPluginMessage(this.protocol, PacketType.CLIENTBOUND): + case getVersionPacketId(this.protocol, PacketType.Clientbound, "PluginMessage"): let pk = packet.copy(); pk.readVarInt(); let tag = pk.readString(); From b8d94d85e091412beba01281d7732eb61d0dc190 Mon Sep 17 00:00:00 2001 From: Colbster937 Date: Thu, 30 Apr 2026 10:02:01 -0500 Subject: [PATCH 10/12] feat: make show ui function on object --- src/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index b5f7977..e22c75c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -74,8 +74,10 @@ if (localStorage["wispcraft_accounts"]) { } } -Object.defineProperty(window, "wispcraftShowSettingsUI", { - value: showUI, +Object.defineProperty(window, "wispcraftAPI", { + value: { + showSettingsUI: showUI + }, writable: false }); From f67e791f8576f4056d3eb5521489df51c56f48b9 Mon Sep 17 00:00:00 2001 From: Colbster937 Date: Thu, 30 Apr 2026 12:33:37 -0500 Subject: [PATCH 11/12] feat: export account functions --- src/index.ts | 34 +++++++++++++++++++++------------- src/ui.ts | 27 +++++++++++---------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/index.ts b/src/index.ts index e22c75c..5710ae8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -52,14 +52,27 @@ try { console.error(e); } +export function getLoggedInAccounts (): TokenStore[] | undefined { + const accounts = localStorage["wispcraft_accounts"]; + if (accounts) { + return JSON.parse(accounts) as TokenStore[]; + } else { + return undefined; + } +} + +export function getLastUsedAccount (): TokenStore | undefined { + const username = localStorage["wispcraft_last_used_account"]; + const accounts = getLoggedInAccounts(); + if (username && accounts) { + return accounts.find((account) => account.username === username); + } else { + return undefined; + } +} + if (localStorage["wispcraft_accounts"]) { - const accounts = JSON.parse( - localStorage["wispcraft_accounts"] - ) as TokenStore[]; - const account = accounts.find( - (account) => - account.username === localStorage["wispcraft_last_used_account"] - ); + const account = getLastUsedAccount(); if (account) { (async () => { try { @@ -74,12 +87,7 @@ if (localStorage["wispcraft_accounts"]) { } } -Object.defineProperty(window, "wispcraftAPI", { - value: { - showSettingsUI: showUI - }, - writable: false -}); +export const showSettingsUI = showUI; // replace websocket with our own window.WebSocket = makeFakeWebSocket(); diff --git a/src/ui.ts b/src/ui.ts index d88781d..8ddb465 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -1,6 +1,6 @@ import { deviceCodeAuth, getProfile, minecraftAuth } from "./auth"; import { reconnect, set_wisp_server } from "./connection/epoxy"; -import { authstore, DEFAULT_WISP_URL, TokenStore, wispUrl } from "."; +import { authstore, DEFAULT_WISP_URL, getLastUsedAccount, getLoggedInAccounts, TokenStore, wispUrl } from "."; import encodeQR from "qr"; // @ts-ignore import workshop from "./img/workshop.png"; @@ -387,15 +387,15 @@ export function createUI() { } if (localStorage["wispcraft_accounts"]) { - const accounts = JSON.parse( - localStorage["wispcraft_accounts"] - ) as TokenStore[]; - for (const account of accounts) { - const option = document.createElement("option"); - option.value = account.username; - option.innerText = account.username; - accountSelect.add(option); - } + const accounts = getLoggedInAccounts(); + if (accounts) { + for (const account of accounts) { + const option = document.createElement("option"); + option.value = account.username; + option.innerText = account.username; + accountSelect.add(option); + } + } } if (localStorage["wispcraft_last_used_account"]) { @@ -467,12 +467,7 @@ export function createUI() { removeButton.disabled = true; return; } - const accounts = JSON.parse( - localStorage["wispcraft_accounts"] - ) as TokenStore[]; - const account = accounts.find( - (account) => account.username === accountSelect.value - ); + const account = getLastUsedAccount(); if (account) { try { try { From f0c9ab026b947e757d60c98c2362d8ed19e9a193 Mon Sep 17 00:00:00 2001 From: Colbster937 Date: Thu, 30 Apr 2026 13:28:06 -0500 Subject: [PATCH 12/12] feat: add auth function --- src/auth.ts | 33 +++++++++++++++++++++++++-------- src/index.ts | 3 ++- src/ui.ts | 19 +++++++------------ 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index b372f1e..311f192 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,3 +1,4 @@ +import encodeQR from "qr"; import { epoxyFetch } from "./connection/epoxy"; // https://gist.github.com/Plagiatus/ce5f18bc010395fc45d8553905e10f55 @@ -29,6 +30,30 @@ interface OAuthResponse { refresh_token: string; } +interface DeviceCodeResponse { + device_code: string; + user_code: string; + verification_uri: string; + expires_in: number; + interval: number; +} + +type AuthCodeResponse = DeviceCodeResponse & { + link_url: string; + qr_svg: string; + qr_svg_uri: string; +}; + +export async function getAuthCodeResponse () { + const codeGenerator = await deviceCodeAuth(); + const linkUrl = "https://microsoft.com/link?otc=" + codeGenerator.code; + const qrSvg = encodeQR(linkUrl, "svg", { + scale: 6, + border: 1, + }); + return { ...codeGenerator, link_url: linkUrl, qr_svg: qrSvg, qr_svg_uri: `data:image/svg+xml;base64,${btoa(qrSvg)}` } +} + export async function deviceCodeAuth() { // TOOD: Type const deviceCodeRes = await epoxyFetch( @@ -45,14 +70,6 @@ export async function deviceCodeAuth() { } ); - interface DeviceCodeResponse { - device_code: string; - user_code: string; - verification_uri: string; - expires_in: number; - interval: number; - } - const deviceCodeData: DeviceCodeResponse = await deviceCodeRes.json(); const { device_code, user_code, verification_uri, interval } = deviceCodeData; diff --git a/src/index.ts b/src/index.ts index 5710ae8..3bb6343 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { getProfile, minecraftAuth, UserInfo } from "./auth"; +import { getAuthCodeResponse, getProfile, minecraftAuth, UserInfo } from "./auth"; import { epoxyFetch, initWisp } from "./connection/epoxy"; import { makeFakeWebSocket } from "./connection/fakewebsocket"; import { showUI } from "./ui"; @@ -88,6 +88,7 @@ if (localStorage["wispcraft_accounts"]) { } export const showSettingsUI = showUI; +export const getAuthCode = getAuthCodeResponse; // replace websocket with our own window.WebSocket = makeFakeWebSocket(); diff --git a/src/ui.ts b/src/ui.ts index 8ddb465..3688350 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -1,4 +1,4 @@ -import { deviceCodeAuth, getProfile, minecraftAuth } from "./auth"; +import { deviceCodeAuth, getAuthCodeResponse, getProfile, minecraftAuth } from "./auth"; import { reconnect, set_wisp_server } from "./connection/epoxy"; import { authstore, DEFAULT_WISP_URL, getLastUsedAccount, getLoggedInAccounts, TokenStore, wispUrl } from "."; import encodeQR from "qr"; @@ -519,13 +519,8 @@ export function createUI() { addButton.onclick = async () => { try { addButton.disabled = true; - const codeGenerator = await deviceCodeAuth(); - const linkUrl = "https://microsoft.com/link?otc=" + codeGenerator.code; - const qrSvg = encodeQR(linkUrl, "svg", { - scale: 6, - border: 1, - }); - accountStatus.innerHTML = `Scan QR Code or click this link and use code for logging in.

${qrSvg}
`; + const res = await getAuthCodeResponse(); + accountStatus.innerHTML = `Scan QR Code or click this link and use code for logging in.

${res.qr_svg}
`; const authCodeBox = document.querySelector( "#auth_code" ) as HTMLInputElement; @@ -537,14 +532,14 @@ export function createUI() { accountStatus.querySelector("#mslink")!.onclick = async () => { - const auth = window.open(linkUrl, "", "height=500,width=350"); - await codeGenerator.token; + const auth = window.open(res.link_url, "", "height=500,width=350"); + await res.token; auth?.close(); }; - await codeGenerator.token; + await res.token; accountStatus.innerHTML = "Authenticating..."; - const token = await codeGenerator.token; + const token = await res.token; authstore.msToken = token; authstore.yggToken = await minecraftAuth(authstore.msToken); authstore.user = await getProfile(authstore.yggToken);