1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-12-13 18:21:51 +00:00

Start to make mods safer

This commit is contained in:
tobspr 2022-01-15 10:49:58 +01:00
parent e12ed11c3e
commit a0071681e7
14 changed files with 42 additions and 64 deletions

View File

@ -54,8 +54,11 @@ function createWindow() {
// fullscreen: true,
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true,
nodeIntegration: false,
webSecurity: false,
// sandbox: true,
contextIsolation: true,
preload: path.join(__dirname, "preload.js"),
},
allowRunningInsecureContent: false,
});

3
electron/preload.js Normal file
View File

@ -0,0 +1,3 @@
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("ipcRenderer", ipcRenderer);

View File

@ -19,7 +19,8 @@
"publishStandalone": "yarn publishOnItch && yarn publishOnSteam",
"publishWeb": "cd gulp && yarn main.deploy.prod",
"publish": "yarn publishStandalone && yarn publishWeb",
"syncTranslations": "node sync-translations.js"
"syncTranslations": "node sync-translations.js",
"buildTypes": "tsc src/js/application.js --declaration --allowJs --emitDeclarationOnly --skipLibCheck --out types.js"
},
"dependencies": {
"@babel/core": "^7.5.4",

View File

@ -1,7 +1,6 @@
import { BaseItem } from "../game/base_item";
import { ClickDetector } from "./click_detector";
import { Signal } from "./signal";
import { getIPCRenderer } from "./utils";
/*
* ***************************************************
@ -113,9 +112,7 @@ export class FormElementInput extends FormElement {
if (G_WEGAME_VERSION) {
const value = String(this.element.value);
getIPCRenderer()
.invoke("profanity-check", value)
.then(newValue => {
ipcRenderer.invoke("profanity-check", value).then(newValue => {
if (value !== newValue && this.element) {
this.element.value = newValue;
}

View File

@ -42,21 +42,6 @@ export function getPlatformName() {
return "unknown";
}
/**
* Returns the IPC renderer, or null if not within the standalone
* @returns {object|null}
*/
let ipcRenderer = null;
export function getIPCRenderer() {
if (!G_IS_STANDALONE) {
return null;
}
if (!ipcRenderer) {
ipcRenderer = eval("require")("electron").ipcRenderer;
}
return ipcRenderer;
}
/**
* Makes a new 2D array with undefined contents
* @param {number} w

View File

@ -602,7 +602,7 @@ export class RegularGameMode extends GameMode {
/** @type {(typeof MetaBuilding)[]} */
this.hiddenBuildings = [MetaConstantProducerBuilding, MetaGoalAcceptorBuilding, MetaBlockBuilding];
// @ts-expect-error
// @ts-ignore
if (!(G_IS_DEV || window.sandboxMode || queryParamOptions.sandboxMode)) {
this.hiddenBuildings.push(MetaItemProducerBuilding);
}

2
src/js/globals.d.ts vendored
View File

@ -24,6 +24,8 @@ declare const G_WEGAME_VERSION: boolean;
declare const shapez: any;
declare const ipcRenderer: any;
// Polyfills
declare interface String {
replaceAll(search: string, replacement: string): string;

View File

@ -1,10 +1,8 @@
/* typehints:start */
import { Application } from "../application";
/* typehints:end */
import { globalConfig } from "../core/config";
import { createLogger } from "../core/logging";
import { getIPCRenderer } from "../core/utils";
import { Mod } from "./mod";
import { ModInterface } from "./mod_interface";
import { MOD_SIGNALS } from "./mod_signals";
@ -76,12 +74,17 @@ export class ModLoader {
this.exposeExports();
window.registerMod = mod => {
this.modLoadQueue.push(mod);
};
if (G_IS_STANDALONE || G_IS_DEV) {
try {
let mods = [];
if (G_IS_STANDALONE) {
mods = await getIPCRenderer().invoke("get-mods");
} else if (G_IS_DEV && globalConfig.debug.externalModUrl) {
mods = await ipcRenderer.invoke("get-mods");
}
if (G_IS_DEV && globalConfig.debug.externalModUrl) {
const mod = await (
await fetch(globalConfig.debug.externalModUrl, {
method: "GET",
@ -91,12 +94,8 @@ export class ModLoader {
}
mods.forEach(modCode => {
window.registerMod = mod => {
this.modLoadQueue.push(mod);
};
// ugh
eval(modCode);
delete window.registerMod;
const func = new Function(modCode);
func();
});
} catch (ex) {
alert("Failed to load mods: " + ex);
@ -111,6 +110,8 @@ export class ModLoader {
});
this.modLoadQueue = [];
this.signals.postInit.dispatch();
delete window.registerMod;
}
}

View File

@ -3,7 +3,6 @@ import { Application } from "../application";
/* typehints:end */
import { createLogger } from "../core/logging";
import { compressX64 } from "../core/lzstring";
import { getIPCRenderer } from "../core/utils";
import { T } from "../translations";
const logger = createLogger("puzzle-api");
@ -113,9 +112,7 @@ export class ClientAPI {
return Promise.resolve({ token });
}
const renderer = getIPCRenderer();
return renderer.invoke("steam:get-ticket").then(
return ipcRenderer.invoke("steam:get-ticket").then(
ticket => {
logger.log("Got auth ticket:", ticket);
return this._request("/v1/public/login", {

View File

@ -4,7 +4,6 @@ import { GameRoot } from "../../game/root";
/* typehints:end */
import { createLogger } from "../../core/logging";
import { getIPCRenderer } from "../../core/utils";
import { ACHIEVEMENTS, AchievementCollection, AchievementProviderInterface } from "../achievement_provider";
const logger = createLogger("achievements/steam");
@ -109,9 +108,7 @@ export class SteamAchievementProvider extends AchievementProviderInterface {
return Promise.resolve();
}
this.ipc = getIPCRenderer();
return this.ipc.invoke("steam:is-initialized").then(initialized => {
return ipcRenderer.invoke("steam:is-initialized").then(initialized => {
this.initialized = initialized;
if (!this.initialized) {
@ -136,7 +133,7 @@ export class SteamAchievementProvider extends AchievementProviderInterface {
if (!this.initialized) {
promise = Promise.resolve();
} else {
promise = this.ipc.invoke("steam:activate-achievement", ACHIEVEMENT_IDS[key]);
promise = ipcRenderer.invoke("steam:activate-achievement", ACHIEVEMENT_IDS[key]);
}
return promise

View File

@ -1,5 +1,4 @@
import { StorageInterface } from "../storage";
import { getIPCRenderer } from "../../core/utils";
import { createLogger } from "../../core/logging";
const logger = createLogger("electron-storage");
@ -12,7 +11,7 @@ export class StorageImplElectron extends StorageInterface {
this.jobs = {};
this.jobId = 0;
getIPCRenderer().on("fs-response", (event, arg) => {
ipcRenderer.on("fs-response", (event, arg) => {
const id = arg.id;
if (!this.jobs[id]) {
logger.warn("Got unhandled FS response, job not known:", id);
@ -37,7 +36,7 @@ export class StorageImplElectron extends StorageInterface {
const jobId = ++this.jobId;
this.jobs[jobId] = { resolve, reject };
getIPCRenderer().send("fs-job", {
ipcRenderer.send("fs-job", {
type: "write",
filename,
contents,
@ -52,7 +51,7 @@ export class StorageImplElectron extends StorageInterface {
const jobId = ++this.jobId;
this.jobs[jobId] = { resolve, reject };
getIPCRenderer().send("fs-job", {
ipcRenderer.send("fs-job", {
type: "read",
filename,
id: jobId,
@ -65,7 +64,7 @@ export class StorageImplElectron extends StorageInterface {
// ipcMain
const jobId = ++this.jobId;
this.jobs[jobId] = { resolve, reject };
getIPCRenderer().send("fs-job", {
ipcRenderer.send("fs-job", {
type: "delete",
filename,
id: jobId,

View File

@ -1,6 +1,5 @@
import { NoAchievementProvider } from "../browser/no_achievement_provider";
import { PlatformWrapperImplBrowser } from "../browser/wrapper";
import { getIPCRenderer } from "../../core/utils";
import { createLogger } from "../../core/logging";
import { StorageImplElectron } from "./storage";
import { SteamAchievementProvider } from "./steam_achievement_provider";
@ -71,15 +70,13 @@ export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser {
}
initializeDlcStatus() {
const renderer = getIPCRenderer();
if (G_WEGAME_VERSION) {
return Promise.resolve();
}
logger.log("Checking DLC ownership ...");
// @todo: Don't hardcode the app id
return renderer.invoke("steam:check-app-ownership", 1625400).then(
return ipcRenderer.invoke("steam:check-app-ownership", 1625400).then(
res => {
logger.log("Got DLC ownership:", res);
this.dlcs.puzzle = Boolean(res);
@ -106,7 +103,7 @@ export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser {
}
setFullscreen(flag) {
getIPCRenderer().send("set-fullscreen", flag);
ipcRenderer.send("set-fullscreen", flag);
}
getSupportsAppExit() {
@ -115,6 +112,6 @@ export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser {
exitApp() {
logger.log(this, "Sending app exit signal");
getIPCRenderer().send("exit-app");
ipcRenderer.send("exit-app");
}
}

View File

@ -405,12 +405,6 @@ export class MainMenuState extends GameState {
makeButton(outerDiv, ["newGameButton", "styledButton"], T.mainMenu.newGame),
this.onPlayButtonClicked
);
// Mods
this.trackClicks(
makeButton(outerDiv, ["modsButton", "styledButton"], " "),
this.onModsClicked
);
} else {
// New game
this.trackClicks(
@ -419,6 +413,9 @@ export class MainMenuState extends GameState {
);
}
// Mods
this.trackClicks(makeButton(outerDiv, ["modsButton", "styledButton"], " "), this.onModsClicked);
buttonContainer.appendChild(outerDiv);
}

View File

@ -1,6 +1,5 @@
import { THIRDPARTY_URLS } from "../core/config";
import { TextualGameState } from "../core/textual_game_state";
import { getIPCRenderer } from "../core/utils";
import { MODS } from "../mods/modloader";
import { T } from "../translations";
@ -117,7 +116,7 @@ export class ModsState extends TextualGameState {
this.dialogs.showWarning(T.global.error, T.mods.folderOnlyStandalone);
return;
}
getIPCRenderer().send("open-mods-folder");
ipcRenderer.send("open-mods-folder");
}
onSteamLinkClicked() {