diff --git a/.deepsource.toml b/.deepsource.toml index 10cb0c60..137ec8de 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -1,9 +1,7 @@ version = 1 exclude_patterns = [ - "Mod Manager/src/torchlight/**", - "src/quickentity1136.js", - "src/quickentity20.js" + "Mod Manager/src/torchlight/**" ] [[analyzers]] diff --git a/.eslintrc.json b/.eslintrc.json index 757c2803..86c1a0d8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -34,6 +34,7 @@ "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-floating-promises": "error", - "@typescript-eslint/no-misused-promises": "error" + "@typescript-eslint/no-misused-promises": "error", + "no-fallthrough": "off" } } \ No newline at end of file diff --git a/.github/workflows/artifact.yml b/.github/workflows/artifact.yml index 9e055506..dd34ee86 100644 --- a/.github/workflows/artifact.yml +++ b/.github/workflows/artifact.yml @@ -16,6 +16,12 @@ jobs: with: node-version: 18 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: x86_64-pc-windows-msvc + default: true + - name: Cache id: cache uses: actions/cache@v2.1.6 @@ -37,7 +43,16 @@ jobs: - name: Prep run: | - npm install -g pkg typescript + npm install -g pkg typescript @napi-rs/cli + + - name: Build Rust code + run: | + cd rust + yarn + yarn build + cd ../ + copy ./rust/index.d.ts ./src/smf-rust.d.ts + copy ./rust/rust.win32-x64-msvc.node ./src/smf-rust.node - name: Build EXE env: diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 6a0400c1..d9054992 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -16,6 +16,12 @@ jobs: with: node-version: 18 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: x86_64-pc-windows-msvc + default: true + - name: Cache id: cache uses: actions/cache@v2.1.6 @@ -37,7 +43,16 @@ jobs: - name: Prep run: | - npm install -g pkg typescript + npm install -g pkg typescript @napi-rs/cli + + - name: Build Rust code + run: | + cd rust + yarn + yarn build + cd ../ + copy ./rust/index.d.ts ./src/smf-rust.d.ts + copy ./rust/rust.win32-x64-msvc.node ./src/smf-rust.node - name: Build EXE env: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f7a57294..601c44de 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,6 +19,12 @@ jobs: with: node-version: 18 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: x86_64-pc-windows-msvc + default: true + - name: Cache id: cache uses: actions/cache@v3 @@ -40,7 +46,16 @@ jobs: - name: Prep run: | - npm install -g pkg typescript + npm install -g pkg typescript @napi-rs/cli + + - name: Build Rust code + run: | + cd rust + yarn + yarn build + cd ../ + copy ./rust/index.d.ts ./src/smf-rust.d.ts + copy ./rust/rust.win32-x64-msvc.node ./src/smf-rust.node - name: Build EXE env: @@ -160,4 +175,4 @@ jobs: with: environment: production version: ${{ github.ref }} - sourcemaps: './compiled/core-singleton.js.map ./compiled/core.js.map ./compiled/crc32.js.map ./compiled/deploy.js.map ./compiled/difference.js.map ./compiled/discover.js.map ./compiled/main.js.map ./compiled/patchWorker.js.map ./compiled/quickentity-3.js.map ./compiled/quickentity-rs.js.map ./compiled/quickentity.js.map ./compiled/quickentity20.js.map ./compiled/quickentity1136.js.map ./compiled/rpkg.js.map ./compiled/three-onlymath.min.js.map ./compiled/types.js.map ./compiled/typescript.js.map ./compiled/utils.js.map' + sourcemaps: './compiled/core-singleton.js.map ./compiled/core.js.map ./compiled/crc32.js.map ./compiled/deploy.js.map ./compiled/difference.js.map ./compiled/discover.js.map ./compiled/main.js.map ./compiled/patchWorker.js.map ./compiled/quickentity-rs.js.map ./compiled/rpkg.js.map ./compiled/types.js.map ./compiled/typescript.js.map ./compiled/utils.js.map' diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..55e0000e --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,21 @@ +name: Close inactive issues +on: + schedule: + - cron: "30 1 * * *" + +jobs: + close-issues: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v4.1.1 + with: + days-before-issue-stale: 5 + days-before-issue-close: 5 + stale-issue-label: "stale" + stale-issue-message: "This issue has been marked as stale because it has been open for 5 days with no further activity." + close-issue-message: "This issue was closed because it was inactive for 5 days since being marked as stale." + days-before-pr-stale: -1 + days-before-pr-close: -1 diff --git a/.gitignore b/.gitignore index 21903bd4..666f5220 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,10 @@ Third-Party/ResourceTool.exe Third-Party/ResourceTool.pdb compiled /Mods -config.json \ No newline at end of file +config.json +rust/npm/win32-x64-msvc/package.json +rust/npm/win32-x64-msvc/README.md +rust/index.d.ts +rust/index.js +src/smf-rust.node +src/smf-rust.d.ts diff --git a/Mod Manager/src/electron.cjs b/Mod Manager/src/electron.cjs index 3d36192b..67b9d0a7 100644 --- a/Mod Manager/src/electron.cjs +++ b/Mod Manager/src/electron.cjs @@ -130,18 +130,18 @@ ipcMain.on("deploy", () => { cwd: ".." }) - let deployOutput = "" + let deployOutput = Buffer.from("") mainWindow.webContents.send("frameworkDeployModalOpen") deployProcess.stdout.on("data", (data) => { - deployOutput += String(data) - mainWindow.webContents.send("frameworkDeployOutput", deployOutput) + deployOutput = Buffer.concat([deployOutput, data]) + mainWindow.webContents.send("frameworkDeployOutput", String(deployOutput)) }) deployProcess.stderr.on("data", (data) => { - deployOutput += String(data) - mainWindow.webContents.send("frameworkDeployOutput", deployOutput) + deployOutput = Buffer.concat([deployOutput, data]) + mainWindow.webContents.send("frameworkDeployOutput", String(deployOutput)) }) deployProcess.on("close", (data) => { diff --git a/Mod Manager/src/lib/entity-patch-schema.json b/Mod Manager/src/lib/entity-patch-schema.json index 60d497ad..3982132d 100644 --- a/Mod Manager/src/lib/entity-patch-schema.json +++ b/Mod Manager/src/lib/entity-patch-schema.json @@ -496,7 +496,9 @@ "$ref": "#/definitions/FullRef" }, { - "type": "string" + "type": "string", + "minLength":16, + "maxLength":16 }, { "type": "null" diff --git a/Mod Manager/src/lib/repository-schema.json b/Mod Manager/src/lib/repository-schema.json index b35ea645..30219e69 100644 --- a/Mod Manager/src/lib/repository-schema.json +++ b/Mod Manager/src/lib/repository-schema.json @@ -409,10 +409,8 @@ "BurstAngleVMultiplier": { "type": "number" }, "BurstRandomizationFactorMultiplier": { "type": "number" }, "Items": { "type": "array", "items": { "type": "string" } }, - "Guids": { "type": "array", "items": { "type": "string" } }, - "_popdensitycomment": { "type": "string" } - }, - "title": "Unlockable" + "Guids": { "type": "array", "items": { "type": "string" } } + } }, "Configuration": { "type": "object", diff --git a/Mod Manager/src/lib/utils.ts b/Mod Manager/src/lib/utils.ts index 51f1e11e..c4a8ee54 100644 --- a/Mod Manager/src/lib/utils.ts +++ b/Mod Manager/src/lib/utils.ts @@ -462,12 +462,10 @@ export function validateModFolder(modFolder: string): [boolean, string] { switch (file.split(".").slice(1).join(".")) { case "entity.json": - if (fileContents.quickEntityVersion === 3.1 && !validateEntity(fileContents)) - return [false, `Invalid file ${file} due to non-matching schema: ${new Ajv({ strict: false }).errorsText(validateEntity.errors)}`] + if (!validateEntity(fileContents)) return [false, `Invalid file ${file} due to non-matching schema: ${new Ajv({ strict: false }).errorsText(validateEntity.errors)}`] break case "entity.patch.json": - if (fileContents.patchVersion === 6 && !validateEntityPatch(fileContents)) - return [false, `Invalid file ${file} due to non-matching schema: ${new Ajv({ strict: false }).errorsText(validateEntityPatch.errors)}`] + if (!validateEntityPatch(fileContents)) return [false, `Invalid file ${file} due to non-matching schema: ${new Ajv({ strict: false }).errorsText(validateEntityPatch.errors)}`] break case "repository.json": if (!validateRepository(fileContents)) return [false, `Invalid file ${file} due to non-matching schema: ${new Ajv({ strict: false }).errorsText(validateRepository.errors)}`] diff --git a/Mod Manager/src/routes/index.svelte b/Mod Manager/src/routes/index.svelte index c4c65143..f0b713b9 100644 --- a/Mod Manager/src/routes/index.svelte +++ b/Mod Manager/src/routes/index.svelte @@ -94,7 +94,8 @@ if ( window.fs - .readdirSync(window.path.join("..", "Mods")).filter(a=>a!="Managed by SMF, do not touch") + .readdirSync(window.path.join("..", "Mods")) + .filter((a) => a != "Managed by SMF, do not touch") .map((a) => window.path.resolve(window.path.join("..", "Mods", a))) .some((a) => window.isFile(a)) ) { @@ -107,7 +108,8 @@ } catch { invalidModText = window.fs - .readdirSync(window.path.join("..", "Mods")).filter(a=>a!="Managed by SMF, do not touch") + .readdirSync(window.path.join("..", "Mods")) + .filter((a) => a != "Managed by SMF, do not touch") .map((a) => window.path.resolve(window.path.join("..", "Mods", a))) .find((a) => window.fs.existsSync(window.path.join(a, "manifest.json")) && !json5.parse(window.fs.readFileSync(window.path.join(a, "manifest.json"), "utf8")).id) ?.split(window.path.sep) @@ -404,12 +406,24 @@ throw new Error("Mod update ZIP has files in the root!") } - window.fs.removeSync(getModFolder(updatingMod!.id)) + if ( + window.fs + .readdirSync("./staging") + .some( + (a) => + json5.parse(window.fs.readFileSync(window.path.join("./staging", a, "manifest.json"), "utf8")).scripts || + json5.parse(window.fs.readFileSync(window.path.join("./staging", a, "manifest.json"), "utf8")).options?.some((b) => b.scripts) + ) + ) { + updatingModScriptsWarningOpen = true + } else { + window.fs.removeSync(getModFolder(updatingMod!.id)) - window.fs.copySync("./staging", "../Mods") + window.fs.copySync("./staging", "../Mods") - window.fs.removeSync("./staging") - window.fs.removeSync("./tempArchive") + window.fs.removeSync("./staging") + window.fs.removeSync("./tempArchive") + } } catch (e) { window.alert("Couldn't extract and apply the mod update! Contact the mod author for help.\n\n" + e) updatingMod = null @@ -421,6 +435,8 @@ window.location.reload() } + let updatingModScriptsWarningOpen = false + const trustedHosts = new Set(["github.com", "raw.githubusercontent.com", "dropbox.com", "dl.dropboxusercontent.com", "drive.google.com", "hitman-resources.netlify.app"]) @@ -456,9 +472,8 @@ {#if semver.lt(FrameworkVersion, release.tag_name)}
{FrameworkVersion} → {release.tag_name}
The author of {getManifestFromModID(modID).name} may be able to find which IPs have their mod downloaded
+ The mod you're updating has added scripts; that means it is able to execute its own (external to the framework) code whenever you apply your mods. Scripts can do cool things and make a lot of + mods possible, but it's possible for them to cause problems, or even install malware (though the framework tries its best to avoid this). Make sure you trust whoever developed this mod, and + wherever you downloaded it from. Are you sure you want to add this mod? +
+