Update custom lobbies

main
peshomir 2025-12-30 21:14:36 +02:00
parent cec45e3425
commit bd67b39745
5 changed files with 68 additions and 33 deletions

View File

@ -74,6 +74,9 @@ async function patchGameCode() {
code: `this.a = Math.floor(0.066 * b.c);
d = b.d - 4 * uiSizes.gap - this.a;`,
addToDictionary: ["uiSizes", "gap"]
}, {
code: `var dt=MenuManager.getState();if(dt===6){if(d===4211){/*...*/}}`,
addToDictionary: ["MenuManager", "getState"]
}];
codeSegments.forEach(({ code, addToDictionary }) => {
modUtils.matchCode(code, { addToDictionary })

View File

@ -214,4 +214,6 @@ export function definePatch(callback) {
* Helper for `modifyCode`
* @param {string} code
*/
export const insert = (code) => code.split(/\r?\n/g).map(l => "/*insert line:*/" + l).join("\n");
export const insert = (code) => (
"\n" + code.split(/\r?\n/g).map(l => "/*insert line:*/" + l).join("\n") + "\n"
);

View File

@ -1,10 +1,7 @@
import ModUtils from '../modUtils.js';
import ModUtils, { insert } from '../modUtils.js';
// Custom lobby patches
export default (/** @type {ModUtils} */ { insertCode, replaceCode, replaceRawCode, safeDictionary: dict, waitForMinification }) => {
// temporarily disabled for new versions
return;
export default (/** @type {ModUtils} */ { modifyCode, insertCode, replaceCode, replaceRawCode, safeDictionary: dict, waitForMinification }) => {
// set player id correctly
insertCode(`function aBG(aBE) {
@ -28,9 +25,24 @@ export default (/** @type {ModUtils} */ { insertCode, replaceCode, replaceRawCod
return __fx.customLobby.setActive(false);
}`)
insertCode(`this.send = function(a, b) {
if (a !== 0) {c(a);}
d[a].send(b);
}; /* here */`, "__fx.customLobby.setSendFunction(this.send)")
// when a socket error occurs on the custom lobby socket
insertCode(`this.b = function(id, t) { /* here */ this.a.push(t); if (i.h === 8 && id === 0) {if (t === 4211) {f(t);} else {/*...*/}}};`, `id===1 && __fx.customLobby.isActive() && MenuManager.getState() !== 6 && __fx.customLobby.setActive(false);`, { dictionary: {MenuManager: dict.MenuManager, getState: dict.getState} })
// when leaving a game
modifyCode(`${insert(`if (__fx.customLobby.isActive() === false)`)} a.b.c();
d.e();
this.f = 0;
g.h();
i.j.setState(0);
MenuManager.setState(0);
${insert(`if (!__fx.customLobby.isActive()) `)} k.l.m(n);
${insert(`if (__fx.customLobby.isActive()) __fx.customLobby.rejoinLobby();
else`)} if (this.o === 2) {/*...*/}`)
waitForMinification(() => {
replaceRawCode("this.send=function(socketId,data){aJE(socketId),aJ4[socketId].send(data)}",
"this.send=function(socketId,data){aJE(socketId),aJ4[socketId].send(data)},__fx.customLobby.setSendFunction(this.send)")
replaceRawCode("b7.dH(a0),0===b7.size?aq.kt.aJJ(wR,3205):",
"b7.dH(a0),0===b7.size?aq.kt.aJJ(wR,3205):__fx.customLobby.isCustomMessage(a0)||")
// set the custom lobby to inactive when clicking the "Back" button on the connection screen or leaving the lobby
@ -39,19 +51,6 @@ export default (/** @type {ModUtils} */ { insertCode, replaceCode, replaceRawCod
replaceRawCode("function(){n.r(),bl.zf(),Sockets.s.ze(3240),n.o(5,5)}",
`(__fx.customLobby.setLeaveFunction(() => {n.r(),bl.zf(),Sockets.s.ze(3240),__fx.customLobby.setActive(false),n.o(5,5)}),
function(){n.r(),bl.zf(),Sockets.s.ze(3240),__fx.customLobby.setActive(false),n.o(5,5)})`)
// when a socket error occurs on the custom lobby socket
// TODO: Fix these after main WebSocket fix is confirmed working
/*
replaceRawCode("this.wQ=function(wR,d){if(8===i.pz&&0===wR)if(4211===d)wS(d);",
`this.wQ=function(wR,d){
wR===1 && __fx.customLobby.isActive() && ${dict.MenuManager}.${dict.getState}() !== 6 && __fx.customLobby.setActive(false);
if(8===i.pz&&0===wR)if(4211===d)wS(d);`)
// when leaving a game
replaceRawCode("this.wl=function(zs){a1.gZ||az.oO.a11.length||(az.oO.a11=az.a12.vd()),ap.ky.zt(),this.vH=0,bU.zu(),m.n.setState(0),aN.setState(0),zs||bJ.df.show(),2===this.a3D?i.ky.a3U():1===this.a3D?i.j(19):i.j(5,5)}",
`this.wl=function(zs){a1.gZ||az.oO.a11.length||(az.oO.a11=az.a12.vd()),
__fx.customLobby.isActive() === false && ap.ky.zt(),
this.vH=0,bU.zu(),m.n.setState(0),aN.setState(0),zs||bJ.df.show();
if (__fx.customLobby.isActive()) __fx.customLobby.rejoinLobby(); else 2===this.a3D?i.ky.a3U():1===this.a3D?i.j(19):i.j(5,5)}`)
// do not display lobby UI
replaceRawCode(`(sV.style.backdropFilter="blur(4px)",sV.style.webkitBackdropFilter="blur(4px)"),`,
`(sV.style.backdropFilter="blur(4px)",sV.style.webkitBackdropFilter="blur(4px)"),
@ -80,6 +79,5 @@ export default (/** @type {ModUtils} */ { insertCode, replaceCode, replaceRawCod
replaceRawCode("1===a.b?this.gLobbyMaxJoin=this.gHumans:this.gLobbyMaxJoin=this.data.playerCount,this.maxPlayers=this.gLobbyMaxJoin,this.gBots=this.gLobbyMaxJoin-this.gHumans,this.sg=0,",
`this.gLobbyMaxJoin = __fx.customLobby.isActive() ? Math.max(Math.min(__fx.customLobby.gameInfo.botCount, this.data.playerCount), this.gHumans) : 1===a.b?this.gLobbyMaxJoin=this.gHumans:this.gLobbyMaxJoin=this.data.playerCount,
this.maxPlayers=this.gLobbyMaxJoin,this.gBots=this.gLobbyMaxJoin-this.gHumans,this.sg=0,`)
*/
});
}

View File

@ -1,12 +1,13 @@
import WindowManager from "./windowManager.js";
const customLobbiesUnavailable = true;
const customLobbiesUnavailable = false;
// const socketURL = "ws://localhost:8080/";
const socketURL = "wss://fx.peshomir.workers.dev/";
const socketURL = "wss://fx-lobbies.peshomir.workers.dev/";
const customMessageMarker = 120;
let isActive = false;
let currentCode = "";
let joinLobby = () => { };
/** when `leaveLobby` is called, the modified code will also execute setActive(false) */
let leaveLobby = () => { };
let sendRaw = (socketId, data) => { };
const textEncoder = new TextEncoder();
@ -33,6 +34,10 @@ const windowElement = WindowManager.create({
const header = document.createElement("h2");
header.textContent = "Custom Lobby";
header.style.marginBottom = "0px";
header.style.marginBlockStart = "0.5em";
const pingIndicator = document.createElement("p");
pingIndicator.style.marginTop = "0px";
const main = document.createElement("div");
main.className = "customlobby-main";
@ -152,7 +157,7 @@ const copyLinkButton = createButton("Copy link", () => {
});
footer.append(startButton, leaveButton, copyLinkButton);
windowElement.append(header, main, footer);
windowElement.append(header, pingIndicator, main, footer);
/** @param {HTMLSelectElement} element */
function setSelectMenuOptions(options, element) {
@ -174,13 +179,13 @@ document.getElementById("lobbyCode").addEventListener("input", ({ target: input
currentCode = input.value.toLowerCase();
input.value = "";
WindowManager.closeWindow("lobbyJoinMenu");
isActive = true;
setActive(true)
joinLobby();
});
document.getElementById("createLobbyButton").addEventListener("click", () => {
currentCode = "";
WindowManager.closeWindow("lobbyJoinMenu");
isActive = true;
setActive(true)
joinLobby();
});
@ -204,7 +209,12 @@ function isCustomMessage(raw) {
const subArray = new Uint8Array(raw.buffer, 1);
const message = JSON.parse(textDecoder.decode(subArray));
const { t: type, d: data } = message;
if (type === "lobby") {
if (type === "pong") {
const latency = performance.now() - data
pingIndicator.innerText = `Ping: ${latency} ms`
} else if (type === "lobby") {
pingIndicator.innerText = ""
sendPing()
WindowManager.openWindow("customLobby");
header.textContent = "Custom Lobby " + data.code;
currentCode = data.code;
@ -293,7 +303,9 @@ function updatePlayerCount() {
}
function getSocketURL() {
return socketURL + (currentCode === "" ? "create" : "join?" + currentCode)
if (currentCode !== "") return socketURL + "join?" + currentCode
const region = document.getElementById("customLobbyRegion").value
return socketURL + "create" + (region === "default" ? "" : `?location=${region}`)
}
function getPlayerId() {
let id = 0;
@ -317,7 +329,7 @@ function checkForLobbyLink(isHashChangeEvent) {
// in case the player is already in a lobby
if (isHashChangeEvent) leaveLobby();
currentCode = hash.slice(7);
isActive = true;
setActive(true)
joinLobby();
}
}
@ -329,9 +341,16 @@ function setJoinFunction(f) {
}
function setLeaveFunction(f) { leaveLobby = f; }
function setSendFunction(f) { sendRaw = f; }
function sendPing() {
sendMessage("ping", performance.now())
}
let pingInterval;
function setActive(active) {
isActive = active;
if (active === false) WindowManager.closeWindow("customLobby");
if (active === false) {
WindowManager.closeWindow("customLobby");
if (pingInterval !== undefined) clearInterval(pingInterval)
} else pingInterval = setInterval(sendPing, 10_000)
}
function hideWindow() {
WindowManager.closeWindow("customLobby");

View File

@ -112,7 +112,20 @@
<div class="window flex-column" id="customLobbyJoinMenu" style="display: none">
<input type="text" id="lobbyCode" placeholder="Enter lobby code">
or
<div>
<button id="createLobbyButton">Create new lobby</button>
<label for="region">in region:</label>
<select id="customLobbyRegion" name="region"
title="Note: Region selection is a best effort, not a guarantee. The regions listed are only a subset of all the possible locations where a lobby can be created.">
<option value="default" selected>Automatic (closest to you)</option>
<option value="wnam">Western North America</option>
<option value="enam">Eastern North America</option>
<option value="weur">Western Europe</option>
<option value="eeur">Eastern Europe</option>
<option value="apac">Asia-Pacific</option>
<option value="oc">Oceania</option>
</select>
</div>
</div>
<div class="window scrollable selectable" id="playerlist" style="display: none;">
<h1>Player List</h1>