const express = require("express") const router = express.Router() const { requireAuth } = require("../../middleware/authmiddlewaregame") const crypto = require("crypto") const fs = require("fs") const key = fs.readFileSync("PrivateKey2020.txt") const { getPort, checkPort, getRandomPort, waitForPort, } = require("get-port-please") const RCC_HOST = process.env.RCC_HOST var sanitize = require("mongo-sanitize") const games = require("./../../model/games.js") const signatures = require("./../signatures.js") const rcc = require("../../model/rcc2020.js") const rcctalk = require("../../rcctalk2018") const User = require("../../model/user.js") const bodyParser = require("body-parser") router.use(bodyParser.json()) function sleep(ms) { return new Promise(resolve => { setTimeout(resolve, ms) }) } const _2020placelauncher = async (req, res, next) => { var enabled = req.config if (enabled.GamesEnabled === false) { return res.json({ status: "error", error: "Games are disabled bad boy", }) } if ( req.headers?.["user-agent"]?.includes("Android") === true || req.headers?.["user-agent"]?.includes("iPhone") === true ) { console.log(req.headers) console.log(req.userdocument.username) } if (req.method === "POST") { // mobile join-game req.query.name = req.body.placeId } var joinJson = { ClientPort: 0, MachineAddress: "localhost", ServerPort: 25564, PingUrl: "", PingInterval: 120, UserName: "default", SeleniumTestMode: false, UserId: 0, SuperSafeChat: false, CharacterAppearance: "http://shitncumblox.gq/game/charapp?name=default", ClientTicket: "", GameId: 1, PlaceId: 1818, MeasurementUrl: "", WaitingForCharacterGuid: "cad99b30-7983-434b-b24c-eac12595e5fd", BaseUrl: "http://www.mete0r.xyz/", ChatStyle: "ClassicAndBubble", VendorId: 0, ScreenShotInfo: "", VideoInfo: 'GamesROBLOX, video, free game, online virtual world', CreatorId: 0, CreatorTypeEnum: "User", MembershipType: "None", AccountAge: 365, CookieStoreFirstTimePlayKey: "rbx_evt_ftp", CookieStoreFiveMinutePlayKey: "rbx_evt_fmp", CookieStoreEnabled: true, IsRobloxPlace: false, GenerateTeleportJoin: false, IsUnknownOrUnder13: false, SessionId: "c25fd620-bbaa-4fb2-b022-3f053cdd1abd|00000000-0000-0000-0000-000000000000|0|204.236.226.210|8|2016-08-17T01:05:05.7115837Z|0|null|null|null|null", DataCenterId: 0, UniverseId: 0, BrowserTrackerId: 0, UsePortraitMode: false, FollowUserId: 0, CharacterAppearanceId: 1, } if (!req.query.name && !req.query.placeId && !req.query.placeid) { return res.json({ status: "error", error: "no placeid bad" }) } if (req.userdocument.gamejoin2020) { return res.json({ jobId: "Test", status: 2, joinScriptUrl: "http://mete0r.xyz/game/join.ashx?ver=2020&auth=" + req.query.auth ?? req.cookies.jwt, authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx", authenticationTicket: "SomeTicketThatDosentCrash", message: "", }) } var sanitizedplaceid = sanitize( req.query.name ?? req.query.placeId ?? req.query.placeid, ) const game = await games.findOne({ idofgame: sanitizedplaceid }).lean() if (!game) { return res.json({ status: "error", error: "that game doesn't exist!" }) } if (game.version != "2020") { return next() } let instance = await rcc.findOne({ PlaceId: sanitizedplaceid }).lean() if (instance && instance.Status === 2) { // if an rcc instance already exists we don't need to create a new one so we will just drag them into the existing game joinJson.UserName = req.userdocument.username joinJson.UserId = req.userdocument.userid joinJson.CharacterAppearance = "http://mete0r.xyz/v1.1/avatar-fetch?userId=" + req.userdocument.userid joinJson.MachineAddress = RCC_HOST // need to put rcc host here lol joinJson.ServerPort = instance.Port joinJson.PlaceId = instance.PlaceId joinJson.GameId = sanitizedplaceid joinJson.CharacterAppearanceId = req.userdocument.userid joinJson.MembershipType = req.userdocument.membership joinJson.CreatorId = game.useridofowner joinJson.SessionId = req.query.auth ?? req.cookies.jwt const timestamp = Date.now() joinJson.ClientTicket = timestamp + ";" // timestamp //create signature 1 const sign1 = crypto.createSign("SHA1") sign1.update( `${req.userdocument.userid}\n` /*userid*/ + `${req.userdocument.username}\n` /*username*/ + `${"0"}\n` /*userid 2 that 0k wants for some reason what a retard*/ + `game${sanitizedplaceid}\n` /*jobid*/ + timestamp /*timestamp*/, ) var signature1 = sign1.sign(key, "base64") joinJson.ClientTicket += signature1 + ";" //create signature 2 const sign2 = crypto.createSign("SHA1") sign2.update( `${req.userdocument.userid}\n` /*userid*/ + `game${sanitizedplaceid}\n` /*jobid*/ + timestamp /*timestamp*/, ) var signature2 = sign2.sign(key, "base64") joinJson.ClientTicket += signature2 + ";4" if (req.method === "POST" && req.body.isTeleport) { // mobile join-game const mobileJoin = { ClientPort: 0, MachineAddress: RCC_HOST, ServerPort: instance.Port, ServerConnections: [ { Address: RCC_HOST, Port: instance.Port, }, ], DirectServerReturn: true, TokenGenAlgorithm: 0, PepperId: 0, TokenValue: "vg", PingUrl: "", PingInterval: 0, UserName: req.userdocument.username, SeleniumTestMode: false, UserId: req.userdocument.userid, RobloxLocale: "", GameLocale: "", SuperSafeChat: false, CharacterAppearance: "http://mete0r.xyz/v1.1/avatar-fetch?userId=" + req.userdocument.userid, ClientTicket: joinJson.ClientTicket, GameId: "" + sanitizedplaceid, PlaceId: sanitizedplaceid, BaseUrl: "http://www.mete0r.xyz/", ChatStyle: "ClassicAndBubble", CreatorId: game.useridofowner, CreatorTypeEnum: "User", MembershipType: req.userdocument.membership, AccountAge: 365, CookieStoreFirstTimePlayKey: "rbx_evt_ftp", CookieStoreFiveMinutePlayKey: "rbx_evt_fmp", CookieStoreEnabled: false, IsUnknownOrUnder13: false, GameChatType: "AllUsers", SessionId: req.query.auth ?? req.cookies.jwt, AnalyticsSessionId: "", DataCenterId: 0, UniverseId: sanitizedplaceid, FollowUserId: 0, characterAppearanceId: req.userdocument.userid, CountryCode: "US", AlternateName: "", RandomSeed1: "57575745353", ClientPublicKeyData: "", } console.log(mobileJoin) return res.json({ jobId: "Test", status: 2, joinScriptUrl: `http://mete0r.xyz/game/join.ashx?ver=2020&auth=${ req.query.auth ?? req.cookies.jwt }`, authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx", authenticationTicket: "SomeTicketThatDosentCrash", message: "", joinScript: mobileJoin, }) } req.userdocument.gamejoin2020 = JSON.stringify(joinJson) req.userdocument.markModified("gamejoin2020") await req.userdocument.save() var joinScriptJson = { jobId: "Test", status: 2, joinScriptUrl: "http://mete0r.xyz/game/join.ashx?ver=2020&auth=" + joinJson.SessionId, authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx", authenticationTicket: "SomeTicketThatDosentCrash", message: "", } return res.send(JSON.stringify(joinScriptJson)) } if (instance && instance.Status === 1) { var joinScriptJson = { jobId: "Test", status: 1, joinScriptUrl: "http://mete0r.xyz/game/join.ashx?ver=2020&auth=" + joinJson.SessionId, authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx", authenticationTicket: "SomeTicketThatDosentCrash", message: "", } if (req.method === "POST" && req.body.isTeleport) { // mobile join-game return res.json({ jobId: "Test", status: 0, joinScriptUrl: "http://mete0r.xyz/game/join.ashx?ver=2020&auth=" + req.query.auth ?? req.cookies.jwt, authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx", authenticationTicket: "SomeTicketThatDosentCrash", message: "", }) } return res.send(JSON.stringify(joinScriptJson)) } var port = 53640 + Math.floor(Math.random() * 100) // launch job rcctalk.OpenGame2020( "game" + sanitizedplaceid, port, RCC_HOST, sanitizedplaceid, game.useridofowner, ) //console.dir(response,{ depth: null }) await rcc.create({ PlaceId: sanitizedplaceid, Port: port, Status: 1, // 1 means loading }) //console.log(newrenderscript) var joinScriptJson = { jobId: "Test", status: 1, joinScriptUrl: "http://mete0r.xyz/game/join.ashx?ver=2020&auth=" + joinJson.SessionId, authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx", authenticationTicket: "SomeTicketThatDosentCrash", message: "", } if (req.method === "POST" && req.body.isTeleport) { // mobile join-game return res.json({ jobId: "Test", status: 0, joinScriptUrl: "http://mete0r.xyz/game/join.ashx?ver=2020&auth=" + req.query.auth ?? req.cookies.jwt, authenticationUrl: "http://mete0r.xyz/Login/Negotiate.ashx", authenticationTicket: "SomeTicketThatDosentCrash", message: "", }) } return res.send(JSON.stringify(joinScriptJson)) } router.all( ["/MTwentyTwenty.ashx", "/2020/join", "/join-game"], requireAuth, _2020placelauncher, async (req, res) => { return res.json({ status: "error", error: "Version different than client requested.", }) }, ) //rcctalk.CloseJob('game2') module.exports = { router: router, _2020placelauncher: _2020placelauncher }