Compare commits
4 Commits
cec45e3425
...
29e6c4f507
| Author | SHA1 | Date |
|---|---|---|
|
|
29e6c4f507 | |
|
|
1607255948 | |
|
|
dff5a9ad57 | |
|
|
bd67b39745 |
3
build.js
3
build.js
|
|
@ -74,6 +74,9 @@ async function patchGameCode() {
|
||||||
code: `this.a = Math.floor(0.066 * b.c);
|
code: `this.a = Math.floor(0.066 * b.c);
|
||||||
d = b.d - 4 * uiSizes.gap - this.a;`,
|
d = b.d - 4 * uiSizes.gap - this.a;`,
|
||||||
addToDictionary: ["uiSizes", "gap"]
|
addToDictionary: ["uiSizes", "gap"]
|
||||||
|
}, {
|
||||||
|
code: `var dt=MenuManager.getState();if(dt===6){if(d===4211){/*...*/}}`,
|
||||||
|
addToDictionary: ["MenuManager", "getState"]
|
||||||
}];
|
}];
|
||||||
codeSegments.forEach(({ code, addToDictionary }) => {
|
codeSegments.forEach(({ code, addToDictionary }) => {
|
||||||
modUtils.matchCode(code, { addToDictionary })
|
modUtils.matchCode(code, { addToDictionary })
|
||||||
|
|
|
||||||
|
|
@ -214,4 +214,6 @@ export function definePatch(callback) {
|
||||||
* Helper for `modifyCode`
|
* Helper for `modifyCode`
|
||||||
* @param {string} code
|
* @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"
|
||||||
|
);
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
import ModUtils from '../modUtils.js';
|
import ModUtils, { insert } from '../modUtils.js';
|
||||||
|
|
||||||
// Custom lobby patches
|
// Custom lobby patches
|
||||||
export default (/** @type {ModUtils} */ { insertCode, replaceCode, replaceRawCode, safeDictionary: dict, waitForMinification }) => {
|
export default (/** @type {ModUtils} */ { modifyCode, insertCode, replaceCode, replaceRawCode, safeDictionary: dict, waitForMinification }) => {
|
||||||
|
|
||||||
// temporarily disabled for new versions
|
|
||||||
return;
|
|
||||||
|
|
||||||
// set player id correctly
|
// set player id correctly
|
||||||
insertCode(`function aBG(aBE) {
|
insertCode(`function aBG(aBE) {
|
||||||
|
|
@ -28,9 +25,24 @@ export default (/** @type {ModUtils} */ { insertCode, replaceCode, replaceRawCod
|
||||||
return __fx.customLobby.setActive(false);
|
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(() => {
|
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):",
|
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)||")
|
"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
|
// 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)}",
|
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)}),
|
`(__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)})`)
|
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
|
// do not display lobby UI
|
||||||
replaceRawCode(`(sV.style.backdropFilter="blur(4px)",sV.style.webkitBackdropFilter="blur(4px)"),`,
|
replaceRawCode(`(sV.style.backdropFilter="blur(4px)",sV.style.webkitBackdropFilter="blur(4px)"),`,
|
||||||
`(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,",
|
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.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,`)
|
this.maxPlayers=this.gLobbyMaxJoin,this.gBots=this.gLobbyMaxJoin-this.gHumans,this.sg=0,`)
|
||||||
*/
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +1,26 @@
|
||||||
import { definePatch } from "../modUtils.js"
|
import { definePatch, insert } from "../modUtils.js"
|
||||||
|
import { styleText } from "node:util";
|
||||||
|
|
||||||
export default definePatch(({ insertCode }) => {
|
export default definePatch(({ insertCode, modifyCode }) => {
|
||||||
|
|
||||||
// Hide propaganda popup
|
// Hide propaganda popup
|
||||||
insertCode(`/* here */
|
insertCode(`/* here */
|
||||||
a = b.c + 60 * 1000;
|
a = b.c + 60 * 1000;
|
||||||
(new ea()).show(eS.eb, eS.colors, eS.id);
|
(new ea()).show(eS.eb, eS.colors, eS.id);
|
||||||
eS = null;
|
eS = null;
|
||||||
return true;`, `if (__fx.settings.hidePropagandaPopup) return;`)
|
return true;`, `if (__fx.settings.hidePropagandaPopup || __fx.customLobby.isActive()) return;`)
|
||||||
|
modifyCode(`if (!a.b.c(0)) {
|
||||||
|
d = e.f + 1000 * 1;
|
||||||
|
return;
|
||||||
|
} ${insert(`if (!__fx.settings.hidePropagandaPopup && !__fx.customLobby.isActive())`)} a.g.h(5);`)
|
||||||
|
|
||||||
|
// for the custom lobby version
|
||||||
|
try {
|
||||||
|
modifyCode(`new a("⚔️<br>" + __L(), function() {
|
||||||
|
${insert(`if (__fx.isCustomLobbyVersion) alert("This version is for use with custom lobbies only. For normal multiplayer, use the version at https://fxclient.github.io/FXclient/")
|
||||||
|
else`)} b(0);
|
||||||
|
}, ${insert(`__fx.isCustomLobbyVersion ? "rgba(50, 50, 50, 0.6)" : `)} c.d)`)
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(styleText("yellow", `Warning: failed to apply patches specific to the custom lobby version`))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import WindowManager from "./windowManager.js";
|
import WindowManager from "./windowManager.js";
|
||||||
|
|
||||||
const customLobbiesUnavailable = true;
|
const customLobbiesUnavailable = false;
|
||||||
// const socketURL = "ws://localhost:8080/";
|
// const socketURL = "ws://localhost:8080/";
|
||||||
const socketURL = "wss://fx.peshomir.workers.dev/";
|
const socketURL = "wss://fx-lobbies.peshomir.workers.dev/";
|
||||||
const customMessageMarker = 120;
|
const customMessageMarker = 120;
|
||||||
let isActive = false;
|
let isActive = false;
|
||||||
let currentCode = "";
|
let currentCode = "";
|
||||||
let joinLobby = () => { };
|
let joinLobby = () => { };
|
||||||
|
/** when `leaveLobby` is called, the modified code will also execute setActive(false) */
|
||||||
let leaveLobby = () => { };
|
let leaveLobby = () => { };
|
||||||
let sendRaw = (socketId, data) => { };
|
let sendRaw = (socketId, data) => { };
|
||||||
const textEncoder = new TextEncoder();
|
const textEncoder = new TextEncoder();
|
||||||
|
|
@ -33,6 +34,10 @@ const windowElement = WindowManager.create({
|
||||||
|
|
||||||
const header = document.createElement("h2");
|
const header = document.createElement("h2");
|
||||||
header.textContent = "Custom Lobby";
|
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");
|
const main = document.createElement("div");
|
||||||
main.className = "customlobby-main";
|
main.className = "customlobby-main";
|
||||||
|
|
@ -152,7 +157,7 @@ const copyLinkButton = createButton("Copy link", () => {
|
||||||
});
|
});
|
||||||
footer.append(startButton, leaveButton, copyLinkButton);
|
footer.append(startButton, leaveButton, copyLinkButton);
|
||||||
|
|
||||||
windowElement.append(header, main, footer);
|
windowElement.append(header, pingIndicator, main, footer);
|
||||||
|
|
||||||
/** @param {HTMLSelectElement} element */
|
/** @param {HTMLSelectElement} element */
|
||||||
function setSelectMenuOptions(options, element) {
|
function setSelectMenuOptions(options, element) {
|
||||||
|
|
@ -174,13 +179,13 @@ document.getElementById("lobbyCode").addEventListener("input", ({ target: input
|
||||||
currentCode = input.value.toLowerCase();
|
currentCode = input.value.toLowerCase();
|
||||||
input.value = "";
|
input.value = "";
|
||||||
WindowManager.closeWindow("lobbyJoinMenu");
|
WindowManager.closeWindow("lobbyJoinMenu");
|
||||||
isActive = true;
|
setActive(true)
|
||||||
joinLobby();
|
joinLobby();
|
||||||
});
|
});
|
||||||
document.getElementById("createLobbyButton").addEventListener("click", () => {
|
document.getElementById("createLobbyButton").addEventListener("click", () => {
|
||||||
currentCode = "";
|
currentCode = "";
|
||||||
WindowManager.closeWindow("lobbyJoinMenu");
|
WindowManager.closeWindow("lobbyJoinMenu");
|
||||||
isActive = true;
|
setActive(true)
|
||||||
joinLobby();
|
joinLobby();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -204,7 +209,12 @@ function isCustomMessage(raw) {
|
||||||
const subArray = new Uint8Array(raw.buffer, 1);
|
const subArray = new Uint8Array(raw.buffer, 1);
|
||||||
const message = JSON.parse(textDecoder.decode(subArray));
|
const message = JSON.parse(textDecoder.decode(subArray));
|
||||||
const { t: type, d: data } = message;
|
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");
|
WindowManager.openWindow("customLobby");
|
||||||
header.textContent = "Custom Lobby " + data.code;
|
header.textContent = "Custom Lobby " + data.code;
|
||||||
currentCode = data.code;
|
currentCode = data.code;
|
||||||
|
|
@ -293,7 +303,9 @@ function updatePlayerCount() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSocketURL() {
|
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() {
|
function getPlayerId() {
|
||||||
let id = 0;
|
let id = 0;
|
||||||
|
|
@ -317,7 +329,7 @@ function checkForLobbyLink(isHashChangeEvent) {
|
||||||
// in case the player is already in a lobby
|
// in case the player is already in a lobby
|
||||||
if (isHashChangeEvent) leaveLobby();
|
if (isHashChangeEvent) leaveLobby();
|
||||||
currentCode = hash.slice(7);
|
currentCode = hash.slice(7);
|
||||||
isActive = true;
|
setActive(true)
|
||||||
joinLobby();
|
joinLobby();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -329,9 +341,16 @@ function setJoinFunction(f) {
|
||||||
}
|
}
|
||||||
function setLeaveFunction(f) { leaveLobby = f; }
|
function setLeaveFunction(f) { leaveLobby = f; }
|
||||||
function setSendFunction(f) { sendRaw = f; }
|
function setSendFunction(f) { sendRaw = f; }
|
||||||
|
function sendPing() {
|
||||||
|
sendMessage("ping", performance.now())
|
||||||
|
}
|
||||||
|
let pingInterval;
|
||||||
function setActive(active) {
|
function setActive(active) {
|
||||||
isActive = 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() {
|
function hideWindow() {
|
||||||
WindowManager.closeWindow("customLobby");
|
WindowManager.closeWindow("customLobby");
|
||||||
|
|
|
||||||
13
src/main.js
13
src/main.js
|
|
@ -14,15 +14,16 @@ import customLobby from './customLobby.js';
|
||||||
import { displayChangelog } from './changelog.js';
|
import { displayChangelog } from './changelog.js';
|
||||||
import { reportError } from './debugging.js';
|
import { reportError } from './debugging.js';
|
||||||
|
|
||||||
const savedVersion = localStorage.getItem("fx_version");
|
|
||||||
if (savedVersion !== version) {
|
|
||||||
localStorage.setItem("fx_version", version);
|
|
||||||
if (savedVersion !== null) displayChangelog();
|
|
||||||
}
|
|
||||||
|
|
||||||
window.__fx = window.__fx || {};
|
window.__fx = window.__fx || {};
|
||||||
const __fx = window.__fx;
|
const __fx = window.__fx;
|
||||||
__fx.version = version + " " + lastUpdated;
|
__fx.version = version + " " + lastUpdated;
|
||||||
|
__fx.isCustomLobbyVersion = window.location.href.startsWith("https://fxclient.github.io/custom-lobbies")
|
||||||
|
|
||||||
|
const savedVersion = localStorage.getItem("fx_version");
|
||||||
|
if (savedVersion !== version && !__fx.isCustomLobbyVersion) {
|
||||||
|
localStorage.setItem("fx_version", version);
|
||||||
|
if (savedVersion !== null) displayChangelog();
|
||||||
|
}
|
||||||
|
|
||||||
__fx.settingsManager = settingsManager;
|
__fx.settingsManager = settingsManager;
|
||||||
__fx.leaderboardFilter = leaderboardFilter;
|
__fx.leaderboardFilter = leaderboardFilter;
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,20 @@
|
||||||
<div class="window flex-column" id="customLobbyJoinMenu" style="display: none">
|
<div class="window flex-column" id="customLobbyJoinMenu" style="display: none">
|
||||||
<input type="text" id="lobbyCode" placeholder="Enter lobby code">
|
<input type="text" id="lobbyCode" placeholder="Enter lobby code">
|
||||||
or
|
or
|
||||||
|
<div>
|
||||||
<button id="createLobbyButton">Create new lobby</button>
|
<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>
|
||||||
<div class="window scrollable selectable" id="playerlist" style="display: none;">
|
<div class="window scrollable selectable" id="playerlist" style="display: none;">
|
||||||
<h1>Player List</h1>
|
<h1>Player List</h1>
|
||||||
|
|
|
||||||
10
version.json
10
version.json
|
|
@ -1,7 +1,11 @@
|
||||||
{
|
{
|
||||||
"version": "0.6.17",
|
"version": "0.6.18",
|
||||||
"lastUpdated": "Dec 4",
|
"lastUpdated": "Dec 30",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Fixes for game update v2.14.4"
|
"Updated custom lobbies to the latest version",
|
||||||
|
"When creating a custom lobby, you can now select a region where it will be created",
|
||||||
|
"The latency to the custom lobby server is displayed below the header in the custom lobby UI",
|
||||||
|
"Improved the propaganda blocking feature",
|
||||||
|
"Added automatic patches for the special custom lobby version (https://fxclient.github.io/custom-lobbies) which continues to serve its purpose of guaranteeing access to custom lobbies while allowing the regular version to quickly be updated to the latest Territorial.io version, neglecting the custom lobby patches if needed"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue