const Net = require('net'); const listenPort = 25565; const mcHost = "localhost"; const mcPort = 25569; const httpPort = 8080; const timeout = 10000; const changeProtocol = true; const removeSkin = true; const { WebSocketServer, WebSocket } = require('ws'); const fs = require("fs"); const path = require("path"); const mime = require("mime-types"); const bufferReplace = require('buffer-replace'); const prefix = "www"; let files = []; let cache = {}; function throughDirectory(directory) { fs.readdirSync(directory).forEach(file => { const absolute = path.join(directory, file); if (fs.statSync(absolute).isDirectory()) return throughDirectory(absolute); else return files.push(absolute.toString().slice(prefix.length+1).replace(/\\/g,"/")); }); } throughDirectory(prefix); const httpsrv = require("http").createServer((req,res)=>{ let url = req.url; if(url.startsWith("/"))url=url.slice(1); if(url=="")url = "index.html"; if(files.includes(url)){ res.writeHead(200,{"Content-Type":mime.contentType(url)}); if(!(url in cache)){ cache[url]=fs.readFileSync(prefix+"/"+url); } res.end(cache[url]); }else{ res.writeHead(404,{"Content-Type":"text/plain"}); res.end("404 Not Found"); } }); const wss = new WebSocketServer({ server: httpsrv }); wss.on('connection', function(ws) { let client = null; makeWsMcClient(ws,c=>client=c); let msgNum = 0; ws.on('message', function(data) { if(msgNum==0){ msgNum++; if(changeProtocol)data=bufferReplace(data,Buffer.from("0245","hex"),Buffer.from("023d","hex")); }else if(msgNum==1){ msgNum++; if(removeSkin)return;//eaglercraft skin } writeData(data); }); ws.on('close', function(){ closeIt(); }); async function writeData(chunk){ if(await waitForIt())client.write(chunk); } async function closeIt(){ if(await waitForIt())client.end(); } async function waitForIt(){ let i=Date.now(); while(client==null&&(Date.now()-isetTimeout(a,10)); } if(client==null){ if(ws.readyState==WebSocket.OPEN)ws.close(); return false; } return true; } }); httpsrv.listen(httpPort); const server = new Net.Server(); server.listen(listenPort, function() { // }); server.on('connection', function(socket) { let client = null; let determinedClient = false; socket.on('data', function(chunk) { if(!determinedClient){ let req = chunk.toString(); if(req.startsWith("GET ")||req.startsWith("HEAD ")||req.startsWith("POST ")||req.startsWith("PUT ")||req.startsWith("DELETE ")||req.startsWith("CONNECT ")||req.startsWith("OPTIONS ")||req.startsWith("TRACE ")||req.startsWith("PATCH ")){ makeClient("localhost",httpPort,socket,c=>client=c); }else{ makeClient(mcHost,mcPort,socket,c=>client=c); } determinedClient=true; } writeData(chunk); }); socket.on('end', function() { if(client!=null)client.end(); }); socket.on('error', function(err) { //console.log(`Server Error: ${err}`); }); async function writeData(chunk){ if(await waitForIt())client.write(chunk); } async function closeIt(){ if(await waitForIt())client.end(); } async function waitForIt(){ let i=Date.now(); while(client==null&&(Date.now()-isetTimeout(a,10)); } if(client==null){ socket.end(); return false; } return true; } }); function makeClient(host,port,socket,cb){ const client = new Net.Socket(); client.connect({ port: port, host: host }, function() { cb(client); }); client.on('end', function() { socket.end(); }); client.on('data', function(chunk) { socket.write(chunk); }); client.on('error', function(err) { //console.log(`Client Error: ${err}`); }); } function makeWsMcClient(ws,cb){ const client = new Net.Socket(); client.connect({ port: mcPort, host: mcHost }, function() { cb(client); }); client.on('end', function() { if(ws.readyState==WebSocket.OPEN)ws.close(); }); client.on('data', function(chunk) { if(ws.readyState==WebSocket.OPEN)ws.send(chunk); }); client.on('error', function(err) { //console.log(`Client Error: ${err}`); }); }