├── .deepsource.toml
├── .eslintrc.json
├── .github
├── dependabot.yml
├── tag-changelog-config.js
└── workflows
│ ├── artifact.yml
│ ├── codeql-analysis.yml
│ ├── pr.yml
│ ├── pr_comment.yml
│ └── release.yml
├── .gitignore
├── .prettierrc
├── COPYING
├── COPYING.LESSER
├── For Build
├── Mods
│ ├── Managed by SMF, do not touch
│ └── Realistic AI
│ │ ├── content-extreme
│ │ └── chunk0
│ │ │ └── Realistic AI Extreme.repository.json
│ │ ├── content-manhunt
│ │ └── chunk0
│ │ │ └── Realistic AI Manhunt.repository.json
│ │ ├── content-normal
│ │ └── chunk0
│ │ │ └── Realistic AI Normal.repository.json
│ │ └── manifest.json
├── Third-Party
│ ├── ResourceLib_HM2.dll
│ ├── ResourceLib_HM2016.dll
│ ├── ResourceLib_HM3.dll
│ ├── ResourceLib_HMA.dll
│ ├── ResourceTool.exe
│ ├── assimp.dll
│ ├── hash_list.hmla
│ └── quickentity_ffi.dll
├── cleanMicrosoftThumbs.dat
├── cleanPackageDefinition.txt
├── cleanThumbs.dat
└── config.json
├── Mod Manager
├── .gitignore
├── .npmrc
├── .prettierrc
├── .vscode
│ ├── extensions.json
│ └── settings.json
├── build.config.json
├── buildResources
│ └── icon.ico
├── globals.d.ts
├── jsconfig.json
├── package-lock.json
├── package.json
├── postcss.config.cjs
├── src
│ ├── app.css
│ ├── app.html
│ ├── electron.cjs
│ ├── global.d.ts
│ ├── lib
│ │ ├── ExpandableTile.svelte
│ │ ├── KeyValueEditor.svelte
│ │ ├── ListEditor.svelte
│ │ ├── LocalisationEditor.svelte
│ │ ├── Mod.svelte
│ │ ├── ModManifestInterface.svelte
│ │ ├── SortableList.svelte
│ │ ├── TextInputModal.svelte
│ │ ├── contract-schema.json
│ │ ├── entity-patch-schema.json
│ │ ├── entity-schema.json
│ │ ├── json-patch-schema.json
│ │ ├── manifest-schema.json
│ │ ├── repository-schema.json
│ │ ├── unlockables-schema.json
│ │ └── utils.ts
│ ├── preload.cjs
│ └── routes
│ │ ├── +layout.svelte
│ │ ├── +page.svelte
│ │ ├── authoring
│ │ ├── +page.svelte
│ │ └── [mod]
│ │ │ ├── +page.svelte
│ │ │ ├── manifest
│ │ │ └── +page.svelte
│ │ │ └── options
│ │ │ └── [option]
│ │ │ └── +page.svelte
│ │ ├── docs
│ │ └── [page]
│ │ │ └── +page.svelte
│ │ ├── info
│ │ └── +page.svelte
│ │ ├── modList
│ │ └── +page.svelte
│ │ └── settings
│ │ └── +page.svelte
├── static
│ └── shiki
│ │ ├── languages
│ │ ├── abap.tmLanguage.json
│ │ ├── actionscript-3.tmLanguage.json
│ │ ├── ada.tmLanguage.json
│ │ ├── apache.tmLanguage.json
│ │ ├── apex.tmLanguage.json
│ │ ├── apl.tmLanguage.json
│ │ ├── applescript.tmLanguage.json
│ │ ├── asm.tmLanguage.json
│ │ ├── astro.tmLanguage.json
│ │ ├── awk.tmLanguage.json
│ │ ├── ballerina.tmLanguage.json
│ │ ├── bat.tmLanguage.json
│ │ ├── berry.tmLanguage.json
│ │ ├── bibtex.tmLanguage.json
│ │ ├── bicep.tmLanguage.json
│ │ ├── blade.tmLanguage.json
│ │ ├── c.tmLanguage.json
│ │ ├── cadence.tmLanguage.json
│ │ ├── clarity.tmLanguage.json
│ │ ├── clojure.tmLanguage.json
│ │ ├── cmake.tmLanguage.json
│ │ ├── cobol.tmLanguage.json
│ │ ├── codeql.tmLanguage.json
│ │ ├── coffee.tmLanguage.json
│ │ ├── cpp-macro.tmLanguage.json
│ │ ├── cpp.tmLanguage.json
│ │ ├── crystal.tmLanguage.json
│ │ ├── csharp.tmLanguage.json
│ │ ├── css.tmLanguage.json
│ │ ├── cue.tmLanguage.json
│ │ ├── d.tmLanguage.json
│ │ ├── dart.tmLanguage.json
│ │ ├── diff.tmLanguage.json
│ │ ├── docker.tmLanguage.json
│ │ ├── dream-maker.tmLanguage.json
│ │ ├── elixir.tmLanguage.json
│ │ ├── elm.tmLanguage.json
│ │ ├── erb.tmLanguage.json
│ │ ├── erlang.tmLanguage.json
│ │ ├── fish.tmLanguage.json
│ │ ├── fsharp.tmLanguage.json
│ │ ├── gherkin.tmLanguage.json
│ │ ├── git-commit.tmLanguage.json
│ │ ├── git-rebase.tmLanguage.json
│ │ ├── glsl.tmLanguage.json
│ │ ├── gnuplot.tmLanguage.json
│ │ ├── go.tmLanguage.json
│ │ ├── graphql.tmLanguage.json
│ │ ├── groovy.tmLanguage.json
│ │ ├── hack.tmLanguage.json
│ │ ├── haml.tmLanguage.json
│ │ ├── handlebars.tmLanguage.json
│ │ ├── haskell.tmLanguage.json
│ │ ├── hcl.tmLanguage.json
│ │ ├── hlsl.tmLanguage.json
│ │ ├── html.tmLanguage.json
│ │ ├── ini.tmLanguage.json
│ │ ├── java.tmLanguage.json
│ │ ├── javascript.tmLanguage.json
│ │ ├── jinja-html.tmLanguage.json
│ │ ├── jinja.tmLanguage.json
│ │ ├── json.tmLanguage.json
│ │ ├── jsonc.tmLanguage.json
│ │ ├── jsonnet.tmLanguage.json
│ │ ├── jssm.tmLanguage.json
│ │ ├── jsx.tmLanguage.json
│ │ ├── julia.tmLanguage.json
│ │ ├── kotlin.tmLanguage.json
│ │ ├── latex.tmLanguage.json
│ │ ├── less.tmLanguage.json
│ │ ├── liquid.tmLanguage.json
│ │ ├── lisp.tmLanguage.json
│ │ ├── logo.tmLanguage.json
│ │ ├── lua.tmLanguage.json
│ │ ├── make.tmLanguage.json
│ │ ├── markdown.tmLanguage.json
│ │ ├── marko.tmLanguage.json
│ │ ├── matlab.tmLanguage.json
│ │ ├── mdx.tmLanguage.json
│ │ ├── mermaid.tmLanguage.json
│ │ ├── nginx.tmLanguage.json
│ │ ├── nim.tmLanguage.json
│ │ ├── nix.tmLanguage.json
│ │ ├── objective-c.tmLanguage.json
│ │ ├── objective-cpp.tmLanguage.json
│ │ ├── ocaml.tmLanguage.json
│ │ ├── pascal.tmLanguage.json
│ │ ├── perl.tmLanguage.json
│ │ ├── php-html.tmLanguage.json
│ │ ├── php.tmLanguage.json
│ │ ├── plsql.tmLanguage.json
│ │ ├── postcss.tmLanguage.json
│ │ ├── powershell.tmLanguage.json
│ │ ├── prisma.tmLanguage.json
│ │ ├── prolog.tmLanguage.json
│ │ ├── pug.tmLanguage.json
│ │ ├── puppet.tmLanguage.json
│ │ ├── purescript.tmLanguage.json
│ │ ├── python.tmLanguage.json
│ │ ├── r.tmLanguage.json
│ │ ├── raku.tmLanguage.json
│ │ ├── razor.tmLanguage.json
│ │ ├── rel.tmLanguage.json
│ │ ├── riscv.tmLanguage.json
│ │ ├── rst.tmLanguage.json
│ │ ├── ruby.tmLanguage.json
│ │ ├── rust.tmLanguage.json
│ │ ├── sas.tmLanguage.json
│ │ ├── sass.tmLanguage.json
│ │ ├── scala.tmLanguage.json
│ │ ├── scheme.tmLanguage.json
│ │ ├── scss.tmLanguage.json
│ │ ├── shaderlab.tmLanguage.json
│ │ ├── shellscript.tmLanguage.json
│ │ ├── smalltalk.tmLanguage.json
│ │ ├── solidity.tmLanguage.json
│ │ ├── sparql.tmLanguage.json
│ │ ├── sql.tmLanguage.json
│ │ ├── ssh-config.tmLanguage.json
│ │ ├── stata.tmLanguage.json
│ │ ├── stylus.tmLanguage.json
│ │ ├── svelte.tmLanguage.json
│ │ ├── swift.tmLanguage.json
│ │ ├── system-verilog.tmLanguage.json
│ │ ├── tasl.tmLanguage.json
│ │ ├── tcl.tmLanguage.json
│ │ ├── tex.tmLanguage.json
│ │ ├── toml.tmLanguage.json
│ │ ├── tsx.tmLanguage.json
│ │ ├── turtle.tmLanguage.json
│ │ ├── twig.tmLanguage.json
│ │ ├── typescript.tmLanguage.json
│ │ ├── vb.tmLanguage.json
│ │ ├── verilog.tmLanguage.json
│ │ ├── vhdl.tmLanguage.json
│ │ ├── viml.tmLanguage.json
│ │ ├── vue-html.tmLanguage.json
│ │ ├── vue.tmLanguage.json
│ │ ├── wasm.tmLanguage.json
│ │ ├── wenyan.tmLanguage.json
│ │ ├── xml.tmLanguage.json
│ │ ├── xsl.tmLanguage.json
│ │ ├── yaml.tmLanguage.json
│ │ └── zenscript.tmLanguage.json
│ │ ├── samples
│ │ ├── Marko.sample
│ │ ├── abap.sample
│ │ ├── actionscript-3.sample
│ │ ├── ada.sample
│ │ ├── apex.sample
│ │ ├── applescript.sample
│ │ ├── asm.sample
│ │ ├── astro.sample
│ │ ├── awk.sample
│ │ ├── ballerina.sample
│ │ ├── bat.sample
│ │ ├── berry.sample
│ │ ├── bicep.sample
│ │ ├── blade.sample
│ │ ├── c.sample
│ │ ├── cadence.sample
│ │ ├── clarity.sample
│ │ ├── clojure.sample
│ │ ├── cmake.sample
│ │ ├── cobol.sample
│ │ ├── codeql.sample
│ │ ├── coffee.sample
│ │ ├── cpp.sample
│ │ ├── crystal.sample
│ │ ├── csharp.sample
│ │ ├── css.sample
│ │ ├── cue.sample
│ │ ├── d.sample
│ │ ├── dart.sample
│ │ ├── diff.sample
│ │ ├── dm.sample
│ │ ├── docker.sample
│ │ ├── elixir.sample
│ │ ├── elm.sample
│ │ ├── erb.sample
│ │ ├── erlang.sample
│ │ ├── fish.sample
│ │ ├── fsharp.sample
│ │ ├── fsl.sample
│ │ ├── glsl.sample
│ │ ├── go.sample
│ │ ├── html.sample
│ │ ├── java.sample
│ │ ├── javascript.sample
│ │ ├── jssm.sample
│ │ ├── liquid.sample
│ │ ├── prisma.sample
│ │ ├── python.sample
│ │ ├── rel.sample
│ │ ├── ruby.sample
│ │ ├── sparql.sample
│ │ ├── stata.sample
│ │ ├── tasl.sample
│ │ ├── tsx.sample
│ │ ├── turtle.sample
│ │ └── zenscript.sample
│ │ └── themes
│ │ ├── css-variables.json
│ │ ├── dark-plus.json
│ │ ├── dracula-soft.json
│ │ ├── dracula.json
│ │ ├── github-dark-dimmed.json
│ │ ├── github-dark.json
│ │ ├── github-light.json
│ │ ├── hc_light.json
│ │ ├── light-plus.json
│ │ ├── material-darker.json
│ │ ├── material-default.json
│ │ ├── material-lighter.json
│ │ ├── material-ocean.json
│ │ ├── material-palenight.json
│ │ ├── min-dark.json
│ │ ├── min-light.json
│ │ ├── monokai.json
│ │ ├── nord.json
│ │ ├── one-dark-pro.json
│ │ ├── poimandres.json
│ │ ├── rose-pine-dawn.json
│ │ ├── rose-pine-moon.json
│ │ ├── rose-pine.json
│ │ ├── slack-dark.json
│ │ ├── slack-ochin.json
│ │ ├── solarized-dark.json
│ │ ├── solarized-light.json
│ │ ├── vitesse-dark.json
│ │ └── vitesse-light.json
├── svelte.config.js
├── tailwind.config.cjs
├── tsconfig.json
└── vite.config.js
├── README.md
├── Third-Party
├── 7z-LICENSE
├── 7z.dll
├── 7z.exe
├── HMLanguageTools.exe
├── HMTextureTools.exe
├── OREStool.exe
├── TonyTools-LICENSE
├── baseGameEntities.txt
├── baseGameSoundbanks.txt
├── h6xtea.exe
├── quickentity-3.exe
├── quickentity-rs.exe
├── xdelta3-LICENSE
└── xdelta3.exe
├── cleanPackageDefinition.txt
├── cleanThumbs.dat
├── config.json
├── docs
├── Command Line Arguments.md
├── Config.md
├── Folder Structure.md
├── Index.md
├── Making a Mod.md
├── Manifest.md
├── Mod Manager.md
├── Mod Updates.md
├── RPKG Mods.md
├── Scripts.md
└── Special File Types.md
├── package-lock.json
├── package.json
├── piscina
├── .taprc
├── dist
│ ├── esm-wrapper.mjs
│ ├── package.json
│ └── src
│ │ ├── common.d.ts
│ │ ├── common.js
│ │ ├── common.js.map
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.js.map
│ │ ├── worker.d.ts
│ │ ├── worker.js
│ │ └── worker.js.map
└── package.json
├── rome.json
├── rust
├── .gitignore
├── .npmignore
├── .yarn
│ └── releases
│ │ └── yarn-3.6.0.cjs
├── .yarnrc.yml
├── Cargo.toml
├── build.rs
├── package.json
├── rustfmt.toml
├── src
│ └── lib.rs
└── yarn.lock
├── src
├── core-singleton.ts
├── core.ts
├── crc32.js
├── deploy.ts
├── difference.ts
├── discover.ts
├── main.ts
├── patchWorker.ts
├── quickentity-3.ts
├── quickentity-rs.ts
├── quickentity.js
├── quickentity1136.js
├── quickentity20.js
├── rpkg.ts
├── three-onlymath.min.js
├── types.ts
├── typescript.ts
└── utils.ts
└── tsconfig.json
/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | exclude_patterns = [
4 | "Mod Manager/src/torchlight/**",
5 | "src/quickentity1136.js",
6 | "src/quickentity20.js"
7 | ]
8 |
9 | [[analyzers]]
10 | name = "javascript"
11 | enabled = true
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es2021": true,
4 | "node": true
5 | },
6 | "extends": [
7 | "eslint:recommended",
8 | "plugin:@typescript-eslint/recommended"
9 | ],
10 | "parser": "@typescript-eslint/parser",
11 | "parserOptions": {
12 | "ecmaVersion": "latest",
13 | "sourceType": "module",
14 | "project": [
15 | "./tsconfig.json"
16 | ]
17 | },
18 | "plugins": [
19 | "@typescript-eslint"
20 | ],
21 | "rules": {
22 | "semi": [
23 | "error",
24 | "never"
25 | ],
26 | "comma-dangle": [
27 | "error",
28 | "never"
29 | ],
30 | "prefer-const": "error",
31 | "no-mixed-spaces-and-tabs": "off",
32 | "no-empty": "off",
33 | "no-empty-function": "off",
34 | "@typescript-eslint/no-empty-function": "off",
35 | "@typescript-eslint/no-non-null-assertion": "off",
36 | "@typescript-eslint/no-floating-promises": "error",
37 | "@typescript-eslint/no-misused-promises": "error"
38 | }
39 | }
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "daily"
12 | commit-message:
13 | prefix: "chore(depends):"
14 |
15 | - package-ecosystem: "npm" # See documentation for possible values
16 | directory: "/Mod Manager/" # Location of package manifests
17 | schedule:
18 | interval: "daily"
19 | commit-message:
20 | prefix: "chore(depends):"
21 |
--------------------------------------------------------------------------------
/.github/tag-changelog-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | types: [
3 | { types: ["feat", "feature"], label: "New Features" },
4 | { types: ["fix", "bugfix"], label: "Bug Fixes" },
5 | { types: ["improvements", "enhancement"], label: "Improvements" },
6 | { types: ["perf"], label: "Performance Improvements" },
7 | { types: ["build", "ci"], label: "Build System" },
8 | { types: ["refactor"], label: "Refactors" },
9 | { types: ["doc", "docs"], label: "Documentation Changes" },
10 | { types: ["test", "tests"], label: "Tests" },
11 | { types: ["style"], label: "Code Style Changes" },
12 | { types: ["chore"], label: "Chores" },
13 | { types: ["other"], label: "Other Changes" }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/.github/workflows/artifact.yml:
--------------------------------------------------------------------------------
1 | name: Create Artifact
2 |
3 | on:
4 | push
5 |
6 | jobs:
7 | build:
8 | runs-on: windows-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v4
12 | with:
13 | fetch-depth: 0
14 |
15 | - uses: actions/setup-node@v4
16 | with:
17 | node-version: 18
18 |
19 | - uses: actions-rs/toolchain@v1
20 | with:
21 | toolchain: stable
22 | target: x86_64-pc-windows-msvc
23 | default: true
24 |
25 | - name: Cache
26 | id: cache
27 | uses: actions/cache@v4
28 | with:
29 | path: node_modules
30 | key: buildCachev25
31 |
32 | - name: Cache
33 | id: cache2
34 | uses: actions/cache@v4
35 | with:
36 | path: Mod Manager/node_modules
37 | key: buildCache2v20
38 |
39 | - name: Install dependencies
40 | if: steps.cache.outputs.cache-hit != 'true'
41 | run: |
42 | npm install
43 |
44 | - name: Prep
45 | run: |
46 | npm install -g pkg typescript @napi-rs/cli
47 |
48 | - name: Build Rust code
49 | run: |
50 | cd rust
51 | yarn
52 | yarn build
53 | cd ../
54 | copy ./rust/index.d.ts ./src/smf-rust.d.ts
55 | copy ./rust/rust.win32-x64-msvc.node ./src/smf-rust.node
56 |
57 | - name: Build EXE
58 | env:
59 | NODE_OPTIONS: "--max-old-space-size=4096"
60 | run: |
61 | New-Item -ItemType Directory -Force -Path ./node_modules/piscina
62 | robocopy ./piscina ./node_modules/piscina /E /is /it; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
63 | tsc
64 | copy ./src/smf-rust.node ./compiled/smf-rust.node
65 | pkg package.json --targets node18-win-x64 --output Deploy.exe --compress Brotli
66 |
67 | - name: Install GUI dependencies
68 | if: steps.cache2.outputs.cache-hit != 'true'
69 | run: |
70 | cd "Mod Manager"
71 | npm install
72 | cd ../
73 |
74 | - name: Build GUI
75 | run: |
76 | cd "Mod Manager"
77 | npm run build
78 | cd ../
79 |
80 | - name: Ready for zip
81 | run: |
82 | New-Item -ItemType Directory dist
83 | New-Item -ItemType Directory dist/Third-Party
84 | New-Item -ItemType Directory dist/Info
85 | New-Item -ItemType Directory dist/API
86 | New-Item -ItemType Directory "dist/Mod Manager"
87 | robocopy ./Third-Party ./dist/Third-Party /E; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
88 | robocopy "./For Build" ./dist /E; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
89 | robocopy ./docs ./dist/Info /E; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
90 | robocopy ./compiled ./dist/API /E *.d.ts; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
91 | robocopy ".\Mod Manager\dist\win-unpacked" "./dist/Mod Manager" /E; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
92 | copy Deploy.exe dist
93 | New-Item -Path dist -Name "Mod Manager.cmd" -ItemType "file" -Value "@echo off`ncd `"Mod Manager`"`nstart `"`" `"Mod Manager.exe`""
94 |
95 | - name: Zip
96 | uses: TheDoctor0/zip-release@4fb9e4ff72847dd3d1c111cf63834e353ed7cb3d
97 | with:
98 | filename: Release.zip
99 | directory: dist
100 |
101 | - uses: actions/upload-artifact@v4
102 | with:
103 | name: Output
104 | path: dist/Release.zip
105 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '21 15 * * 4'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'javascript' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v3
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v2
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
52 |
53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54 | # If this step fails, then you should remove it and run the build manually (see below)
55 | - name: Autobuild
56 | uses: github/codeql-action/autobuild@v2
57 |
58 | # ℹ️ Command-line programs to run using the OS shell.
59 | # 📚 https://git.io/JvXDl
60 |
61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62 | # and modify them (or add more) to build your code if your project
63 | # uses a compiled language
64 |
65 | #- run: |
66 | # make bootstrap
67 | # make release
68 |
69 | - name: Perform CodeQL Analysis
70 | uses: github/codeql-action/analyze@v2
71 |
--------------------------------------------------------------------------------
/.github/workflows/pr.yml:
--------------------------------------------------------------------------------
1 | name: PR Build
2 |
3 | on:
4 | pull_request:
5 |
6 | jobs:
7 | build:
8 | runs-on: windows-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v4
12 | with:
13 | fetch-depth: 0
14 |
15 | - uses: actions/setup-node@v4
16 | with:
17 | node-version: 18
18 |
19 | - uses: actions-rs/toolchain@v1
20 | with:
21 | toolchain: stable
22 | target: x86_64-pc-windows-msvc
23 | default: true
24 |
25 | - name: Cache
26 | id: cache
27 | uses: actions/cache@v4
28 | with:
29 | path: node_modules
30 | key: buildCachev25
31 |
32 | - name: Cache
33 | id: cache2
34 | uses: actions/cache@v4
35 | with:
36 | path: Mod Manager/node_modules
37 | key: buildCache2v20
38 |
39 | - name: Install dependencies
40 | if: steps.cache.outputs.cache-hit != 'true'
41 | run: |
42 | npm install
43 |
44 | - name: Prep
45 | run: |
46 | npm install -g pkg typescript @napi-rs/cli
47 |
48 | - name: Build Rust code
49 | run: |
50 | cd rust
51 | yarn
52 | yarn build
53 | cd ../
54 | copy ./rust/index.d.ts ./src/smf-rust.d.ts
55 | copy ./rust/rust.win32-x64-msvc.node ./src/smf-rust.node
56 |
57 | - name: Build EXE
58 | env:
59 | NODE_OPTIONS: "--max-old-space-size=4096"
60 | run: |
61 | New-Item -ItemType Directory -Force -Path ./node_modules/piscina
62 | robocopy ./piscina ./node_modules/piscina /COPYALL /E /is /it; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
63 | tsc
64 | copy ./src/smf-rust.node ./compiled/smf-rust.node
65 | pkg package.json --targets node18-win-x64 --output Deploy.exe --compress Brotli
66 |
67 | - name: Download RPKG
68 | uses: aochmann/actions-download-artifact@5709392f11b5937bd316e52687ad87f7deced5f5
69 | with:
70 | repo: glacier-modding/RPKG-Tool
71 | name: rpkg-cli
72 | latest: true
73 | path: './Third-Party'
74 |
75 | - name: Download ResourceTool
76 | uses: aochmann/actions-download-artifact@5709392f11b5937bd316e52687ad87f7deced5f5
77 | with:
78 | repo: OrfeasZ/ZHMTools
79 | name: ResourceTool-win-x64
80 | latest: true
81 | path: './Third-Party'
82 |
83 | - name: Install GUI dependencies
84 | if: steps.cache2.outputs.cache-hit != 'true'
85 | run: |
86 | cd "Mod Manager"
87 | npm install
88 | cd ../
89 |
90 | - name: Build GUI
91 | run: |
92 | cd "Mod Manager"
93 | npm run build
94 | cd ../
95 |
96 | - name: Ready for zip
97 | run: |
98 | New-Item -ItemType Directory dist
99 | New-Item -ItemType Directory dist/Third-Party
100 | New-Item -ItemType Directory dist/Info
101 | New-Item -ItemType Directory dist/API
102 | New-Item -ItemType Directory "dist/Mod Manager"
103 | robocopy ./Third-Party ./dist/Third-Party /COPYALL /E; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
104 | robocopy "./For Build" ./dist /COPYALL /E; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
105 | robocopy ./docs ./dist/Info /COPYALL /E; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
106 | robocopy ./compiled ./dist/API /COPYALL /E *.d.ts; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
107 | robocopy ".\Mod Manager\dist\win-unpacked" "./dist/Mod Manager" /COPYALL /E; if ($lastexitcode -lt 8) { $global:LASTEXITCODE = $null }
108 | copy Deploy.exe dist
109 | New-Item -Path dist -Name "Mod Manager.cmd" -ItemType "file" -Value "@echo off`ncd `"Mod Manager`"`nstart `"`" `"Mod Manager.exe`""
110 |
111 | - uses: actions/upload-artifact@v4
112 | with:
113 | name: Output
114 | path: dist
115 |
--------------------------------------------------------------------------------
/.github/workflows/pr_comment.yml:
--------------------------------------------------------------------------------
1 | name: Comment on pull request
2 | on:
3 | workflow_run:
4 | workflows: ['PR Build']
5 | types: [completed]
6 | jobs:
7 | pr_comment:
8 | if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/github-script@v3
12 | with:
13 | # This snippet is public-domain, taken from
14 | # https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml
15 | script: |
16 | const {owner, repo} = context.repo;
17 | const run_id = ${{github.event.workflow_run.id}};
18 | const pull_head_sha = '${{github.event.workflow_run.head_sha}}';
19 | const pull_user_id = ${{github.event.sender.id}};
20 | const issue_number = await (async () => {
21 | const pulls = await github.pulls.list({owner, repo});
22 | for await (const {data} of github.paginate.iterator(pulls)) {
23 | for (const pull of data) {
24 | if (pull.head.sha === pull_head_sha && pull.user.id === pull_user_id) {
25 | return pull.number;
26 | }
27 | }
28 | }
29 | })();
30 | if (issue_number) {
31 | core.info(`Using pull request ${issue_number}`);
32 | } else {
33 | return core.error(`No matching pull request found`);
34 | }
35 | const {data: {artifacts}} = await github.actions.listWorkflowRunArtifacts({owner, repo, run_id});
36 | if (!artifacts.length) {
37 | return core.error(`No artifacts found`);
38 | }
39 | let body = `Download the artifacts for this pull request:\n`;
40 | for (const art of artifacts) {
41 | body += `\n* [${art.name}.zip](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip?h=6ea9fd5ddf66c9e4adbcbe858e65b9de8ce44998)`;
42 | }
43 | const {data: comments} = await github.issues.listComments({repo, owner, issue_number});
44 | const existing_comment = comments.find((c) => c.user.login === 'github-actions[bot]');
45 | if (existing_comment) {
46 | core.info(`Updating comment ${existing_comment.id}`);
47 | await github.issues.updateComment({repo, owner, comment_id: existing_comment.id, body});
48 | } else {
49 | core.info(`Creating a comment`);
50 | await github.issues.createComment({repo, owner, issue_number, body});
51 | }
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | hash_list.txt
3 | rpkg-cli.exe
4 | Deploy.exe
5 | Third-Party/ResourceLib_HM2.dll
6 | Third-Party/ResourceLib_HM2.pdb
7 | Third-Party/ResourceLib_HM2016.dll
8 | Third-Party/ResourceLib_HM2016.pdb
9 | Third-Party/ResourceLib_HM3.dll
10 | Third-Party/ResourceLib_HM3.pdb
11 | Third-Party/ResourceTool.exe
12 | Third-Party/ResourceTool.pdb
13 | compiled
14 | /Mods
15 | config.json
16 | rust/npm/win32-x64-msvc/package.json
17 | rust/npm/win32-x64-msvc/README.md
18 | rust/index.d.ts
19 | rust/index.js
20 | src/smf-rust.node
21 | src/smf-rust.d.ts
22 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "htmlWhitespaceSensitivity": "ignore",
3 | "trailingComma": "none",
4 | "requirePragma": false,
5 | "bracketSpacing": true,
6 | "singleQuote": false,
7 | "printWidth": 200,
8 | "useTabs": true,
9 | "tabWidth": 4,
10 | "semi": false
11 | }
--------------------------------------------------------------------------------
/For Build/Mods/Managed by SMF, do not touch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Mods/Managed by SMF, do not touch
--------------------------------------------------------------------------------
/For Build/Mods/Realistic AI/content-manhunt/chunk0/Realistic AI Manhunt.repository.json:
--------------------------------------------------------------------------------
1 | {
2 | "f045ad91-9a20-4c78-9be2-39f69cc695ad": {
3 | "Value": 7,
4 | "Toggle": true
5 | },
6 | "e0cff39f-aaef-406c-ab2a-a0d812923c11": {
7 | "Value": 12
8 | },
9 | "d317ac83-34a0-48cd-9c48-1ee92e6dd6e5": {
10 | "Value": 7,
11 | "Toggle": true
12 | },
13 | "b616cda4-6aa9-4277-b8ac-ac86c9116270": {
14 | "Value": 40
15 | },
16 | "a8319f65-09fe-46be-a914-b98039c4d831": {
17 | "Value": 400
18 | },
19 | "92488ee1-9f97-42d5-a5f6-8c4d30dffdf9": {
20 | "Value": 0.2
21 | },
22 | "8206fa1c-601c-44e2-b455-8b0e296f9e3d": {
23 | "Value": 3,
24 | "Toggle": true
25 | },
26 | "7864c92c-e246-4fd6-b540-316fddac2e82": {
27 | "Value": 0.4
28 | },
29 | "6fe10af7-e60e-4924-bd78-c1c596dc84d9": {
30 | "Value": 2.5
31 | },
32 | "6a26d2b3-5363-461d-a699-d38b44ba48b4": {
33 | "Value": 3
34 | },
35 | "6a1e6009-3013-46bd-ada1-1b4b471920dc": {
36 | "Value": 0.2
37 | },
38 | "63fc82a9-5d7c-4b05-ae6c-a60b36648afe": {
39 | "Value": 5
40 | },
41 | "57f89493-0364-46e9-a1e8-9897c1474f8f": {
42 | "Value": 3
43 | },
44 | "4aee33d7-8a05-4df8-96ac-15bfa97e160c": {
45 | "Value": 425
46 | },
47 | "455a46f9-7b81-453d-9a38-cd45308e37c8": {
48 | "Value": 7,
49 | "Toggle": true
50 | },
51 | "432c4282-8792-4982-b35f-eb7660c9c834": {
52 | "Value": 3,
53 | "Toggle": true
54 | },
55 | "1bde01b1-d873-4d67-9af8-4461c3a1fee8": {
56 | "Value": 40
57 | },
58 | "17d26f17-4e58-483e-9923-4118559a1a83": {
59 | "Value": 600
60 | },
61 | "168fead8-6ef5-4a21-95d9-99758c611571": {
62 | "Value": 3,
63 | "Toggle": true
64 | },
65 | "116463d8-bf8a-4abe-98e8-1666c207f0c8": {
66 | "Value": 999,
67 | "Count": 999
68 | },
69 | "1094dd4e-c277-4bd1-a637-8c8b428c9add": {
70 | "Value": 3,
71 | "Toggle": true
72 | },
73 | "0cf3b48b-8d9c-4aaa-9984-b386bfdea1ab": {
74 | "Value": 3
75 | },
76 | "047cb532-1791-4a28-a9da-6aa7cfcfc178": {
77 | "Value": 0.25
78 | }
79 | }
--------------------------------------------------------------------------------
/For Build/Mods/Realistic AI/content-normal/chunk0/Realistic AI Normal.repository.json:
--------------------------------------------------------------------------------
1 | {
2 | "fc471a2e-198d-4c35-97d9-54b8bbce927e": {
3 | "Value": 0.15
4 | },
5 | "f045ad91-9a20-4c78-9be2-39f69cc695ad": {
6 | "Value": 7,
7 | "Toggle": true
8 | },
9 | "e0cff39f-aaef-406c-ab2a-a0d812923c11": {
10 | "Value": 12
11 | },
12 | "d317ac83-34a0-48cd-9c48-1ee92e6dd6e5": {
13 | "Value": 7,
14 | "Toggle": true
15 | },
16 | "b616cda4-6aa9-4277-b8ac-ac86c9116270": {
17 | "Value": 40
18 | },
19 | "a8319f65-09fe-46be-a914-b98039c4d831": {
20 | "Value": 125
21 | },
22 | "92488ee1-9f97-42d5-a5f6-8c4d30dffdf9": {
23 | "Value": 0.2
24 | },
25 | "8206fa1c-601c-44e2-b455-8b0e296f9e3d": {
26 | "Value": 3,
27 | "Toggle": true
28 | },
29 | "7864c92c-e246-4fd6-b540-316fddac2e82": {
30 | "Value": 0.4
31 | },
32 | "6fe10af7-e60e-4924-bd78-c1c596dc84d9": {
33 | "Value": 2.5
34 | },
35 | "6a26d2b3-5363-461d-a699-d38b44ba48b4": {
36 | "Value": 3
37 | },
38 | "6a1e6009-3013-46bd-ada1-1b4b471920dc": {
39 | "Value": 0.2
40 | },
41 | "63fc82a9-5d7c-4b05-ae6c-a60b36648afe": {
42 | "Value": 5
43 | },
44 | "57f89493-0364-46e9-a1e8-9897c1474f8f": {
45 | "Value": 3
46 | },
47 | "4aee33d7-8a05-4df8-96ac-15bfa97e160c": {
48 | "Value": 150
49 | },
50 | "455a46f9-7b81-453d-9a38-cd45308e37c8": {
51 | "Value": 7,
52 | "Toggle": true
53 | },
54 | "432c4282-8792-4982-b35f-eb7660c9c834": {
55 | "Value": 3,
56 | "Toggle": true
57 | },
58 | "1bde01b1-d873-4d67-9af8-4461c3a1fee8": {
59 | "Value": 40
60 | },
61 | "17d26f17-4e58-483e-9923-4118559a1a83": {
62 | "Value": 180
63 | },
64 | "168fead8-6ef5-4a21-95d9-99758c611571": {
65 | "Value": 3,
66 | "Toggle": true
67 | },
68 | "1094dd4e-c277-4bd1-a637-8c8b428c9add": {
69 | "Value": 3,
70 | "Toggle": true
71 | },
72 | "0cf3b48b-8d9c-4aaa-9984-b386bfdea1ab": {
73 | "Value": 3
74 | },
75 | "047cb532-1791-4a28-a9da-6aa7cfcfc178": {
76 | "Value": 0.25
77 | }
78 | }
--------------------------------------------------------------------------------
/For Build/Mods/Realistic AI/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0.1",
3 | "id": "Atampy26.RealisticAI",
4 | "name": "Realistic AI",
5 | "description": "Makes the AI smarter, more realistic and more attentive in Master mode.",
6 | "authors": ["Atampy26"],
7 | "frameworkVersion": "2.33.26",
8 | "updateCheck": "https://hitman-resources.netlify.app/framework/updates/Realistic AI.json",
9 | "options": [
10 | {
11 | "group": "Edition",
12 | "name": "Normal",
13 | "tooltip": "The base version of Realistic AI; more realistic than vanilla.",
14 | "enabledByDefault": true,
15 | "type": "select",
16 | "contentFolders": ["content-normal"]
17 | },
18 | {
19 | "group": "Edition",
20 | "name": "Manhunt",
21 | "tooltip": "Guards now set up Manhunts, in which a large area of the map is searched, centred at your last known position.",
22 | "type": "select",
23 | "contentFolders": ["content-manhunt"]
24 | },
25 | {
26 | "group": "Edition",
27 | "name": "Extreme",
28 | "tooltip": "Increases everything to ridiculous levels, past the point of realism. Everyone now has precognition and knows exactly what you're doing.",
29 | "type": "select",
30 | "contentFolders": ["content-extreme"]
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/For Build/Third-Party/ResourceLib_HM2.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Third-Party/ResourceLib_HM2.dll
--------------------------------------------------------------------------------
/For Build/Third-Party/ResourceLib_HM2016.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Third-Party/ResourceLib_HM2016.dll
--------------------------------------------------------------------------------
/For Build/Third-Party/ResourceLib_HM3.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Third-Party/ResourceLib_HM3.dll
--------------------------------------------------------------------------------
/For Build/Third-Party/ResourceLib_HMA.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Third-Party/ResourceLib_HMA.dll
--------------------------------------------------------------------------------
/For Build/Third-Party/ResourceTool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Third-Party/ResourceTool.exe
--------------------------------------------------------------------------------
/For Build/Third-Party/assimp.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Third-Party/assimp.dll
--------------------------------------------------------------------------------
/For Build/Third-Party/hash_list.hmla:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Third-Party/hash_list.hmla
--------------------------------------------------------------------------------
/For Build/Third-Party/quickentity_ffi.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/Third-Party/quickentity_ffi.dll
--------------------------------------------------------------------------------
/For Build/cleanMicrosoftThumbs.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/cleanMicrosoftThumbs.dat
--------------------------------------------------------------------------------
/For Build/cleanPackageDefinition.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/cleanPackageDefinition.txt
--------------------------------------------------------------------------------
/For Build/cleanThumbs.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/For Build/cleanThumbs.dat
--------------------------------------------------------------------------------
/For Build/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "runtimePath": "..\\Runtime",
3 | "retailPath": "..\\Retail",
4 | "skipIntro": false,
5 | "outputToSeparateDirectory": false,
6 | "loadOrder": [],
7 | "modOptions": {},
8 | "outputConfigToAppDataOnDeploy": true,
9 | "knownMods": []
10 | }
--------------------------------------------------------------------------------
/Mod Manager/.gitignore:
--------------------------------------------------------------------------------
1 | types/env.d.ts
2 | yarn-error.log
3 | pnpm-lock.yaml
4 | node_modules/
5 | .svelte-kit/
6 | .DS_Store
7 | .svelte/
8 | *.local
9 | build/
10 | dist/
--------------------------------------------------------------------------------
/Mod Manager/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict = true
2 |
--------------------------------------------------------------------------------
/Mod Manager/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "svelteSortOrder": "scripts-markup-styles",
3 | "htmlWhitespaceSensitivity": "ignore",
4 | "trailingComma": "none",
5 | "requirePragma": false,
6 | "bracketSpacing": true,
7 | "singleQuote": false,
8 | "printWidth": 200,
9 | "useTabs": true,
10 | "tabWidth": 4,
11 | "semi": false
12 | }
--------------------------------------------------------------------------------
/Mod Manager/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["svelte.svelte-vscode"]
3 | }
4 |
--------------------------------------------------------------------------------
/Mod Manager/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "[svelte]": {
3 | "editor.formatOnSave": true,
4 | "editor.defaultFormatter": "svelte.svelte-vscode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Mod Manager/build.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "appId": "com.atampy26.simple-mod-framework.mod-manager",
3 | "compression": "maximum",
4 | "productName": "Mod Manager",
5 | "directories": {
6 | "output": "dist",
7 | "buildResources": "buildResources"
8 | },
9 | "files": [
10 | "src/electron.cjs",
11 | "src/preload.cjs",
12 | "src/torchlight/**/*",
13 | {
14 | "from": "build",
15 | "to": ""
16 | }
17 | ],
18 | "protocols": [
19 | {
20 | "name": "Simple Mod Framework",
21 | "schemes": ["simple-mod-framework"]
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/Mod Manager/buildResources/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Mod Manager/buildResources/icon.ico
--------------------------------------------------------------------------------
/Mod Manager/globals.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/Mod Manager/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "$lib": ["src/lib"],
6 | "$lib/*": ["src/lib/*"],
7 | "/~/*": ["src/*"]
8 | }
9 | },
10 | "exclude": ["node_modules", "build", "dist"]
11 | }
12 |
--------------------------------------------------------------------------------
/Mod Manager/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ModManager",
3 | "version": "1.0.0",
4 | "author": "Atampy26",
5 | "private": true,
6 | "description": "Mod manager for the Simple Mod Framework.",
7 | "main": "src/electron.cjs",
8 | "type": "module",
9 | "scripts": {
10 | "dev": "cross-env NODE_ENV=dev npm run dev:all",
11 | "dev:all": "concurrently -n=svelte,electron -c='#ff3e00',blue \"npm run dev:svelte\" \"npm run dev:electron\"",
12 | "dev:svelte": "vite dev",
13 | "dev:electron": "electron src/electron.cjs",
14 | "build": "cross-env NODE_ENV=production npm run build:svelte && npm run build:electron",
15 | "build:svelte": "vite build",
16 | "build:electron": "electron-builder -w --dir --config build.config.json",
17 | "start": "vite start"
18 | },
19 | "engines": {
20 | "npm": ">=7",
21 | "pnpm": "use npm - https://github.com/FractalHQ/sveltekit-electron/issues/12#issuecomment-1068399385",
22 | "yarn": "use npm - https://github.com/FractalHQ/sveltekit-electron/issues/12#issuecomment-1068399385"
23 | },
24 | "browserslist": [
25 | "Chrome 89"
26 | ],
27 | "dependencies": {
28 | "@electron/remote": "^2.0.8",
29 | "@fortawesome/free-regular-svg-icons": "^6.1.2",
30 | "@fortawesome/free-solid-svg-icons": "^6.1.2",
31 | "adm-zip": "^0.5.9",
32 | "ajv": "^8.11.0",
33 | "ansi-to-html": "^0.7.2",
34 | "autoprefixer": "^10.4.8",
35 | "axios": "^0.27.2",
36 | "carbon-components-svelte": "^0.67.8",
37 | "carbon-icons-svelte": "^11.2.0",
38 | "chalk": "^4.1.2",
39 | "electron-context-menu": "^2.5.2",
40 | "electron-reloader": "^1.2.3",
41 | "electron-serve": "^1.1.0",
42 | "electron-window-state": "^5.0.3",
43 | "filtrex": "^3.0.0",
44 | "fs-extra": "^10.1.0",
45 | "hash-wasm": "^4.9.0",
46 | "json5": "^2.2.2",
47 | "klaw-sync": "^6.0.0",
48 | "lodash.chunk": "^4.2.0",
49 | "lodash.get": "^4.4.2",
50 | "lodash.isequal": "^4.5.0",
51 | "lodash.memoize": "^4.1.2",
52 | "lodash.mergewith": "^4.6.2",
53 | "marked": "^4.0.18",
54 | "md5": "^2.3.0",
55 | "postcss": "^8.4.16",
56 | "rehype-stringify": "^9.0.3",
57 | "sanitize-html": "^2.7.3",
58 | "semver": "^7.3.7",
59 | "shiki": "^0.11.1",
60 | "svelte-fa": "^2.4.0",
61 | "svelte-tippy": "^1.3.2",
62 | "tailwindcss": "^3.1.8",
63 | "tippy.js": "^6.3.7",
64 | "unified": "^10.1.2",
65 | "uuid": "^8.3.2"
66 | },
67 | "devDependencies": {
68 | "@sveltejs/adapter-static": "1.0.0-next.50",
69 | "@sveltejs/kit": "^1.25.1",
70 | "@types/adm-zip": "^0.5.0",
71 | "@types/electron-window-state": "^2.0.34",
72 | "@types/lodash.isequal": "^4.5.6",
73 | "@types/lodash.memoize": "^4.1.7",
74 | "@types/lodash.mergewith": "^4.6.7",
75 | "@types/marked": "^4.0.3",
76 | "@types/sanitize-html": "^2.6.2",
77 | "@types/uuid": "^8.3.4",
78 | "@typescript-eslint/eslint-plugin": "^5.33.0",
79 | "@typescript-eslint/parser": "^5.33.0",
80 | "concurrently": "^7.3.0",
81 | "cross-env": "^7.0.3",
82 | "dotenv": "^8.6.0",
83 | "electron": "^26.2.4",
84 | "electron-builder": "^23.3.3",
85 | "electron-connect": "^0.6.3",
86 | "electron-packager": "^15.4.0",
87 | "electron-updater": "^4.6.5",
88 | "eslint": "^8.21.0",
89 | "eslint-plugin-svelte": "^2.33.2",
90 | "npm-run-all": "^4.1.5",
91 | "prettier": "^3.0.3",
92 | "prettier-eslint": "^15.0.1",
93 | "prettier-plugin-svelte": "^3.0.3",
94 | "sass": "^1.54.4",
95 | "svelte": "^4.2.1",
96 | "svelte-check": "^3.5.2",
97 | "svelte-preprocess": "^5.0.4",
98 | "typescript": "^4.7.4",
99 | "vite": "^4.4.9"
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/Mod Manager/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | tailwindcss: {}
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Mod Manager/src/app.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | code.h {
6 | @apply bg-neutral-800 text-orange-200 rounded-sm text-sm;
7 | font-family: "Fira Code", "IBM Plex Mono", "Menlo", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", Courier, monospace !important;
8 | padding: 0.1rem 0.2rem !important;
9 | }
--------------------------------------------------------------------------------
/Mod Manager/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 | Simple Mod Framework
11 | %sveltekit.head%
12 |
13 |
14 |
15 | %sveltekit.body%
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Mod Manager/src/global.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | import type fs from "fs-extra"
6 | import type originalFs from "original-fs"
7 | import type klaw from "klaw-sync"
8 | import type path from "path"
9 | import type buffer from "buffer"
10 | import type electron from "electron"
11 | import type sanitizeHtml from "sanitize-html"
12 | import type child_process from "child_process"
13 |
14 | declare global {
15 | interface Window {
16 | ipc: any
17 | fs: typeof fs
18 | isFile: (path: string) => boolean
19 | originalFs: typeof originalFs
20 | path: typeof path
21 | klaw: typeof klaw
22 | Buffer: typeof buffer
23 | openExternalLink: typeof electron["shell"]["openExternal"]
24 | sanitizeHtml: typeof sanitizeHtml
25 | child_process: typeof child_process
26 | nodeVersion: string
27 | electronVersion: string
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Mod Manager/src/lib/ExpandableTile.svelte:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 |
31 |
32 |
{
35 | open = !open
36 | clicked = true
37 | }}
38 | >
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | {#if !open}
47 |
48 |
49 |
50 | {/if}
51 | {#if open}
52 |
53 |
54 |
55 |
56 | {/if}
57 |
58 |
59 |
60 |
61 |
90 |
--------------------------------------------------------------------------------
/Mod Manager/src/lib/KeyValueEditor.svelte:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
26 |
27 |
28 | Key |
29 | Value |
30 |
31 |
32 |
33 | {#each Object.entries(data) as [key, value], index (key)}
34 |
35 |
36 | {key}
37 | |
38 |
39 |
40 | {value}
41 |
63 | |
64 |
65 | {/each}
66 |
67 |
68 |
69 |
70 | {
74 | newKeyInputModalOpen = true
75 | }}
76 | >
77 | Add an entry
78 |
79 |
80 |
81 | {
88 | if (newKeyInputModal.value && newKeyInputModal.value.length) {
89 | dispatch("define", {
90 | key: newKeyInputModal.value,
91 | value: "UI_PLACEHOLDER_VALUE"
92 | })
93 | }
94 | }}
95 | />
96 |
97 | {
105 | if (newValueInputModal.value && newValueInputModal.value.length) {
106 | dispatch("define", {
107 | key: valueToEdit,
108 | value: newValueInputModal.value
109 | })
110 | }
111 | }}
112 | />
113 |
--------------------------------------------------------------------------------
/Mod Manager/src/lib/ListEditor.svelte:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 | {#each data as value, index (value)}
25 |
26 |
27 |
28 | {value}
29 | {
35 | valueToEdit = value
36 | newValueInputModalOpen = true
37 | }}
38 | />
39 | {
45 | dispatch("undefine", {
46 | value
47 | })
48 | }}
49 | />
50 |
51 | |
52 |
53 | {/each}
54 | {#if data.length == 0}
55 |
56 |
57 |
58 | No entries
59 |
60 | |
61 |
62 | {/if}
63 |
64 |
65 |
66 |
67 | {
71 | valueToEdit = "Placeholder value"
72 | newValueInputModalOpen = true
73 | }}
74 | >
75 | Add an entry
76 |
77 |
78 |
79 | {
86 | if (newValueInputModal.value && newValueInputModal.value.length) {
87 | dispatch("define", {
88 | original: valueToEdit,
89 | new: newValueInputModal.value
90 | })
91 | }
92 | }}
93 | />
94 |
--------------------------------------------------------------------------------
/Mod Manager/src/lib/SortableList.svelte:
--------------------------------------------------------------------------------
1 |
68 |
69 | {#if list && list.length}
70 |
71 | {#each list as item, index (getKey(item))}
72 | -
85 |
86 |
{getKey(item)}
87 |
88 |
89 | {/each}
90 |
91 | {/if}
92 |
93 |
106 |
--------------------------------------------------------------------------------
/Mod Manager/src/lib/TextInputModal.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
17 |
18 | {
23 | modalInput.value = modalInitialText
24 | modalInput.focus()
25 | }}
26 | on:close
27 | >
28 | {#if multiline}
29 |
30 | {:else}
31 | {
38 | if (e.key === "Enter") {
39 | showingModal = false
40 | }
41 | }}
42 | />
43 | {/if}
44 |
45 |
--------------------------------------------------------------------------------
/Mod Manager/src/lib/json-patch-schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-07/schema#",
3 | "type": "object",
4 | "properties": {
5 | "file": { "type": "string" },
6 | "type": { "type": "string" },
7 | "patch": {
8 | "type": "array",
9 | "items": {
10 | "oneOf": [
11 | {
12 | "additionalProperties": false,
13 | "required": ["value", "op", "path"],
14 | "properties": {
15 | "path": { "type": "string" },
16 | "op": { "description": "The operation to perform.", "type": "string", "enum": ["add", "replace", "test"] },
17 | "value": { "description": "The value to add, replace or test." }
18 | }
19 | },
20 | {
21 | "additionalProperties": false,
22 | "required": ["op", "path"],
23 | "properties": { "path": { "type": "string" }, "op": { "description": "The operation to perform.", "type": "string", "enum": ["remove"] } }
24 | },
25 | {
26 | "additionalProperties": false,
27 | "required": ["from", "op", "path"],
28 | "properties": {
29 | "path": { "type": "string" },
30 | "op": { "description": "The operation to perform.", "type": "string", "enum": ["move", "copy"] },
31 | "from": { "type": "string", "description": "A JSON Pointer path pointing to the location to move/copy from." }
32 | }
33 | }
34 | ]
35 | }
36 | }
37 | },
38 | "additionalProperties": false,
39 | "required": ["file", "patch"]
40 | }
41 |
--------------------------------------------------------------------------------
/Mod Manager/src/lib/unlockables-schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-07/schema#",
3 | "type": "object",
4 | "patternProperties": { "^.*$": { "$ref": "#/definitions/Unlockable" } },
5 | "definitions": {
6 | "Unlockable": {
7 | "type": "object",
8 | "properties": {
9 | "Id": { "type": "string" },
10 | "Guid": { "type": "string" },
11 | "Type": { "type": "string" },
12 | "Subtype": { "type": "string" },
13 | "ImageId": { "anyOf": [{ "type": "null" }, { "type": "string" }] },
14 | "RMTPrice": { "type": "integer" },
15 | "GamePrice": { "type": "integer" },
16 | "IsPurchasable": { "type": "boolean" },
17 | "IsPublished": { "type": "boolean" },
18 | "IsDroppable": { "type": "boolean" },
19 | "Capabilities": { "type": "array", "items": {} },
20 | "Qualities": { "$ref": "#/definitions/Qualities" },
21 | "Properties": { "$ref": "#/definitions/Properties" },
22 | "Rarity": { "anyOf": [{ "type": "null" }, { "type": "string" }] },
23 | "UnlockOrder": { "type": "integer" }
24 | }
25 | },
26 | "Properties": {
27 | "type": "object",
28 | "properties": {
29 | "RewardHidden": { "type": "boolean" },
30 | "HowToUnlock": { "type": "string" },
31 | "AllowUpSync": { "type": "boolean" },
32 | "Background": { "type": "string" },
33 | "Icon": { "type": "string" },
34 | "LockedIcon": { "type": "string" },
35 | "DlcImage": { "type": "string" },
36 | "DlcName": { "type": "string" },
37 | "IsLocked": { "type": "boolean" },
38 | "Order": { "type": "integer" },
39 | "ProgressionKey": { "type": "string" },
40 | "Season": { "type": "integer" },
41 | "RequiredResources": { "type": "array", "items": { "type": "string" } },
42 | "Entitlements": { "type": "array", "items": { "type": "string" } },
43 | "ParentLocation": { "type": "string" },
44 | "GameChangers": { "type": "array", "items": {} },
45 | "CreateContractId": { "type": "string" },
46 | "IsFreeDLC": { "type": "boolean" },
47 | "HideProgression": { "type": "boolean" },
48 | "ExcludeParentRewards": { "type": "boolean" },
49 | "Quality": { "$ref": "#/definitions/Quality" },
50 | "v0Id": { "type": "string" },
51 | "UpcomingContent": { "type": "boolean" },
52 | "UpcomingKey": { "type": "string" },
53 | "LimitedLoadout": { "type": "boolean" },
54 | "NormalLoadoutUnlock": { "type": "string" },
55 | "Unlocks": { "type": "array", "items": { "type": "string" } },
56 | "Rarity": { "type": "string" },
57 | "LoadoutSlot": { "type": "string" },
58 | "IsConsumable": { "type": "boolean" },
59 | "RepositoryId": { "type": "string" },
60 | "OrderIndex": { "type": "integer" },
61 | "Name": { "type": "string" },
62 | "Description": { "type": "string" },
63 | "UnlockOrder": { "type": "integer" },
64 | "Location": { "type": "string" },
65 | "UnlockedByDefault": { "type": "boolean" },
66 | "Equip": { "type": "array", "items": { "type": "string" } },
67 | "GameAssets": { "type": "array", "items": { "type": "string" } },
68 | "RepositoryAssets": { "type": "array", "items": { "type": "string" } },
69 | "Gameplay": { "$ref": "#/definitions/Gameplay" },
70 | "AlwaysAdd": { "type": "boolean" },
71 | "BlacklistedByDefault": { "type": "boolean" },
72 | "IsContainer": { "type": "boolean" },
73 | "LoadoutSettings": { "$ref": "#/definitions/LoadoutSettings" },
74 | "Perks": { "type": "array", "items": { "type": "string" } }
75 | }
76 | },
77 | "Gameplay": { "type": "object", "properties": { "range": { "type": "number" }, "damage": { "type": "number" }, "clipsize": { "type": "number" }, "rateoffire": { "type": "number" } } },
78 | "LoadoutSettings": {
79 | "type": "object",
80 | "properties": { "GearSlotsEnabledCount": { "type": "integer" }, "GearSlotsAllowContainers": { "type": "boolean" }, "ConcealedWeaponSlotEnabled": { "type": "boolean" } }
81 | },
82 | "Qualities": { "type": "object" },
83 | "Quality": { "anyOf": [{ "type": "integer" }, { "type": "string" }] }
84 | },
85 | "additionalProperties": false
86 | }
87 |
--------------------------------------------------------------------------------
/Mod Manager/src/preload.cjs:
--------------------------------------------------------------------------------
1 | const { contextBridge, ipcRenderer, shell } = require("electron")
2 |
3 | contextBridge.exposeInMainWorld("fs", require("fs-extra"))
4 | contextBridge.exposeInMainWorld("isFile", path => require("fs-extra").statSync(path).isFile())
5 | contextBridge.exposeInMainWorld("originalFs", require("original-fs"))
6 | contextBridge.exposeInMainWorld("path", require("path"))
7 | contextBridge.exposeInMainWorld("klaw", require("klaw-sync"))
8 | contextBridge.exposeInMainWorld("Buffer", {
9 | isBuffer: Buffer.isBuffer,
10 | from: Buffer.from
11 | })
12 | contextBridge.exposeInMainWorld("ipc", {
13 | send: (channel, data) => {
14 | ipcRenderer.send(channel, data)
15 | },
16 | sendSync: (channel, data) => {
17 | ipcRenderer.sendSync(channel, data)
18 | },
19 | receive: (channel, func) => {
20 | ipcRenderer.on(channel, (event, ...args) => func(...args))
21 | },
22 | receiveOnce: (channel, func) => {
23 | ipcRenderer.once(channel, (event, ...args) => func(...args))
24 | }
25 | })
26 | contextBridge.exposeInMainWorld("openExternalLink", shell.openExternal)
27 | contextBridge.exposeInMainWorld("sanitizeHtml", require("sanitize-html"))
28 | contextBridge.exposeInMainWorld("child_process", require("child_process"))
29 | contextBridge.exposeInMainWorld("nodeVersion", process.versions.node)
30 | contextBridge.exposeInMainWorld("electronVersion", process.versions.electron)
31 |
--------------------------------------------------------------------------------
/Mod Manager/src/routes/+layout.svelte:
--------------------------------------------------------------------------------
1 |
22 |
23 | {#if ready}
24 |
51 | {/if}
52 |
53 |
58 |
--------------------------------------------------------------------------------
/Mod Manager/src/routes/authoring/+page.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
Mod Authoring
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 | {#each getAllMods()
23 | .filter((a) => modIsFramework(a))
24 | .map((a) => getManifestFromModID(a))
25 | .sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: "base" })) as manifest (manifest.id)}
26 |
27 |
28 |
29 | {manifest.authors.length == 1 ? manifest.authors.join(", ") : manifest.authors.slice(0, -1).join(", ") + " and " + manifest.authors.at(-1)}
30 |
31 | {manifest.name}
32 |
33 |
34 | {manifest.description}
35 |
36 |
37 |
38 | goto(`/authoring/${manifest.id}`)} />
39 |
40 |
41 |
42 | {/each}
43 |
44 |
45 |
46 |
47 |
48 |
58 |
--------------------------------------------------------------------------------
/Mod Manager/src/routes/docs/[page]/+page.svelte:
--------------------------------------------------------------------------------
1 |
67 |
68 |
69 |
70 |
{$page.params.page.split(".")[0]}
71 |
72 | {#if loading}
73 |
74 | {:else}
75 | window.history.back()} icon={ArrowLeft}>Back
76 | goto("/docs/Index.md")} icon={Home}>Go to Index
77 | {/if}
78 |
79 |
80 | {@html pageContent}
81 |
82 |
83 |
114 |
--------------------------------------------------------------------------------
/Mod Manager/src/routes/info/+page.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
Information
15 |
16 | This GUI is powered by Svelte, and the CLI is powered by Node.js. You're on framework version {FrameworkVersion}.
17 |
18 |
19 |
Thanks to the Hitman modding community for making this possible, and thanks to IO Interactive for making the game this is for.
20 |
21 |
22 | {
25 | mergeConfig({ skipIntro: detail })
26 | }}
27 | labelText="Skip intro"
28 | />
29 |
30 |
31 |
32 |
33 | {
36 | if (getConfig().developerMode) {
37 | mergeConfig({
38 | developerMode: false,
39 | knownMods: []
40 | })
41 |
42 | forceUpdate = Math.random()
43 | } else {
44 | mergeConfig({
45 | developerMode: true,
46 | knownMods: []
47 | })
48 |
49 | forceUpdate = Math.random()
50 | }
51 | }}
52 | >
53 | {forceUpdate && getConfig().developerMode ? "Disable" : "Enable"} developer mode
54 |
55 |
56 |
57 |
58 |
59 |
60 | {
63 | if (getConfig().reportErrors) {
64 | mergeConfig({
65 | reportErrors: false,
66 | errorReportingID: undefined
67 | })
68 |
69 | forceUpdate = Math.random()
70 | } else {
71 | mergeConfig({
72 | reportErrors: true,
73 | errorReportingID: v4()
74 | })
75 |
76 | forceUpdate = Math.random()
77 | }
78 | }}
79 | >
80 | {forceUpdate && getConfig().reportErrors ? "Disable" : "Enable"} error reporting
81 |
82 | {#if forceUpdate && getConfig().reportErrors}
83 | Your reporting ID is {forceUpdate && getConfig().errorReportingID}
84 | {/if}
85 |
86 |
87 |
88 |
89 |
90 |
92 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/berry.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
3 | "name": "berry",
4 | "patterns": [
5 | {
6 | "include": "#controls"
7 | },
8 | {
9 | "include": "#strings"
10 | },
11 | {
12 | "include": "#comment-block"
13 | },
14 | {
15 | "include": "#comments"
16 | },
17 | {
18 | "include": "#keywords"
19 | },
20 | {
21 | "include": "#function"
22 | },
23 | {
24 | "include": "#member"
25 | },
26 | {
27 | "include": "#identifier"
28 | },
29 | {
30 | "include": "#number"
31 | },
32 | {
33 | "include": "#operator"
34 | }
35 | ],
36 | "repository": {
37 | "controls": {
38 | "patterns": [
39 | {
40 | "name": "keyword.control.berry",
41 | "match": "\\b(if|elif|else|for|while|do|end|break|continue|return|try|except|raise)\\b"
42 | }
43 | ]
44 | },
45 | "strings": {
46 | "patterns": [
47 | {
48 | "name": "string.quoted.double.berry",
49 | "match": "\"(\\\\.|[^\"])*\""
50 | },
51 | {
52 | "name": "string.quoted.single.berry",
53 | "match": "'(\\\\.|[^'])*'"
54 | }
55 | ]
56 | },
57 | "comment-block": {
58 | "name": "comment.berry",
59 | "begin": "\\#\\-",
60 | "end": "\\-#",
61 | "patterns": [{}]
62 | },
63 | "comments": {
64 | "name": "comment.line.berry",
65 | "begin": "\\#",
66 | "end": "\\n",
67 | "patterns": [{}]
68 | },
69 | "keywords": {
70 | "patterns": [
71 | {
72 | "name": "keyword.berry",
73 | "match": "\\b(var|static|def|class|true|false|nil|self|super|import|as)\\b"
74 | }
75 | ]
76 | },
77 | "identifier": {
78 | "patterns": [
79 | {
80 | "name": "identifier.berry",
81 | "match": "\\b[_A-Za-z]\\w+\\b"
82 | }
83 | ]
84 | },
85 | "number": {
86 | "patterns": [
87 | {
88 | "name": "constant.numeric.berry",
89 | "match": "0x[a-fA-F0-9]+|\\d+|(\\d+\\.?|\\.\\d)\\d*([eE][+-]?\\d+)?"
90 | }
91 | ]
92 | },
93 | "operator": {
94 | "patterns": [
95 | {
96 | "name": "keyword.operator.berry",
97 | "match": "\\(|\\)|\\[|\\]|\\.|-|\\!|~|\\*|/|%|\\+|&|\\^|\\||<|>|=|:"
98 | }
99 | ]
100 | },
101 | "member": {
102 | "patterns": [
103 | {
104 | "match": "\\.([a-zA-Z_][a-zA-Z0-9_]*)",
105 | "captures": {
106 | "0": {
107 | "name": "entity.other.attribute-name.berry"
108 | }
109 | }
110 | }
111 | ]
112 | },
113 | "function": {
114 | "patterns": [
115 | {
116 | "name": "entity.name.function.berry",
117 | "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\())"
118 | }
119 | ]
120 | }
121 | },
122 | "scopeName": "source.berry"
123 | }
124 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/docker.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "information_for_contributors": [
3 | "This file has been converted from https://github.com/moby/moby/blob/master/contrib/syntax/textmate/Docker.tmbundle/Syntaxes/Dockerfile.tmLanguage",
4 | "If you want to provide a fix or improvement, please create a pull request against the original repository.",
5 | "Once accepted there, we are happy to receive an update request."
6 | ],
7 | "version": "https://github.com/moby/moby/commit/abd39744c6f3ed854500e423f5fabf952165161f",
8 | "name": "docker",
9 | "scopeName": "source.dockerfile",
10 | "patterns": [
11 | {
12 | "captures": {
13 | "1": {
14 | "name": "keyword.other.special-method.dockerfile"
15 | },
16 | "2": {
17 | "name": "keyword.other.special-method.dockerfile"
18 | }
19 | },
20 | "match": "^\\s*\\b(?i:(FROM))\\b.*?\\b(?i:(AS))\\b"
21 | },
22 | {
23 | "captures": {
24 | "1": {
25 | "name": "keyword.control.dockerfile"
26 | },
27 | "2": {
28 | "name": "keyword.other.special-method.dockerfile"
29 | }
30 | },
31 | "match": "^\\s*(?i:(ONBUILD)\\s+)?(?i:(ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR))\\s"
32 | },
33 | {
34 | "captures": {
35 | "1": {
36 | "name": "keyword.operator.dockerfile"
37 | },
38 | "2": {
39 | "name": "keyword.other.special-method.dockerfile"
40 | }
41 | },
42 | "match": "^\\s*(?i:(ONBUILD)\\s+)?(?i:(CMD|ENTRYPOINT))\\s"
43 | },
44 | {
45 | "begin": "\"",
46 | "beginCaptures": {
47 | "1": {
48 | "name": "punctuation.definition.string.begin.dockerfile"
49 | }
50 | },
51 | "end": "\"",
52 | "endCaptures": {
53 | "1": {
54 | "name": "punctuation.definition.string.end.dockerfile"
55 | }
56 | },
57 | "name": "string.quoted.double.dockerfile",
58 | "patterns": [
59 | {
60 | "match": "\\\\.",
61 | "name": "constant.character.escaped.dockerfile"
62 | }
63 | ]
64 | },
65 | {
66 | "begin": "'",
67 | "beginCaptures": {
68 | "1": {
69 | "name": "punctuation.definition.string.begin.dockerfile"
70 | }
71 | },
72 | "end": "'",
73 | "endCaptures": {
74 | "1": {
75 | "name": "punctuation.definition.string.end.dockerfile"
76 | }
77 | },
78 | "name": "string.quoted.single.dockerfile",
79 | "patterns": [
80 | {
81 | "match": "\\\\.",
82 | "name": "constant.character.escaped.dockerfile"
83 | }
84 | ]
85 | },
86 | {
87 | "captures": {
88 | "1": {
89 | "name": "punctuation.whitespace.comment.leading.dockerfile"
90 | },
91 | "2": {
92 | "name": "comment.line.number-sign.dockerfile"
93 | },
94 | "3": {
95 | "name": "punctuation.definition.comment.dockerfile"
96 | }
97 | },
98 | "comment": "comment.line",
99 | "match": "^(\\s*)((#).*$\\n?)"
100 | }
101 | ]
102 | }
103 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/git-rebase.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "information_for_contributors": [
3 | "This file has been converted from https://github.com/textmate/git.tmbundle/blob/master/Syntaxes/Git%20Rebase%20Message.tmLanguage",
4 | "If you want to provide a fix or improvement, please create a pull request against the original repository.",
5 | "Once accepted there, we are happy to receive an update request."
6 | ],
7 | "version": "https://github.com/textmate/git.tmbundle/commit/5870cf3f8abad3a6637bdf69250b5d2ded427dc4",
8 | "name": "git-rebase",
9 | "scopeName": "text.git-rebase",
10 | "patterns": [
11 | {
12 | "captures": {
13 | "1": {
14 | "name": "punctuation.definition.comment.git-rebase"
15 | }
16 | },
17 | "match": "^\\s*(#).*$\\n?",
18 | "name": "comment.line.number-sign.git-rebase"
19 | },
20 | {
21 | "captures": {
22 | "1": {
23 | "name": "support.function.git-rebase"
24 | },
25 | "2": {
26 | "name": "constant.sha.git-rebase"
27 | },
28 | "3": {
29 | "name": "meta.commit-message.git-rebase"
30 | }
31 | },
32 | "match": "^\\s*(pick|p|reword|r|edit|e|squash|s|fixup|f|drop|d)\\s+([0-9a-f]+)\\s+(.*)$",
33 | "name": "meta.commit-command.git-rebase"
34 | },
35 | {
36 | "captures": {
37 | "1": {
38 | "name": "support.function.git-rebase"
39 | },
40 | "2": {
41 | "patterns": [
42 | {
43 | "include": "source.shell"
44 | }
45 | ]
46 | }
47 | },
48 | "match": "^\\s*(exec|x)\\s+(.*)$",
49 | "name": "meta.commit-command.git-rebase"
50 | },
51 | {
52 | "captures": {
53 | "1": {
54 | "name": "support.function.git-rebase"
55 | }
56 | },
57 | "match": "^\\s*(break|b)\\s*$",
58 | "name": "meta.commit-command.git-rebase"
59 | }
60 | ]
61 | }
62 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/ini.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "information_for_contributors": [
3 | "This file has been converted from https://github.com/textmate/ini.tmbundle/blob/master/Syntaxes/Ini.plist",
4 | "If you want to provide a fix or improvement, please create a pull request against the original repository.",
5 | "Once accepted there, we are happy to receive an update request."
6 | ],
7 | "version": "https://github.com/textmate/ini.tmbundle/commit/2af0cbb0704940f967152616f2f1ff0aae6287a6",
8 | "name": "ini",
9 | "scopeName": "source.ini",
10 | "patterns": [
11 | {
12 | "begin": "(^[ \\t]+)?(?=#)",
13 | "beginCaptures": {
14 | "1": {
15 | "name": "punctuation.whitespace.comment.leading.ini"
16 | }
17 | },
18 | "end": "(?!\\G)",
19 | "patterns": [
20 | {
21 | "begin": "#",
22 | "beginCaptures": {
23 | "0": {
24 | "name": "punctuation.definition.comment.ini"
25 | }
26 | },
27 | "end": "\\n",
28 | "name": "comment.line.number-sign.ini"
29 | }
30 | ]
31 | },
32 | {
33 | "begin": "(^[ \\t]+)?(?=;)",
34 | "beginCaptures": {
35 | "1": {
36 | "name": "punctuation.whitespace.comment.leading.ini"
37 | }
38 | },
39 | "end": "(?!\\G)",
40 | "patterns": [
41 | {
42 | "begin": ";",
43 | "beginCaptures": {
44 | "0": {
45 | "name": "punctuation.definition.comment.ini"
46 | }
47 | },
48 | "end": "\\n",
49 | "name": "comment.line.semicolon.ini"
50 | }
51 | ]
52 | },
53 | {
54 | "captures": {
55 | "1": {
56 | "name": "keyword.other.definition.ini"
57 | },
58 | "2": {
59 | "name": "punctuation.separator.key-value.ini"
60 | }
61 | },
62 | "match": "\\b([a-zA-Z0-9_.-]+)\\b\\s*(=)"
63 | },
64 | {
65 | "captures": {
66 | "1": {
67 | "name": "punctuation.definition.entity.ini"
68 | },
69 | "3": {
70 | "name": "punctuation.definition.entity.ini"
71 | }
72 | },
73 | "match": "^(\\[)(.*?)(\\])",
74 | "name": "entity.name.section.group-title.ini"
75 | },
76 | {
77 | "begin": "'",
78 | "beginCaptures": {
79 | "0": {
80 | "name": "punctuation.definition.string.begin.ini"
81 | }
82 | },
83 | "end": "'",
84 | "endCaptures": {
85 | "0": {
86 | "name": "punctuation.definition.string.end.ini"
87 | }
88 | },
89 | "name": "string.quoted.single.ini",
90 | "patterns": [
91 | {
92 | "match": "\\\\.",
93 | "name": "constant.character.escape.ini"
94 | }
95 | ]
96 | },
97 | {
98 | "begin": "\"",
99 | "beginCaptures": {
100 | "0": {
101 | "name": "punctuation.definition.string.begin.ini"
102 | }
103 | },
104 | "end": "\"",
105 | "endCaptures": {
106 | "0": {
107 | "name": "punctuation.definition.string.end.ini"
108 | }
109 | },
110 | "name": "string.quoted.double.ini"
111 | }
112 | ]
113 | }
114 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/jinja-html.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jinja-html",
3 | "scopeName": "text.html.jinja",
4 | "comment": "Jinja HTML Templates",
5 | "firstLineMatch": "^{% extends [\"'][^\"']+[\"'] %}",
6 | "foldingStartMarker": "(<(?i:(head|table|tr|div|style|script|ul|ol|form|dl))\\b.*?>|{%\\s*(block|filter|for|if|macro|raw))",
7 | "foldingStopMarker": "((?i:(head|table|tr|div|style|script|ul|ol|form|dl))\\b.*?>|{%\\s*(endblock|endfilter|endfor|endif|endmacro|endraw)\\s*%})",
8 | "patterns": [
9 | {
10 | "include": "source.jinja"
11 | },
12 | {
13 | "include": "text.html.basic"
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/logo.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "comment": "Roughed out by Paul Bissex ",
3 | "fileTypes": [],
4 | "keyEquivalent": "^~L",
5 | "name": "logo",
6 | "patterns": [
7 | {
8 | "match": "^to [\\w.]+",
9 | "name": "entity.name.function.logo"
10 | },
11 | {
12 | "match": "continue|do\\.until|do\\.while|end|for(each)?|if(else|falsetrue|)|repeat|stop|until",
13 | "name": "keyword.control.logo"
14 | },
15 | {
16 | "match": "\\b(\\.defmacro|\\.eq|\\.macro|\\.maybeoutput|\\.setbf|\\.setfirst|\\.setitem|\\.setsegmentsize|allopen|allowgetset|and|apply|arc|arctan|arity|array|arrayp|arraytolist|ascii|ashift|back|background|backslashedp|beforep|bitand|bitnot|bitor|bitxor|buried|buriedp|bury|buryall|buryname|butfirst|butfirsts|butlast|bye|cascade|case|caseignoredp|catch|char|clean|clearscreen|cleartext|close|closeall|combine|cond|contents|copydef|cos|count|crossmap|cursor|define|definedp|dequeue|difference|dribble|edall|edit|editfile|edn|edns|edpl|edpls|edps|emptyp|eofp|epspict|equalp|erall|erase|erasefile|ern|erns|erpl|erpls|erps|erract|error|exp|fence|filep|fill|filter|find|first|firsts|forever|form|forward|fput|fullprintp|fullscreen|fulltext|gc|gensym|global|goto|gprop|greaterp|heading|help|hideturtle|home|ignore|int|invoke|iseq|item|keyp|label|last|left|lessp|list|listp|listtoarray|ln|load|loadnoisily|loadpict|local|localmake|log10|lowercase|lput|lshift|macroexpand|macrop|make|map|map.se|mdarray|mditem|mdsetitem|member|memberp|minus|modulo|name|namelist|namep|names|nodes|nodribble|norefresh|not|numberp|openappend|openread|openupdate|openwrite|or|output|palette|parse|pause|pen|pencolor|pendown|pendownp|penerase|penmode|penpaint|penreverse|pensize|penup|pick|plist|plistp|plists|pllist|po|poall|pon|pons|pop|popl|popls|pops|pos|pot|pots|power|pprop|prefix|primitivep|print|printdepthlimit|printwidthlimit|procedurep|procedures|product|push|queue|quoted|quotient|radarctan|radcos|radsin|random|rawascii|readchar|readchars|reader|readlist|readpos|readrawline|readword|redefp|reduce|refresh|remainder|remdup|remove|remprop|repcount|rerandom|reverse|right|round|rseq|run|runparse|runresult|save|savel|savepict|screenmode|scrunch|sentence|setbackground|setcursor|seteditor|setheading|sethelploc|setitem|setlibloc|setmargins|setpalette|setpen|setpencolor|setpensize|setpos|setprefix|setread|setreadpos|setscrunch|settemploc|settextcolor|setwrite|setwritepos|setx|setxy|sety|shell|show|shownp|showturtle|sin|splitscreen|sqrt|standout|startup|step|stepped|steppedp|substringp|sum|tag|test|text|textscreen|thing|throw|towards|trace|traced|tracedp|transfer|turtlemode|type|unbury|unburyall|unburyname|unburyonedit|unstep|untrace|uppercase|usealternatenam|wait|while|window|word|wordp|wrap|writepos|writer|xcor|ycor)\\b",
17 | "name": "keyword.other.logo"
18 | },
19 | {
20 | "captures": {
21 | "1": {
22 | "name": "punctuation.definition.variable.logo"
23 | }
24 | },
25 | "match": "(\\:)(?:\\|[^|]*\\||[-\\w.]*)+",
26 | "name": "variable.parameter.logo"
27 | },
28 | {
29 | "match": "\"(?:\\|[^|]*\\||[-\\w.]*)+",
30 | "name": "string.other.word.logo"
31 | },
32 | {
33 | "begin": "(^[ \\t]+)?(?=;)",
34 | "beginCaptures": {
35 | "1": {
36 | "name": "punctuation.whitespace.comment.leading.logo"
37 | }
38 | },
39 | "end": "(?!\\G)",
40 | "patterns": [
41 | {
42 | "begin": ";",
43 | "beginCaptures": {
44 | "0": {
45 | "name": "punctuation.definition.comment.logo"
46 | }
47 | },
48 | "end": "\\n",
49 | "name": "comment.line.semicolon.logo"
50 | }
51 | ]
52 | }
53 | ],
54 | "scopeName": "source.logo",
55 | "uuid": "7613EC24-B0F9-4D01-8706-1D54098BFFD8"
56 | }
57 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/mdx.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
3 | "name": "mdx",
4 | "patterns": [
5 | {
6 | "include": "#jsx"
7 | },
8 | {
9 | "include": "#markdown"
10 | }
11 | ],
12 | "repository": {
13 | "jsx": {
14 | "patterns": [
15 | {
16 | "include": "#jsx-module"
17 | },
18 | {
19 | "include": "#jsx-tag"
20 | }
21 | ],
22 | "repository": {
23 | "jsx-module": {
24 | "patterns": [
25 | {
26 | "begin": "^(?=(import|export)\\b)",
27 | "while": "^(?!\\s*$)",
28 | "contentName": "source.js.jsx",
29 | "patterns": [
30 | {
31 | "include": "source.js.jsx"
32 | }
33 | ]
34 | }
35 | ]
36 | },
37 | "jsx-tag": {
38 | "patterns": [
39 | {
40 | "begin": "^(?=<([a-z]|[A-Z]))",
41 | "end": "(?<=>)",
42 | "contentName": "source.js.jsx",
43 | "patterns": [
44 | {
45 | "include": "source.js.jsx"
46 | }
47 | ]
48 | }
49 | ]
50 | }
51 | }
52 | },
53 | "markdown": {
54 | "contentName": "text.html.markdown",
55 | "patterns": [
56 | {
57 | "include": "text.html.markdown"
58 | }
59 | ]
60 | }
61 | },
62 | "scopeName": "text.html.markdown.jsx"
63 | }
64 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/php-html.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "information_for_contributors": [
3 | "This file has been converted from https://github.com/atom/language-php/blob/master/grammars/html.cson",
4 | "If you want to provide a fix or improvement, please create a pull request against the original repository.",
5 | "Once accepted there, we are happy to receive an update request."
6 | ],
7 | "version": "https://github.com/atom/language-php/commit/ff64523c94c014d68f5dec189b05557649c5872a",
8 | "name": "php-html",
9 | "scopeName": "text.html.php",
10 | "injections": {
11 | "L:meta.embedded.php.blade": {
12 | "patterns": [
13 | {
14 | "include": "text.html.basic"
15 | },
16 | {
17 | "include": "text.html.php.blade#blade"
18 | }
19 | ]
20 | },
21 | "text.html.php - (meta.embedded | meta.tag), L:((text.html.php meta.tag) - (meta.embedded.block.php | meta.embedded.line.php)), L:(source.js - (meta.embedded.block.php | meta.embedded.line.php)), L:(source.css - (meta.embedded.block.php | meta.embedded.line.php))": {
22 | "patterns": [
23 | {
24 | "include": "#php-tag"
25 | }
26 | ]
27 | }
28 | },
29 | "patterns": [
30 | {
31 | "begin": "\\A#!",
32 | "beginCaptures": {
33 | "0": {
34 | "name": "punctuation.definition.comment.php"
35 | }
36 | },
37 | "end": "$",
38 | "name": "comment.line.shebang.php"
39 | },
40 | {
41 | "include": "text.html.derivative"
42 | }
43 | ],
44 | "repository": {
45 | "php-tag": {
46 | "patterns": [
47 | {
48 | "begin": "<\\?(?i:php|=)?(?![^?]*\\?>)",
49 | "beginCaptures": {
50 | "0": {
51 | "name": "punctuation.section.embedded.begin.php"
52 | }
53 | },
54 | "end": "(\\?)>",
55 | "endCaptures": {
56 | "0": {
57 | "name": "punctuation.section.embedded.end.php"
58 | },
59 | "1": {
60 | "name": "source.php"
61 | }
62 | },
63 | "name": "meta.embedded.block.php",
64 | "contentName": "source.php",
65 | "patterns": [
66 | {
67 | "include": "source.php"
68 | }
69 | ]
70 | },
71 | {
72 | "begin": "<\\?(?i:php|=)?",
73 | "beginCaptures": {
74 | "0": {
75 | "name": "punctuation.section.embedded.begin.php"
76 | }
77 | },
78 | "end": "(\\?)>",
79 | "endCaptures": {
80 | "0": {
81 | "name": "punctuation.section.embedded.end.php"
82 | },
83 | "1": {
84 | "name": "source.php"
85 | }
86 | },
87 | "name": "meta.embedded.line.php",
88 | "contentName": "source.php",
89 | "patterns": [
90 | {
91 | "include": "source.php"
92 | }
93 | ]
94 | }
95 | ]
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/sparql.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sparql",
3 | "scopeName": "source.sparql",
4 | "fileTypes": ["rq", "sparql"],
5 | "patterns": [
6 | {
7 | "include": "source.turtle"
8 | },
9 | {
10 | "include": "#query-keyword-operators"
11 | },
12 | {
13 | "include": "#functions"
14 | },
15 | {
16 | "include": "#variables"
17 | },
18 | {
19 | "include": "#expression-operators"
20 | }
21 | ],
22 | "repository": {
23 | "query-keyword-operators": {
24 | "name": "keyword.control.sparql",
25 | "match": "\\b(?i:define|select|distinct|reduced|from|named|construct|ask|describe|where|graph|having|bind|as|filter|optional|union|order|by|group|limit|offset|values|insert data|delete data|with|delete|insert|clear|silent|default|all|create|drop|copy|move|add|to|using|service|not exists|exists|not in|in|minus|load)\\b"
26 | },
27 | "functions": {
28 | "name": "support.function.sparql",
29 | "match": "\\b(?i:concat|regex|asc|desc|bound|isiri|isuri|isblank|isliteral|isnumeric|str|lang|datatype|sameterm|langmatches|avg|count|group_concat|separator|max|min|sample|sum|iri|uri|bnode|strdt|uuid|struuid|strlang|strlen|substr|ucase|lcase|strstarts|strends|contains|strbefore|strafter|encode_for_uri|replace|abs|round|ceil|floor|rand|now|year|month|day|hours|minutes|seconds|timezone|tz|md5|sha1|sha256|sha384|sha512|coalesce|if)\\b"
30 | },
31 | "variables": {
32 | "name": "constant.variable.sparql.turtle",
33 | "match": "(?|<=|>=|\\*|/|\\+|-|\\||\\^|\\?|\\!)"
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/wenyan.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
3 | "scopeName": "source.wenyan",
4 | "name": "wenyan",
5 | "patterns": [
6 | {
7 | "include": "#keywords"
8 | },
9 | {
10 | "include": "#constants"
11 | },
12 | {
13 | "include": "#operators"
14 | },
15 | {
16 | "include": "#symbols"
17 | },
18 | {
19 | "include": "#expression"
20 | },
21 | {
22 | "include": "#comment-blocks"
23 | },
24 | {
25 | "include": "#comment-lines"
26 | }
27 | ],
28 | "repository": {
29 | "expression": {
30 | "patterns": [
31 | {
32 | "include": "#variables"
33 | }
34 | ]
35 | },
36 | "keywords": {
37 | "patterns": [
38 | {
39 | "name": "storage.type",
40 | "match": "數|列|言|術|爻|物|元"
41 | },
42 | {
43 | "name": "keyword.control",
44 | "match": "乃行是術曰|若其不然者|乃歸空無|欲行是術|乃止是遍|若其然者|其物如是|乃得矣|之術也|必先得|是術曰|恆為是|之物也|乃得|是謂|云云|中之|為是|乃止|若非|或若|之長|其餘"
45 | },
46 | {
47 | "name": "keyword.control",
48 | "match": "或云|蓋謂"
49 | },
50 | {
51 | "name": "keyword.operator",
52 | "match": "中有陽乎|中無陰乎|所餘幾何|不等於|不大於|不小於|等於|大於|小於|加|減|乘|除|變|以|於"
53 | },
54 | {
55 | "name": "keyword.other",
56 | "match": "不知何禍歟|不復存矣|姑妄行此|如事不諧|名之曰|吾嘗觀|之禍歟|乃作罷|吾有|今有|物之|書之|以施|昔之|是矣|之書|方悟|之義|嗚呼|之禍|有|施|曰|噫|取|今|夫|中|豈"
57 | },
58 | {
59 | "name": "keyword.control",
60 | "match": "也|凡|遍|若|者|之|充|銜"
61 | }
62 | ]
63 | },
64 | "comment-lines": {
65 | "name": "comment.line",
66 | "begin": "注曰|疏曰|批曰",
67 | "end": "$",
68 | "patterns": [
69 | {
70 | "name": "constant.character",
71 | "match": "\\\\."
72 | }
73 | ]
74 | },
75 | "comment-blocks": {
76 | "name": "comment.block",
77 | "begin": "(注曰|疏曰|批曰)。?(「「|『)",
78 | "end": "(」」|』)",
79 | "patterns": [
80 | {
81 | "name": "constant.character",
82 | "match": "\\\\."
83 | }
84 | ]
85 | },
86 | "constants": {
87 | "patterns": [
88 | {
89 | "name": "constant.numeric",
90 | "match": "負|·|又|零|〇|一|二|三|四|五|六|七|八|九|十|百|千|萬|億|兆|京|垓|秭|穰|溝|澗|正|載|極|分|釐|毫|絲|忽|微|纖|沙|塵|埃|渺|漠"
91 | },
92 | {
93 | "name": "constant.language",
94 | "match": "其|陰|陽"
95 | },
96 | {
97 | "name": "string.quoted",
98 | "begin": "「「|『",
99 | "end": "」」|』",
100 | "patterns": [
101 | {
102 | "name": "constant.character",
103 | "match": "\\\\."
104 | }
105 | ]
106 | }
107 | ]
108 | },
109 | "symbols": {
110 | "patterns": [
111 | {
112 | "name": "punctuation.separator",
113 | "match": "。|、"
114 | }
115 | ]
116 | },
117 | "variables": {
118 | "name": "variable.other",
119 | "begin": "「",
120 | "end": "」",
121 | "patterns": [
122 | {
123 | "name": "constant.character",
124 | "match": "\\\\."
125 | }
126 | ]
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/languages/xsl.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "information_for_contributors": [
3 | "This file has been converted from https://github.com/atom/language-xml/blob/master/grammars/xsl.cson",
4 | "If you want to provide a fix or improvement, please create a pull request against the original repository.",
5 | "Once accepted there, we are happy to receive an update request."
6 | ],
7 | "version": "https://github.com/atom/language-xml/commit/507de2ee7daca60cf02e9e21fbeb92bbae73e280",
8 | "name": "xsl",
9 | "scopeName": "text.xml.xsl",
10 | "patterns": [
11 | {
12 | "begin": "(<)(xsl)((:))(template)",
13 | "captures": {
14 | "1": {
15 | "name": "punctuation.definition.tag.xml"
16 | },
17 | "2": {
18 | "name": "entity.name.tag.namespace.xml"
19 | },
20 | "3": {
21 | "name": "entity.name.tag.xml"
22 | },
23 | "4": {
24 | "name": "punctuation.separator.namespace.xml"
25 | },
26 | "5": {
27 | "name": "entity.name.tag.localname.xml"
28 | }
29 | },
30 | "end": "(>)",
31 | "name": "meta.tag.xml.template",
32 | "patterns": [
33 | {
34 | "captures": {
35 | "1": {
36 | "name": "entity.other.attribute-name.namespace.xml"
37 | },
38 | "2": {
39 | "name": "entity.other.attribute-name.xml"
40 | },
41 | "3": {
42 | "name": "punctuation.separator.namespace.xml"
43 | },
44 | "4": {
45 | "name": "entity.other.attribute-name.localname.xml"
46 | }
47 | },
48 | "match": " (?:([-_a-zA-Z0-9]+)((:)))?([a-zA-Z-]+)"
49 | },
50 | {
51 | "include": "#doublequotedString"
52 | },
53 | {
54 | "include": "#singlequotedString"
55 | }
56 | ]
57 | },
58 | {
59 | "include": "text.xml"
60 | }
61 | ],
62 | "repository": {
63 | "doublequotedString": {
64 | "begin": "\"",
65 | "beginCaptures": {
66 | "0": {
67 | "name": "punctuation.definition.string.begin.xml"
68 | }
69 | },
70 | "end": "\"",
71 | "endCaptures": {
72 | "0": {
73 | "name": "punctuation.definition.string.end.xml"
74 | }
75 | },
76 | "name": "string.quoted.double.xml"
77 | },
78 | "singlequotedString": {
79 | "begin": "'",
80 | "beginCaptures": {
81 | "0": {
82 | "name": "punctuation.definition.string.begin.xml"
83 | }
84 | },
85 | "end": "'",
86 | "endCaptures": {
87 | "0": {
88 | "name": "punctuation.definition.string.end.xml"
89 | }
90 | },
91 | "name": "string.quoted.single.xml"
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/Marko.sample:
--------------------------------------------------------------------------------
1 |
2 | <@then>Done@then>
3 | <@catch|err|>
4 |
5 | Took too long to fetch the data!
6 |
7 |
8 | Promise failed with ${err.message}.
9 |
10 | @catch>
11 |
12 |
13 | # from https://markojs.com/docs/core-tags/
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/abap.sample:
--------------------------------------------------------------------------------
1 | report zldbread no standard page heading.
2 | tables: lfa1.
3 | data: begin of t occurs 0,
4 | linfr like lfa1-lifnr,
5 | name1 like lfa1-name1,
6 | end of t.
7 |
8 | start-of-selection.
9 |
10 | get lfa1.
11 | clear t.
12 | move-corresponding lfa1 to t.
13 | append t.
14 | end-of-selection.
15 | sort t by name1.
16 | loop at t.
17 |
18 | write: / t-name1, t-lifnr.
19 | endloop.
20 |
21 | *- From https://sapbrainsonline.com/abap-tutorial/codes/reading-logical-database-using-abap-program.html -*
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/actionscript-3.sample:
--------------------------------------------------------------------------------
1 | private function createParticles( count ):void{
2 | var anchorPoint = 0;
3 | for(var i:uint = 0; i < count; i++){
4 |
5 | var particle:Object;
6 | if( inactiveFireParticles.length > 0 ){
7 | particle = inactiveFireParticles.shift();
8 | }else {
9 | particle = new Object();
10 | fireParticles.push( particle );
11 | }
12 |
13 | particle.x = uint( Math.random() * frame.width * 0.1 ) + anchors[anchorPoint];
14 | particle.y = frame.bottom;
15 | particle.life = 70 + uint( Math.random() * 30 );
16 | particle.size = 5 + uint( Math.random() * 10 );
17 |
18 | if(particle.size > 12){
19 | particle.size = 10;
20 | }
21 | particle.anchor = anchors[anchorPoint] + uint( Math.random() * 5 );
22 |
23 | anchorPoint = (anchorPoint == 9)? 0 : anchorPoint + 1;
24 | }
25 | }
26 |
27 | // From https://code.tutsplus.com/tutorials/actionscript-30-optimization-a-practical-example--active-11295
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/ada.sample:
--------------------------------------------------------------------------------
1 | with Ada.Text_IO; use Ada.Text_IO;
2 |
3 | procedure Learn is
4 |
5 | subtype Alphabet is Character range 'A' .. 'Z';
6 |
7 | begin
8 |
9 | Put_Line ("Learning Ada from " & Alphabet'First & " to " & Alphabet'Last);
10 |
11 | end Learn;
12 |
13 | -- From https://learn.adacore.com/
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/apex.sample:
--------------------------------------------------------------------------------
1 | String s1 = 'Salesforce and force.com';
2 | String s2 = s1.remove('force');
3 | System.debug( 's2'+ s2);// 'Sales and .com'
4 |
5 | // From https://www.guru99.com/apex-tutorial.html
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/applescript.sample:
--------------------------------------------------------------------------------
1 | tell application "Address Book"
2 |
3 | set bDayList to name of every person whose birth date is not missing value
4 |
5 | choose from list bDayList with prompt "Whose birthday would you like?"
6 |
7 | if the result is not false then
8 |
9 | set aName to item 1 of the result
10 |
11 | set theBirthday to birth date of person named aName
12 |
13 | display dialog aName & "'s birthday is " & date string of theBirthday
14 |
15 | end if
16 |
17 | end tell
18 |
19 | -- From https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_cmds.html
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/asm.sample:
--------------------------------------------------------------------------------
1 | segment .text ;code segment
2 | global_start ;must be declared for linker
3 |
4 | _start: ;tell linker entry point
5 | mov edx,len ;message length
6 | mov ecx,msg ;message to write
7 | mov ebx,1 ;file descriptor (stdout)
8 | mov eax,4 ;system call number (sys_write)
9 | int 0x80 ;call kernel
10 |
11 | mov eax,1 ;system call number (sys_exit)
12 | int 0x80 ;call kernel
13 |
14 | segment .data ;data segment
15 | msg db 'Hello, world!',0xa ;our dear string
16 | len equ $ - msg ;length of our dear string
17 |
18 | ;From https://www.tutorialspoint.com/assembly_programming/assembly_memory_segments.htm
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/astro.sample:
--------------------------------------------------------------------------------
1 | ---
2 | const name = "world"
3 | ---
4 |
5 |
6 |
7 |
8 |
9 | Hello, {name}
10 |
11 |
12 |
13 | Hello, {name}
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/awk.sample:
--------------------------------------------------------------------------------
1 | #!/bin/awk -f
2 | BEGIN {
3 | # How many lines
4 | lines=0;
5 | total=0;
6 | }
7 | {
8 | # this code is executed once for each line
9 | # increase the number of files
10 | lines++;
11 | # increase the total size, which is field #1
12 | total+=$1;
13 | }
14 | END {
15 | # end, now output the total
16 | print lines " lines read";
17 | print "total is ", total;
18 | if (lines > 0 ) {
19 | print "average is ", total/lines;
20 | } else {
21 | print "average is 0";
22 | }
23 | }
24 |
25 | #From https://www.grymoire.com/Unix/Awk.html
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/ballerina.sample:
--------------------------------------------------------------------------------
1 | import ballerina/io;
2 |
3 | // This function definition has two parameters of type `int`.
4 | // `returns` clause specifies type of return value.
5 | function add(int x, int y) returns int {
6 |
7 | int sum = x + y;
8 | // `return` statement returns a value.
9 | return sum;
10 |
11 | }
12 |
13 | public function main() {
14 | io:println(add(5, 11));
15 | }
16 | import ballerina/io;
17 |
18 | // This function definition has two parameters of type `int`.
19 | // `returns` clause specifies type of return value.
20 | function add(int x, int y) returns int {
21 |
22 | int sum = x + y;
23 | // `return` statement returns a value.
24 | return sum;
25 |
26 | }
27 |
28 | public function main() {
29 | io:println(add(5, 11));
30 | }
31 |
32 | // From https://ballerina.io/learn/by-example/functions
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/bat.sample:
--------------------------------------------------------------------------------
1 | @rem My First Batch file!
2 |
3 | @echo off
4 |
5 | echo Three
6 |
7 | echo Two
8 |
9 | echo One
10 |
11 | echo Hello World!
12 |
13 | pause
14 |
15 | @rem From https://o7planning.org/11531/batch-scripting-language-tutorial-for-beginners
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/berry.sample:
--------------------------------------------------------------------------------
1 | class node
2 | var v, l, r
3 | def init(v, l, r)
4 | self.v = v
5 | self.l = l
6 | self.r = r
7 | end
8 | def insert(v)
9 | if v < self.v
10 | if self.l
11 | self.l.insert(v)
12 | else
13 | self.l = node(v)
14 | end
15 | else
16 | if self.r
17 | self.r.insert(v)
18 | else
19 | self.r = node (v)
20 | end
21 | end
22 | end
23 | def sort(l)
24 | if (self.l) self.l.sort(l) end
25 | l.push(self.v)
26 | if (self.r) self.r.sort(l) end
27 | end
28 | end
29 |
30 | class btree
31 | var root
32 | def insert(v)
33 | if self.root
34 | self.root.insert(v)
35 | else
36 | self.root = node(v)
37 | end
38 | end
39 | def sort()
40 | var l = []
41 | if self.root
42 | self.root.sort(l)
43 | end
44 | return l
45 | end
46 | end
47 |
48 | var tree = btree()
49 | tree.insert(-100)
50 | tree.insert(5);
51 | tree.insert(3);
52 | tree.insert(9);
53 | tree.insert(10);
54 | tree.insert(10000000);
55 | tree.insert(1);
56 | tree.insert(-1);
57 | tree.insert(-10);
58 | print(tree.sort());
59 |
60 | # From https://github.com/berry-lang/berry/blob/master/examples/bintree.be
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/bicep.sample:
--------------------------------------------------------------------------------
1 | @description('Name of the eventhub namespace')
2 | param eventHubNamespaceName string
3 |
4 | @description('Name of the eventhub name')
5 | param eventHubName string
6 |
7 | @description('The service principal')
8 | param principalId string
9 |
10 | // Create an event hub namespace
11 | resource eventHubNamespace 'Microsoft.EventHub/namespaces@2021-01-01-preview' = {
12 | name: eventHubNamespaceName
13 | location: resourceGroup().location
14 | sku: {
15 | name: 'Standard'
16 | tier: 'Standard'
17 | capacity: 1
18 | }
19 | properties: {
20 | zoneRedundant: true
21 | }
22 | }
23 |
24 | // Create an event hub inside the namespace
25 | resource eventHub 'Microsoft.EventHub/namespaces/eventhubs@2021-01-01-preview' = {
26 | parent: eventHubNamespace
27 | name: eventHubName
28 | properties: {
29 | messageRetentionInDays: 7
30 | partitionCount: 1
31 | }
32 | }
33 |
34 | // give Azure Pipelines Service Principal permissions against the event hub
35 |
36 | var roleDefinitionAzureEventHubsDataOwner = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')
37 |
38 | resource integrationTestEventHubReceiverNamespaceRoleAssignment 'Microsoft.Authorization/roleAssignments@2018-01-01-preview' = {
39 | name: guid(principalId, eventHub.id, roleDefinitionAzureEventHubsDataOwner)
40 | scope: eventHubNamespace
41 | properties: {
42 | roleDefinitionId: roleDefinitionAzureEventHubsDataOwner
43 | principalId: principalId
44 | }
45 | }
46 |
47 | // From https://dev.azure.com/johnnyreilly/blog-demos/_git/permissioning-azure-pipelines-bicep-role-assignments?path=/infra/main.bicep
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/blade.sample:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {!! $post->html !!}
7 |
8 | @unless($post->isTweet())
9 | @if($post->external_url)
10 |
11 |
12 | Read more
13 | [{{ $post->external_url_host }}]
14 |
15 | @endif
16 | @endunless
17 |
18 |
19 | @include('front.newsletter.partials.block', [
20 | 'class' => 'mb-8',
21 | ])
22 |
23 |
24 | @include('front.posts.partials.comments')
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | @foreach($post->tags as $tag)
33 |
34 | @endforeach
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | #From https://freek.dev/2024-how-to-render-markdown-with-perfectly-highlighted-code-snippets
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/c.sample:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define ARR_LEN 7
4 |
5 | void qsort(int v[], int left, int right);
6 | void printArr(int v[], int len);
7 |
8 | int main()
9 | {
10 | int i;
11 | int v[ARR_LEN] = { 4, 3, 1, 7, 9, 6, 2 };
12 | printArr(v, ARR_LEN);
13 | qsort(v, 0, ARR_LEN-1);
14 | printArr(v, ARR_LEN);
15 | return 0;
16 | }
17 |
18 | void qsort(int v[], int left, int right)
19 | {
20 | int i, last;
21 | void swap(int v[], int i, int j);
22 |
23 | if (left >= right)
24 | return;
25 | swap(v, left, (left + right) / 2);
26 | last = left;
27 | for (i = left+1; i <= right; i++)
28 | if (v[i] < v[left])
29 | swap(v, ++last, i);
30 | swap(v, left, last);
31 | qsort(v, left, last-1);
32 | qsort(v, last+1, right);
33 | }
34 |
35 | void swap(int v[], int i, int j)
36 | {
37 | int temp;
38 |
39 | temp = v[i];
40 | v[i] = v[j];
41 | v[j] = temp;
42 | }
43 |
44 | void printArr(int v[], int len)
45 | {
46 | int i;
47 | for (i = 0; i < len; i++)
48 | printf("%d ", v[i]);
49 | printf("\n");
50 | }
51 |
52 | // From https://github.com/Heatwave/The-C-Programming-Language-2nd-Edition/blob/master/chapter-4-functions-and-program-structure/8.qsort.c
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/cadence.sample:
--------------------------------------------------------------------------------
1 | pub contract HelloWorld {
2 |
3 | // Declare a public field of type String.
4 | //
5 | // All fields must be initialized in the init() function.
6 | pub let greeting: String
7 |
8 | // The init() function is required if the contract contains any fields.
9 | init() {
10 | self.greeting = "Hello, World!"
11 | }
12 |
13 | // Public function that returns our friendly greeting!
14 | pub fun hello(): String {
15 | return self.greeting
16 | }
17 | }
18 |
19 | // From https://docs.onflow.org/cadence/tutorial/02-hello-world/
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/clarity.sample:
--------------------------------------------------------------------------------
1 | (impl-trait .sip010-ft-trait.sip010-ft-trait)
2 |
3 | ;; SIP010 trait on mainnet
4 | ;; (impl-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)
5 |
6 | (define-constant contract-owner tx-sender)
7 | (define-constant err-owner-only (err u100))
8 | (define-constant err-not-token-owner (err u101))
9 |
10 | ;; No maximum supply!
11 | (define-fungible-token clarity-coin)
12 |
13 | (define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
14 | (begin
15 | (asserts! (is-eq tx-sender sender) err-owner-only)
16 | (try! (ft-transfer? clarity-coin amount sender recipient))
17 | (match memo to-print (print to-print) 0x)
18 | (ok true)
19 | )
20 | )
21 |
22 | (define-read-only (get-name)
23 | (ok "Clarity Coin")
24 | )
25 |
26 | (define-read-only (get-symbol)
27 | (ok "CC")
28 | )
29 |
30 | (define-read-only (get-decimals)
31 | (ok u0)
32 | )
33 |
34 | (define-read-only (get-balance (who principal))
35 | (ok (ft-get-balance clarity-coin who))
36 | )
37 |
38 | (define-read-only (get-total-supply)
39 | (ok (ft-get-supply clarity-coin))
40 | )
41 |
42 | (define-read-only (get-token-uri)
43 | (ok none)
44 | )
45 |
46 | (define-public (mint (amount uint) (recipient principal))
47 | (begin
48 | (asserts! (is-eq tx-sender contract-owner) err-owner-only)
49 | (ft-mint? clarity-coin amount recipient)
50 | )
51 | )
52 |
53 | ;; From https://github.com/clarity-lang/book/blob/main/projects/sip010-ft/contracts/clarity-coin.clar
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/clojure.sample:
--------------------------------------------------------------------------------
1 | (let [my-vector [1 2 3 4]
2 | my-map {:fred "ethel"}
3 | my-list (list 4 3 2 1)]
4 | (list
5 | (conj my-vector 5)
6 | (assoc my-map :ricky "lucy")
7 | (conj my-list 5)
8 | ;the originals are intact
9 | my-vector
10 | my-map
11 | my-list))
12 | -> ([1 2 3 4 5] {:ricky "lucy", :fred "ethel"} (5 4 3 2 1) [1 2 3 4] {:fred "ethel"} (4 3 2 1))
13 |
14 | ;From https://clojure.org/about/functional_programming#_immutable_data_structures
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/cmake.sample:
--------------------------------------------------------------------------------
1 | # Almost all CMake files should start with this
2 | # You should always specify a range with the newest
3 | # and oldest tested versions of CMake. This will ensure
4 | # you pick up the best policies.
5 | cmake_minimum_required(VERSION 3.1...3.23)
6 |
7 | # This is your project statement. You should always list languages;
8 | # Listing the version is nice here since it sets lots of useful variables
9 | project(
10 | ModernCMakeExample
11 | VERSION 1.0
12 | LANGUAGES CXX)
13 |
14 | # If you set any CMAKE_ variables, that can go here.
15 | # (But usually don't do this, except maybe for C++ standard)
16 |
17 | # Find packages go here.
18 |
19 | # You should usually split this into folders, but this is a simple example
20 |
21 | # This is a "default" library, and will match the *** variable setting.
22 | # Other common choices are STATIC, SHARED, and MODULE
23 | # Including header files here helps IDEs but is not required.
24 | # Output libname matches target name, with the usual extensions on your system
25 | add_library(MyLibExample simple_lib.cpp simple_lib.hpp)
26 |
27 | # Link each target with other targets or add options, etc.
28 |
29 | # Adding something we can run - Output name matches target name
30 | add_executable(MyExample simple_example.cpp)
31 |
32 | # Make sure you link your targets with this command. It can also link libraries and
33 | # even flags, so linking a target that does not exist will not give a configure-time error.
34 | target_link_libraries(MyExample PRIVATE MyLibExample)
35 |
36 | # From https://cliutils.gitlab.io/modern-cmake/chapters/basics/example.html
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/cobol.sample:
--------------------------------------------------------------------------------
1 | *> setup the identification division
2 | IDENTIFICATION DIVISION.
3 | *> setup the program id
4 | PROGRAM-ID. HELLO.
5 | *> setup the procedure division (like 'main' function)
6 | PROCEDURE DIVISION.
7 | *> print a string
8 | DISPLAY 'WILLKOMMEN'.
9 | *> end our program
10 | STOP RUN.
11 |
12 | *> From https://medium.com/@yvanscher/7-cobol-examples-with-explanations-ae1784b4d576
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/codeql.sample:
--------------------------------------------------------------------------------
1 | // a query
2 |
3 | /**
4 | * @name LDAP query built from user-controlled sources
5 | * @description Building an LDAP query from user-controlled sources is vulnerable to insertion of
6 | * malicious LDAP code by the user.
7 | * @kind path-problem
8 | * @problem.severity error
9 | * @id py/ldap-injection
10 | * @tags experimental
11 | * security
12 | * external/cwe/cwe-090
13 | */
14 |
15 | import python
16 | import experimental.semmle.python.security.injection.LDAP
17 | import DataFlow::PathGraph
18 |
19 | from LDAPInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
20 | where config.hasFlowPath(source, sink)
21 | select sink.getNode(), source, sink, "$@ LDAP query parameter comes from $@.", sink.getNode(),
22 | "This", source.getNode(), "a user-provided value"
23 |
24 | // a concept
25 |
26 | module LDAPEscape {
27 | abstract class Range extends DataFlow::Node {
28 | abstract DataFlow::Node getAnInput();
29 | }
30 | }
31 |
32 | class LDAPEscape extends DataFlow::Node {
33 | LDAPEscape::Range range;
34 |
35 | LDAPEscape() { this = range }
36 |
37 | DataFlow::Node getAnInput() { result = range.getAnInput() }
38 | }
39 |
40 | // a library modeling
41 |
42 | private module LDAP2 {
43 | private class LDAP2QueryMethods extends string {
44 | LDAP2QueryMethods() {
45 | this in ["search", "search_s", "search_st", "search_ext", "search_ext_s"]
46 | }
47 | }
48 |
49 | private class LDAP2Query extends DataFlow::CallCfgNode, LDAPQuery::Range {
50 | DataFlow::Node ldapQuery;
51 |
52 | LDAP2Query() {
53 | exists(DataFlow::AttrRead searchMethod |
54 | this.getFunction() = searchMethod and
55 | API::moduleImport("ldap").getMember("initialize").getACall() =
56 | searchMethod.getObject().getALocalSource() and
57 | searchMethod.getAttributeName() instanceof LDAP2QueryMethods and
58 | (
59 | ldapQuery = this.getArg(0)
60 | or
61 | (
62 | ldapQuery = this.getArg(2) or
63 | ldapQuery = this.getArgByName("filterstr")
64 | )
65 | )
66 | )
67 | }
68 |
69 | override DataFlow::Node getQuery() { result = ldapQuery }
70 | }
71 |
72 | private class LDAP2EscapeDNCall extends DataFlow::CallCfgNode, LDAPEscape::Range {
73 | LDAP2EscapeDNCall() {
74 | this = API::moduleImport("ldap").getMember("dn").getMember("escape_dn_chars").getACall()
75 | }
76 |
77 | override DataFlow::Node getAnInput() { result = this.getArg(0) }
78 | }
79 |
80 | private class LDAP2EscapeFilterCall extends DataFlow::CallCfgNode, LDAPEscape::Range {
81 | LDAP2EscapeFilterCall() {
82 | this =
83 | API::moduleImport("ldap").getMember("filter").getMember("escape_filter_chars").getACall()
84 | }
85 |
86 | override DataFlow::Node getAnInput() { result = this.getArg(0) }
87 | }
88 | }
89 |
90 | // a taint flow config
91 |
92 | class LDAPInjectionFlowConfig extends TaintTracking::Configuration {
93 | LDAPInjectionFlowConfig() { this = "LDAPInjectionFlowConfig" }
94 |
95 | override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
96 |
97 | override predicate isSink(DataFlow::Node sink) { sink = any(LDAPQuery ldapQuery).getQuery() }
98 |
99 | override predicate isSanitizer(DataFlow::Node sanitizer) {
100 | sanitizer = any(LDAPEscape ldapEsc).getAnInput()
101 | }
102 | }
103 |
104 | // From https://github.com/github/codeql/pull/5443/files
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/coffee.sample:
--------------------------------------------------------------------------------
1 | # Assignment:
2 | number = 42
3 | opposite = true
4 |
5 | # Conditions:
6 | number = -42 if opposite
7 |
8 | # Functions:
9 | square = (x) -> x * x
10 |
11 | # Arrays:
12 | list = [1, 2, 3, 4, 5]
13 |
14 | # Objects:
15 | math =
16 | root: Math.sqrt
17 | square: square
18 | cube: (x) -> x * square x
19 |
20 | # Splats:
21 | race = (winner, runners...) ->
22 | print winner, runners
23 |
24 | # Existence:
25 | alert "I knew it!" if elvis?
26 |
27 | # Array comprehensions:
28 | cubes = (math.cube num for num in list)
29 |
30 | # From https://coffeescript.org/#overview
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/cpp.sample:
--------------------------------------------------------------------------------
1 | // Working of implicit type-conversion
2 |
3 | #include
4 | using namespace std;
5 |
6 | int main() {
7 |
8 | int num_int;
9 | double num_double = 9.99;
10 |
11 | // implicit conversion
12 | // assigning a double value to an int variable
13 | num_int = num_double;
14 |
15 | cout << "num_int = " << num_int << endl;
16 | cout << "num_double = " << num_double << endl;
17 |
18 | return 0;
19 | }
20 |
21 | // From https://www.programiz.com/cpp-programming/type-conversion
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/crystal.sample:
--------------------------------------------------------------------------------
1 | struct Foo(T)
2 | end
3 |
4 | Foo(Int32)
5 |
6 | # ---
7 | struct Foo
8 | end
9 |
10 | # struct Bar < Foo
11 | # end
12 | # Error in ./struct/struct.cr:10: can't extend non-abstract struct Foo
13 |
14 | abstract struct AbstractFoo
15 | end
16 |
17 | struct Bar < AbstractFoo
18 | end
19 |
20 | # ---
21 | struct Test
22 | def initialize(@test : String)
23 | end
24 | end
25 |
26 | Test.new("foo")
27 |
28 | # ---
29 | struct User
30 | property name, age
31 |
32 | def initialize(@name : String, @age : Int32)
33 | end
34 |
35 | def print
36 | puts "#{age} - #{name}"
37 | end
38 | end
39 |
40 | puts User.new("osman", 3).name
41 | User.new("ali", 9).print
42 |
43 | # From https://github.com/askn/crystal-by-example/blob/master/struct/struct.cr
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/csharp.sample:
--------------------------------------------------------------------------------
1 | using KCTest.Infrastructure.Database;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Hosting;
6 |
7 | namespace KCTest.API
8 | {
9 | public class Program
10 | {
11 | public static void Main(string[] args)
12 | {
13 | var host = CreateHostBuilder(args).Build();
14 |
15 | using (var scope = host.Services.CreateScope())
16 | {
17 | var db = scope.ServiceProvider.GetRequiredService();
18 | db.Database.Migrate();
19 | }
20 |
21 | host.Run();
22 | }
23 |
24 | public static IHostBuilder CreateHostBuilder(string[] args) =>
25 | Host.CreateDefaultBuilder(args)
26 | .ConfigureWebHostDefaults(webBuilder =>
27 | {
28 | webBuilder.UseStartup();
29 | });
30 | }
31 | }
32 |
33 | // From https://github.com/Jadhielv/KCTest/blob/master/Backend/src/KCTest.API/Program.cs
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/css.sample:
--------------------------------------------------------------------------------
1 | .Aligner {
2 | display: flex;
3 | align-items: center;
4 | justify-content: center;
5 | }
6 |
7 | .Aligner-item {
8 | max-width: 50%;
9 | }
10 |
11 | .Aligner-item--top {
12 | align-self: flex-start;
13 | }
14 |
15 | .Aligner-item--bottom {
16 | align-self: flex-end;
17 | }
18 |
19 | /* From https://philipwalton.github.io/solved-by-flexbox/demos/vertical-centering/ */
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/cue.sample:
--------------------------------------------------------------------------------
1 | package kube
2 |
3 | service: [ID=_]: {
4 | apiVersion: "v1"
5 | kind: "Service"
6 | metadata: {
7 | name: ID
8 | labels: {
9 | app: ID // by convention
10 | domain: "prod" // always the same in the given files
11 | component: #Component // varies per directory
12 | }
13 | }
14 | spec: {
15 | // Any port has the following properties.
16 | ports: [...{
17 | port: int
18 | protocol: *"TCP" | "UDP" // from the Kubernetes definition
19 | name: string | *"client"
20 | }]
21 | selector: metadata.labels // we want those to be the same
22 | }
23 | }
24 |
25 | deployment: [ID=_]: {
26 | apiVersion: "apps/v1"
27 | kind: "Deployment"
28 | metadata: name: ID
29 | spec: {
30 | // 1 is the default, but we allow any number
31 | replicas: *1 | int
32 | template: {
33 | metadata: labels: {
34 | app: ID
35 | domain: "prod"
36 | component: #Component
37 | }
38 | // we always have one namesake container
39 | spec: containers: [{name: ID}]
40 | }
41 | }
42 | }
43 |
44 | #Component: string
45 |
46 | daemonSet: [ID=_]: _spec & {
47 | apiVersion: "apps/v1"
48 | kind: "DaemonSet"
49 | _name: ID
50 | }
51 |
52 | statefulSet: [ID=_]: _spec & {
53 | apiVersion: "apps/v1"
54 | kind: "StatefulSet"
55 | _name: ID
56 | }
57 |
58 | deployment: [ID=_]: _spec & {
59 | apiVersion: "apps/v1"
60 | kind: "Deployment"
61 | _name: ID
62 | spec: replicas: *1 | int
63 | }
64 |
65 | configMap: [ID=_]: {
66 | metadata: name: ID
67 | metadata: labels: component: #Component
68 | }
69 |
70 | _spec: {
71 | _name: string
72 |
73 | metadata: name: _name
74 | metadata: labels: component: #Component
75 | spec: selector: {}
76 | spec: template: {
77 | metadata: labels: {
78 | app: _name
79 | component: #Component
80 | domain: "prod"
81 | }
82 | spec: containers: [{name: _name}]
83 | }
84 | }
85 |
86 | // Define the _export option and set the default to true
87 | // for all ports defined in all containers.
88 | _spec: spec: template: spec: containers: [...{
89 | ports: [...{
90 | _export: *true | false // include the port in the service
91 | }]
92 | }]
93 |
94 | for x in [deployment, daemonSet, statefulSet] for k, v in x {
95 | service: "\(k)": {
96 | spec: selector: v.spec.template.metadata.labels
97 |
98 | spec: ports: [
99 | for c in v.spec.template.spec.containers
100 | for p in c.ports
101 | if p._export {
102 | let Port = p.containerPort // Port is an alias
103 | port: *Port | int
104 | targetPort: *Port | int
105 | },
106 | ]
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/d.sample:
--------------------------------------------------------------------------------
1 | void main()
2 | {
3 | import std.datetime.stopwatch : benchmark;
4 | import std.math, std.parallelism, std.stdio;
5 |
6 | auto logs = new double[100_000];
7 | auto bm = benchmark!({
8 | foreach (i, ref elem; logs)
9 | elem = log(1.0 + i);
10 | }, {
11 | foreach (i, ref elem; logs.parallel)
12 | elem = log(1.0 + i);
13 | })(100); // number of executions of each tested function
14 | writefln("Linear init: %s msecs", bm[0].total!"msecs");
15 | writefln("Parallel init: %s msecs", bm[1].total!"msecs");
16 | }
17 |
18 | // From https://dlang.org/
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/dart.sample:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_workshop/screens/about_screen.dart';
3 | import 'package:flutter_workshop/screens/home_demo_screen.dart';
4 | import 'package:flutter_workshop/screens/home_screen.dart';
5 | import 'package:flutter_workshop/screens/product_detail_screen.dart';
6 | import 'package:flutter_workshop/screens/product_screen.dart';
7 | import 'package:flutter_workshop/screens/random_words_screen.dart';
8 | import 'package:flutter_workshop/screens/unknown_screen.dart';
9 | import 'package:device_simulator/device_simulator.dart';
10 |
11 | void main() => runApp(MyApp());
12 |
13 | class MyApp extends StatelessWidget {
14 | @override
15 | Widget build(BuildContext context) {
16 | return MaterialApp(
17 | initialRoute: '/',
18 | routes: {
19 | HomeScreen.routeName: (_) => DeviceSimulator(
20 | brightness: Brightness.dark, enable: true, child: HomeScreen()),
21 | ProductScreen.routeName: (_) => ProductScreen(),
22 | ProductDetailScreen.routeName: (_) => ProductDetailScreen(),
23 | RandomWordsScreen.routeName: (_) => RandomWordsScreen(),
24 | HomeDemoScreen.routeName: (_) => HomeDemoScreen(),
25 | AboutScreen.routeName: (_) => AboutScreen()
26 | },
27 | onUnknownRoute: (_) =>
28 | MaterialPageRoute(builder: (_) => UnknownScreen()));
29 | }
30 | }
31 |
32 | // From https://github.com/Jadhielv/flutter-workshop/blob/master/lib/main.dart
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/diff.sample:
--------------------------------------------------------------------------------
1 | $ cat file1.txt
2 | cat
3 | mv
4 | comm
5 | cp
6 |
7 | $ cat file2.txt
8 | cat
9 | cp
10 | diff
11 | comm
12 |
13 | $ diff -c file1.txt file2.txt
14 | *** file1.txt Thu Jan 11 08:52:37 2018
15 | --- file2.txt Thu Jan 11 08:53:01 2018
16 | ***************
17 | *** 1,4 ****
18 | cat
19 | - mv
20 | - comm
21 | cp
22 | --- 1,4 ----
23 | cat
24 | cp
25 | + diff
26 | + comm
27 |
28 | # From https://www.geeksforgeeks.org/diff-command-linux-examples/
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/dm.sample:
--------------------------------------------------------------------------------
1 | //Allows you to set a theme for a set of areas without tying them to looping sounds explicitly
2 | /datum/component/area_sound_manager
3 | //area -> looping sound type
4 | var/list/area_to_looping_type = list()
5 | //Current sound loop
6 | var/datum/looping_sound/our_loop
7 | //A list of "acceptable" z levels to be on. If you leave this, we're gonna delete ourselves
8 | var/list/accepted_zs
9 | //The timer id of our current start delay, if it exists
10 | var/timerid
11 |
12 | /datum/component/area_sound_manager/Initialize(area_loop_pairs, change_on, remove_on, acceptable_zs)
13 | if(!ismovable(parent))
14 | return
15 | area_to_looping_type = area_loop_pairs
16 | accepted_zs = acceptable_zs
17 | change_the_track()
18 |
19 | RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/react_to_move)
20 | RegisterSignal(parent, COMSIG_MOVABLE_Z_CHANGED, .proc/react_to_z_move)
21 | RegisterSignal(parent, change_on, .proc/handle_change)
22 | RegisterSignal(parent, remove_on, .proc/handle_removal)
23 |
24 | /datum/component/area_sound_manager/Destroy(force, silent)
25 | QDEL_NULL(our_loop)
26 | . = ..()
27 |
28 | /datum/component/area_sound_manager/proc/react_to_move(datum/source, atom/oldloc, dir, forced)
29 | SIGNAL_HANDLER
30 | var/list/loop_lookup = area_to_looping_type
31 | if(loop_lookup[get_area(oldloc)] == loop_lookup[get_area(parent)])
32 | return
33 | change_the_track(TRUE)
34 |
35 | /datum/component/area_sound_manager/proc/react_to_z_move(datum/source, old_z, new_z)
36 | SIGNAL_HANDLER
37 | if(!length(accepted_zs) || (new_z in accepted_zs))
38 | return
39 | qdel(src)
40 |
41 | /datum/component/area_sound_manager/proc/handle_removal(datum/source)
42 | SIGNAL_HANDLER
43 | qdel(src)
44 |
45 | /datum/component/area_sound_manager/proc/handle_change(datum/source)
46 | SIGNAL_HANDLER
47 | change_the_track()
48 |
49 | /datum/component/area_sound_manager/proc/change_the_track(skip_start = FALSE)
50 | var/time_remaining = 0
51 |
52 | if(our_loop)
53 | var/our_id = our_loop.timerid || timerid
54 | if(our_id)
55 | time_remaining = timeleft(our_id, SSsound_loops) || 0
56 | //Time left will sometimes return negative values, just ignore them and start a new sound loop now
57 | time_remaining = max(time_remaining, 0)
58 | QDEL_NULL(our_loop)
59 |
60 | var/area/our_area = get_area(parent)
61 | var/new_loop_type = area_to_looping_type[our_area]
62 | if(!new_loop_type)
63 | return
64 |
65 | our_loop = new new_loop_type(parent, FALSE, TRUE, skip_start)
66 |
67 | //If we're still playing, wait a bit before changing the sound so we don't double up
68 | if(time_remaining)
69 | timerid = addtimer(CALLBACK(src, .proc/start_looping_sound), time_remaining, TIMER_UNIQUE | TIMER_CLIENT_TIME | TIMER_STOPPABLE | TIMER_NO_HASH_WAIT | TIMER_DELETE_ME, SSsound_loops)
70 | return
71 | timerid = null
72 | our_loop.start()
73 |
74 | /datum/component/area_sound_manager/proc/start_looping_sound()
75 | timerid = null
76 | if(our_loop)
77 | our_loop.start()
78 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/docker.sample:
--------------------------------------------------------------------------------
1 | # syntax=docker/dockerfile:1
2 | FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
3 | WORKDIR /app
4 |
5 | # Copy csproj and restore as distinct layers
6 | COPY *.csproj ./
7 | RUN dotnet restore
8 |
9 | # Copy everything else and build
10 | COPY ../engine/examples ./
11 | RUN dotnet publish -c Release -o out
12 |
13 | # Build runtime image
14 | FROM mcr.microsoft.com/dotnet/aspnet:3.1
15 | WORKDIR /app
16 | COPY --from=build-env /app/out .
17 | ENTRYPOINT ["dotnet", "aspnetapp.dll"]
18 |
19 | # From https://docs.docker.com/samples/dotnetcore/
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/elixir.sample:
--------------------------------------------------------------------------------
1 | # module_name.ex
2 | defmodule ModuleName do
3 | def hello do
4 | IO.puts "Hello World"
5 | end
6 | end
7 |
8 | # From https://elixir-lang.org/crash-course.html#elixir
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/elm.sample:
--------------------------------------------------------------------------------
1 | module Main exposing (..)
2 |
3 | -- Press buttons to increment and decrement a counter.
4 | --
5 | -- Read how it works:
6 | -- https://guide.elm-lang.org/architecture/buttons.html
7 | --
8 |
9 |
10 | import Browser
11 | import Html exposing (Html, button, div, text)
12 | import Html.Events exposing (onClick)
13 |
14 |
15 |
16 | -- MAIN
17 |
18 |
19 | main =
20 | Browser.sandbox { init = init, update = update, view = view }
21 |
22 |
23 |
24 | -- MODEL
25 |
26 |
27 | type alias Model = Int
28 |
29 |
30 | init : Model
31 | init =
32 | 0
33 |
34 |
35 |
36 | -- UPDATE
37 |
38 |
39 | type Msg
40 | = Increment
41 | | Decrement
42 |
43 |
44 | update : Msg -> Model -> Model
45 | update msg model =
46 | case msg of
47 | Increment ->
48 | model + 1
49 |
50 | Decrement ->
51 | model - 1
52 |
53 |
54 |
55 | -- VIEW
56 |
57 |
58 | view : Model -> Html Msg
59 | view model =
60 | div []
61 | [ button [ onClick Decrement ] [ text "-" ]
62 | , div [] [ text (String.fromInt model) ]
63 | , button [ onClick Increment ] [ text "+" ]
64 | ]
65 |
66 | -- From https://elm-lang.org/examples/buttons
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/erb.sample:
--------------------------------------------------------------------------------
1 | require "erb"
2 |
3 | # Build template data class.
4 | class Product
5 | def initialize( code, name, desc, cost )
6 | @code = code
7 | @name = name
8 | @desc = desc
9 | @cost = cost
10 |
11 | @features = [ ]
12 | end
13 |
14 | def add_feature( feature )
15 | @features << feature
16 | end
17 |
18 | # Support templating of member data.
19 | def get_binding
20 | binding
21 | end
22 |
23 | # ...
24 | end
25 |
26 | # Create template.
27 | template = %{
28 |
29 | Ruby Toys -- <%= @name %>
30 |
31 |
32 | <%= @name %> (<%= @code %>)
33 | <%= @desc %>
34 |
35 |
36 | <% @features.each do |f| %>
37 | - <%= f %>
38 | <% end %>
39 |
40 |
41 |
42 | <% if @cost < 10 %>
43 | Only <%= @cost %>!!!
44 | <% else %>
45 | Call for a price, today!
46 | <% end %>
47 |
48 |
49 |
50 |
51 | }.gsub(/^ /, '')
52 |
53 | rhtml = ERB.new(template)
54 |
55 | # Set up template data.
56 | toy = Product.new( "TZ-1002",
57 | "Rubysapien",
58 | "Geek's Best Friend! Responds to Ruby commands...",
59 | 999.95 )
60 | toy.add_feature("Listens for verbal commands in the Ruby language!")
61 | toy.add_feature("Ignores Perl, Java, and all C variants.")
62 | toy.add_feature("Karate-Chop Action!!!")
63 | toy.add_feature("Matz signature on left leg.")
64 | toy.add_feature("Gem studded eyes... Rubies, of course!")
65 |
66 | # Produce result.
67 | rhtml.run(toy.get_binding)
68 |
69 | # From https://docs.ruby-lang.org/en/2.3.0/ERB.html#class-ERB-label-Examples
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/erlang.sample:
--------------------------------------------------------------------------------
1 | %% File: person.hrl
2 |
3 | %%-----------------------------------------------------------
4 | %% Data Type: person
5 | %% where:
6 | %% name: A string (default is undefined).
7 | %% age: An integer (default is undefined).
8 | %% phone: A list of integers (default is []).
9 | %% dict: A dictionary containing various information
10 | %% about the person.
11 | %% A {Key, Value} list (default is the empty list).
12 | %%------------------------------------------------------------
13 | -record(person, {name, age, phone = [], dict = []}).
14 |
15 | -module(person).
16 | -include("person.hrl").
17 | -compile(export_all). % For test purposes only.
18 |
19 | %% This creates an instance of a person.
20 | %% Note: The phone number is not supplied so the
21 | %% default value [] will be used.
22 |
23 | make_hacker_without_phone(Name, Age) ->
24 | #person{name = Name, age = Age,
25 | dict = [{computer_knowledge, excellent},
26 | {drinks, coke}]}.
27 |
28 | %% This demonstrates matching in arguments
29 |
30 | print(#person{name = Name, age = Age,
31 | phone = Phone, dict = Dict}) ->
32 | io:format("Name: ~s, Age: ~w, Phone: ~w ~n"
33 | "Dictionary: ~w.~n", [Name, Age, Phone, Dict]).
34 |
35 | %% Demonstrates type testing, selector, updating.
36 |
37 | birthday(P) when is_record(P, person) ->
38 | P#person{age = P#person.age + 1}.
39 |
40 | register_two_hackers() ->
41 | Hacker1 = make_hacker_without_phone("Joe", 29),
42 | OldHacker = birthday(Hacker1),
43 | % The central_register_server should have
44 | % an interface function for this.
45 | central_register_server ! {register_person, Hacker1},
46 | central_register_server ! {register_person,
47 | OldHacker#person{name = "Robert",
48 | phone = [0,8,3,2,4,5,3,1]}}.
49 |
50 | %% From https://erlang.org/doc/programming_examples/records.html#a-longer-example
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/fish.sample:
--------------------------------------------------------------------------------
1 | function fish_prompt
2 | # A simple prompt. Displays the current directory
3 | # (which fish stores in the $PWD variable)
4 | # and then a user symbol - a '►' for a normal user and a '#' for root.
5 | set -l user_char '►'
6 | if fish_is_root_user
7 | set user_char '#'
8 | end
9 |
10 | echo (set_color yellow)$PWD (set_color purple)$user_char
11 | end
12 |
13 | # From https://fishshell.com/docs/current/language.html#functions
14 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/fsharp.sample:
--------------------------------------------------------------------------------
1 | type Customer(firstName, middleInitial, lastName) =
2 | member this.FirstName = firstName
3 | member this.MiddleInitial = middleInitial
4 | member this.LastName = lastName
5 |
6 | member this.SayFullName() =
7 | $"{this.FirstName} {this.MiddleInitial} {this.LastName}"
8 |
9 | let customer = Customer("Emillia", "C", "Miller")
10 |
11 | printfn $"Hello, I'm {customer.SayFullName()}!"
12 |
13 | // From https://dotnet.microsoft.com/languages/fsharp
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/fsl.sample:
--------------------------------------------------------------------------------
1 |
2 | machine_name : "TCP/IP";
3 | machine_reference : "http://www.texample.net/tikz/examples/tcp-state-machine/";
4 | machine_version : 1.0.0;
5 |
6 | machine_author : "John Haugeland ";
7 | machine_license : MIT;
8 |
9 | jssm_version : >= 5.0.0;
10 |
11 |
12 |
13 | Closed 'Passive open' -> Listen;
14 | Closed 'Active Open / SYN' -> SynSent;
15 |
16 | Listen 'Close' -> Closed;
17 | Listen 'Send / SYN' -> SynSent;
18 | Listen 'SYN / SYN+ACK' -> SynRcvd;
19 |
20 | SynSent 'Close' -> Closed;
21 | SynSent 'SYN / SYN+ACK' -> SynRcvd;
22 | SynSent 'SYN+ACK / ACK' -> Established;
23 |
24 | SynRcvd 'Timeout / RST' -> Closed;
25 | SynRcvd 'Close / FIN' -> FinWait1;
26 | SynRcvd 'ACK' -> Established;
27 |
28 | Established 'Close / FIN' -> FinWait1;
29 | Established 'FIN / ACK' -> CloseWait;
30 |
31 | FinWait1 'FIN / ACK' -> Closing; // the source diagram has this action wrong
32 | FinWait1 'FIN+ACK / ACK' -> TimeWait;
33 | FinWait1 'ACK / Nothing' -> FinWait2; // see http://www.cs.odu.edu/~cs779/spring17/lectures/architecture_files/image009.jpg
34 |
35 | FinWait2 'FIN / ACK' -> TimeWait;
36 |
37 | Closing 'ACK' -> TimeWait;
38 |
39 | TimeWait 'Up to 2*MSL' -> Closed;
40 |
41 | CloseWait 'Close / FIN' -> LastAck;
42 |
43 | LastAck 'ACK' -> Closed;
44 |
45 |
46 |
47 | # From https://github.com/StoneCypher/jssm/blob/main/src/machines/linguist/tcp%20ip.fsl
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/glsl.sample:
--------------------------------------------------------------------------------
1 | #version 330
2 |
3 | const float PI = 3.1415926535897932384626433832795;
4 |
5 | const float waveLength = 20.0;
6 | const float waveAmplitude = 1.0;
7 | const float specularReflectivity = 0.4;
8 | const float shineDamper = 20.0;
9 |
10 | layout(location = 0) in vec2 in_position;
11 | layout(location = 1) in vec4 in_indicators;
12 |
13 | out vec4 pass_clipSpaceGrid;
14 | out vec4 pass_clipSpaceReal;
15 | out vec3 pass_normal;
16 | out vec3 pass_toCameraVector;
17 | out vec3 pass_specular;
18 | out vec3 pass_diffuse;
19 |
20 | uniform float height;
21 | uniform vec3 cameraPos;
22 | uniform float waveTime;
23 |
24 | uniform vec3 lightDirection;
25 | uniform vec3 lightColour;
26 | uniform vec2 lightBias;
27 |
28 | uniform mat4 projectionViewMatrix;
29 |
30 | vec3 calcSpecularLighting(vec3 toCamVector, vec3 toLightVector, vec3 normal){
31 | vec3 reflectedLightDirection = reflect(-toLightVector, normal);
32 | float specularFactor = dot(reflectedLightDirection , toCamVector);
33 | specularFactor = max(specularFactor,0.0);
34 | specularFactor = pow(specularFactor, shineDamper);
35 | return specularFactor * specularReflectivity * lightColour;
36 | }
37 |
38 | vec3 calculateDiffuseLighting(vec3 toLightVector, vec3 normal){
39 | float brightness = max(dot(toLightVector, normal), 0.0);
40 | return (lightColour * lightBias.x) + (brightness * lightColour * lightBias.y);
41 | }
42 |
43 | vec3 calcNormal(vec3 vertex0, vec3 vertex1, vec3 vertex2){
44 | vec3 tangent = vertex1 - vertex0;
45 | vec3 bitangent = vertex2 - vertex0;
46 | return normalize(cross(tangent, bitangent));
47 | }
48 |
49 | float generateOffset(float x, float z){
50 | float radiansX = (x / waveLength + waveTime) * 2.0 * PI;
51 | float radiansZ = (z / waveLength + waveTime) * 2.0 * PI;
52 | return waveAmplitude * 0.5 * (sin(radiansZ) + cos(radiansX));
53 | }
54 |
55 | vec3 applyDistortion(vec3 vertex){
56 | float xDistortion = generateOffset(vertex.x, vertex.z);
57 | float yDistortion = generateOffset(vertex.x, vertex.z);
58 | float zDistortion = generateOffset(vertex.x, vertex.z);
59 | return vertex + vec3(xDistortion, yDistortion, zDistortion);
60 | }
61 |
62 | void main(void){
63 |
64 | vec3 currentVertex = vec3(in_position.x, height, in_position.y);
65 | vec3 vertex1 = currentVertex + vec3(in_indicators.x, 0.0, in_indicators.y);
66 | vec3 vertex2 = currentVertex + vec3(in_indicators.z, 0.0, in_indicators.w);
67 |
68 | pass_clipSpaceGrid = projectionViewMatrix * vec4(currentVertex, 1.0);
69 |
70 | currentVertex = applyDistortion(currentVertex);
71 | vertex1 = applyDistortion(vertex1);
72 | vertex2 = applyDistortion(vertex2);
73 |
74 | pass_normal = calcNormal(currentVertex, vertex1, vertex2);
75 |
76 | pass_clipSpaceReal = projectionViewMatrix * vec4(currentVertex, 1.0);
77 | gl_Position = pass_clipSpaceReal;
78 |
79 | pass_toCameraVector = normalize(cameraPos - currentVertex);
80 |
81 | vec3 toLightVector = -normalize(lightDirection);
82 | pass_specular = calcSpecularLighting(pass_toCameraVector, toLightVector, pass_normal);
83 | pass_diffuse = calculateDiffuseLighting(toLightVector, pass_normal);
84 | }
85 |
86 | // From https://github.com/TheThinMatrix/WaterStep10/blob/master/water/waterRendering/waterVertex.glsl
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/go.sample:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "net/http"
7 | )
8 |
9 | func handler(w http.ResponseWriter, r *http.Request) {
10 | fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
11 | }
12 |
13 | func main() {
14 | http.HandleFunc("/", handler)
15 | log.Fatal(http.ListenAndServe(":8080", nil))
16 | }
17 |
18 | // From https://golang.org/doc/articles/wiki/#tmp_3
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/html.sample:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
…
23 |
…
24 |
…
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/java.sample:
--------------------------------------------------------------------------------
1 | public class HelloWorld {
2 |
3 | public static void main(String[] args) {
4 | // Prints "Hello, World" to the terminal window.
5 | System.out.println("Hello, World");
6 | }
7 |
8 | }
9 |
10 | // From https://introcs.cs.princeton.edu/java/11hello/HelloWorld.java.html
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/javascript.sample:
--------------------------------------------------------------------------------
1 | // posts will be populated at build time by getStaticProps()
2 | function Blog({ posts }) {
3 | return (
4 |
5 | {posts.map((post) => (
6 | - {post.title}
7 | ))}
8 |
9 | )
10 | }
11 |
12 | // This function gets called at build time on server-side.
13 | export async function getStaticProps() {
14 | const res = await fetch('https://.../posts')
15 | const posts = await res.json()
16 |
17 | return {
18 | props: {
19 | posts
20 | }
21 | }
22 | }
23 |
24 | export default Blog
25 |
26 | // From https://nextjs.org/docs/basic-features/data-fetching
27 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/jssm.sample:
--------------------------------------------------------------------------------
1 |
2 | machine_name : "BGP";
3 | machine_reference : "http://www.inetdaemon.com/tutorials/internet/ip/routing/bgp/operation/finite_state_model.shtml";
4 | machine_version : 1.0.0;
5 |
6 | machine_author : "John Haugeland ";
7 | machine_license : MIT;
8 |
9 | jssm_version : >= 5.0.0;
10 |
11 |
12 |
13 | Idle -> [Idle Connect];
14 | Connect -> [Idle Connect OpenSent Active];
15 | Active -> [Idle Connect OpenSent Active];
16 | OpenSent -> [Idle Active OpenConfirm];
17 | OpenConfirm -> [Idle OpenSent OpenConfirm Established];
18 | Established -> [Idle Established];
19 |
20 |
21 |
22 | # from https://github.com/StoneCypher/jssm/blob/main/src/machines/linguist/bgp.fsl
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/liquid.sample:
--------------------------------------------------------------------------------
1 | Recommended Products
2 |
13 |
14 | {%- comment -%} From https://www.codeshopify.com/blog_posts/related-products-with-product_list-sections-metafields {%- endcomment -%}
15 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/prisma.sample:
--------------------------------------------------------------------------------
1 | datasource db {
2 | provider = "postgresql"
3 | url = env("DATABASE_URL")
4 | }
5 |
6 | generator client {
7 | provider = "prisma-client-js"
8 | }
9 |
10 | /// Post including an author and content.
11 | model Post {
12 | id Int @default(autoincrement()) @id
13 | content String?
14 | published Boolean @default(false)
15 | author User? @relation(fields: [authorId], references: [id])
16 | authorId Int?
17 | }
18 |
19 | // Documentation for this model.
20 | model User {
21 | id Int @default(autoincrement()) @id
22 | email String @unique
23 | name String?
24 | posts Post[]
25 | specialName UserName
26 | test Test
27 | }
28 |
29 | /// This is an enum specifying the UserName.
30 | enum UserName {
31 | Fred
32 | Eric
33 | }
34 |
35 | // This is a test enum.
36 | enum Test {
37 | TestUno
38 | TestDue
39 | }
40 |
41 | // taken from https://github.com/prisma/language-tools/blob/master/packages/vscode/testFixture/hover.prisma
42 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/python.sample:
--------------------------------------------------------------------------------
1 | def fib(n): # write Fibonacci series up to n
2 | """Print a Fibonacci series up to n."""
3 | a, b = 0, 1
4 | while a < n:
5 | print(a, end=' ')
6 | a, b = b, a+b
7 | print()
8 |
9 | # Now call the function we just defined:
10 | fib(2000)
11 |
12 | # From https://docs.python.org/3/tutorial/controlflow.html#defining-functions
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/rel.sample:
--------------------------------------------------------------------------------
1 | module person
2 | def ssn = 123-45-6789
3 | module name
4 | def first = "John"
5 | def middle = "Q"
6 | def last = "Public"
7 | end
8 | module birth
9 | def city = "Pittsburg"
10 | def state = "PA"
11 | def country = "USA"
12 | def date = parse_date["2000-01-01", "Y-m-d"]
13 | end
14 | end
15 |
16 | module mymodule
17 | def R = {1; 2}
18 | ic {count[R] = 2}
19 | end
20 |
21 | @inline
22 | module my_stats[R]
23 | def my_minmax = (min[R], max[R])
24 | def my_mean = mean[R]
25 | def my_median = median[R]
26 | end
27 |
28 | @inline
29 | module BipartiteGraph[M, N]
30 | def node = M; N
31 | def edge = M, N
32 | end
33 |
34 | @inline
35 | module CycleGraph[N]
36 | def node = N
37 | def edge(a in N, b in N) =
38 | sort[N](x, a)
39 | and sort[N](y, b)
40 | and y = x%count[N] + 1
41 | from x, y
42 | end
43 |
44 | @inline
45 | module GraphProperties[G]
46 | def outdegree[v in G:node] = count[v1 : G:edge(v, v1)] <++ 0
47 | def indegree[v in G:node] = count[v1 : G:edge(v1, v)] <++ 0
48 | def edge_count = count[G:edge] <++ 0
49 | end
50 |
51 | def cg = CompleteGraph[range[1 ,5, 1]]
52 | def cg_props = GraphProperties[cg]
53 |
54 | def bg = BipartiteGraph[{1; 2}, {3; 4; 5}]
55 | def bg_props = GraphProperties[bg]
56 |
57 | def cycleg = CycleGraph[{"a"; "b"; "c"; "d" ; "e"}]
58 | def cycleg_props = GraphProperties[cycleg]
59 |
60 | module output
61 | def complete_edge_count = cg_props:edge_count
62 | def bipartite_edge_count = bg_props:edge_count
63 | def cycle_edge_count = cycleg_props:edge_count
64 | end
65 |
66 | # From https://docs.relational.ai/rel/concepts/modules/
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/ruby.sample:
--------------------------------------------------------------------------------
1 | class LotteryTicket
2 |
3 | NUMERIC_RANGE = 1..25
4 |
5 | attr_reader :picks, :purchased
6 |
7 | def initialize( *picks )
8 | if picks.length != 3
9 | raise ArgumentError, "three numbers must be picked"
10 | elsif picks.uniq.length != 3
11 | raise ArgumentError, "the three picks must be different numbers"
12 | elsif picks.detect { |p| not NUMERIC_RANGE === p }
13 | raise ArgumentError, "the three picks must be numbers between 1 and 25"
14 | end
15 | @picks = picks
16 | @purchased = Time.now
17 | end
18 |
19 | end
20 |
21 | # From https://poignant.guide/book/chapter-5.html
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/sparql.sample:
--------------------------------------------------------------------------------
1 | PREFIX foaf:
2 | SELECT ?name (COUNT(?friend) AS ?count)
3 | WHERE {
4 | ?person foaf:name ?name .
5 | ?person foaf:knows ?friend .
6 | } GROUP BY ?person ?name
7 |
8 | # From https://www.w3.org/TR/sparql11-overview/#sparql11-query
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/stata.sample:
--------------------------------------------------------------------------------
1 | capture program drop exit_message
2 | program exit_message
3 | syntax, rc(int) progname(str) start_time(str) [CAPture]
4 | local end_time "$S_TIME $S_DATE"
5 | local time "Start: `start_time'" _n(1) "End: `end_time'"
6 | di ""
7 | if (`rc' == 0) {
8 | di "End: $S_TIME $S_DATE"
9 | local paux ran
10 | local message "`progname' finished running" _n(2) "`time'"
11 | local subject "`progname' `paux'"
12 | }
13 | else if ("`capture'" == "") {
14 | di "WARNING: $S_TIME $S_DATE"
15 | local paux ran with non-0 exit status
16 | local message "`progname' ran but Stata gave error code r(`rc')" _n(2) "`time'"
17 | local subject "`progname' `paux'"
18 | }
19 | else {
20 | di "ERROR: $S_TIME $S_DATE"
21 | local paux ran with errors
22 | local message "`progname' stopped with error code r(`rc')" _n(2) "`time'"
23 | local subject "`progname' `paux'"
24 | }
25 | di "`subject'"
26 | di ""
27 | di "`message'"
28 | end
29 |
30 | * From https://github.com/mcaceresb/stata-gtools/blob/fad519ef0454936d450802ac732728ba953957ac/src/test/gtools_tests.do
31 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/tasl.sample:
--------------------------------------------------------------------------------
1 | # This is a tasl schema!
2 | namespace s http://schema.org/
3 |
4 | # classes are like tables, except they
5 | # can be arbitrary algebraic data types,
6 | # not just columns of primitives.
7 | class s:Person :: {
8 | s:name -> string
9 | s:email -> ? uri
10 | s:spouse -> ? * s:Person
11 | s:gender -> [
12 | s:Male
13 | s:Female
14 | s:value <- string
15 | ]
16 | }
17 |
18 | # references are a primitive type that
19 | # point to other classes in the schema,
20 | # just like foreign keys.
21 | class s:Book :: {
22 | s:name -> string
23 | s:isbn -> uri
24 | s:author -> * s:Person
25 | }
26 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/tsx.sample:
--------------------------------------------------------------------------------
1 | // posts will be populated at build time by getStaticProps()
2 | function Blog({ posts }) {
3 | return (
4 |
5 | {posts.map((post) => (
6 | - {post.title}
7 | ))}
8 |
9 | )
10 | }
11 |
12 | // This function gets called at build time on server-side.
13 | export async function getStaticProps() {
14 | const res = await fetch('https://.../posts')
15 | const posts = await res.json()
16 |
17 | return {
18 | props: {
19 | posts
20 | }
21 | }
22 | }
23 |
24 | export default Blog
25 |
26 | // From https://nextjs.org/docs/basic-features/data-fetching
27 |
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/turtle.sample:
--------------------------------------------------------------------------------
1 | @prefix foaf: .
2 | @prefix rdfs: .
3 |
4 | a foaf:Person .
5 | foaf:name "Alice" .
6 | foaf:mbox .
7 | foaf:knows .
8 | foaf:knows .
9 | foaf:name "Bob" .
10 | foaf:knows .
11 | foaf:knows .
12 | foaf:name "Charlie" .
13 | foaf:knows .
14 | foaf:name "Snoopy"@en .
15 |
16 | # From https://www.w3.org/TR/sparql11-overview/#Example
--------------------------------------------------------------------------------
/Mod Manager/static/shiki/samples/zenscript.sample:
--------------------------------------------------------------------------------
1 | import crafttweaker.api.BracketHandlers;
2 |
3 | val air = ;
4 | val diamond = ;
5 | var woodTypes = ["oak","spruce","birch","jungle","acacia","dark_oak"];
6 |
7 | for name in woodTypes {
8 | val thing = BracketHandlers.getItem("minecraft:" + name + "_planks");
9 | craftingTable.addShaped(name + "_diamond", diamond, [[air, thing], [thing, air]]);
10 | }
11 |
12 | function checkLeapYear(year as int) as bool {
13 | if(year % 4 == 0) {
14 | if(year % 100 == 0) {
15 | if(year % 400 == 0) {
16 | return true;
17 | } else {
18 | return false;
19 | }
20 | } else {
21 | return true;
22 | }
23 | } else {
24 | return false;
25 | }
26 | }
27 |
28 | print("Is 2000 a leap year: " ~ checkLeapYear(2000));
29 | print("Is 2004 a leap year: " ~ checkLeapYear(2004));
30 | print("Is 2100 a leap year: " ~ checkLeapYear(2100));
31 | print("Is 2012 a leap year: " ~ checkLeapYear(2012));
32 |
33 |
34 | //Note: this is a cleaner way
35 | function checkLeapYear2(year as int) as bool {
36 | return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
37 | }
38 |
39 | print("Is 2000 a leap year (2nd function): " ~ checkLeapYear2(2000));
40 | print("Is 2004 a leap year (2nd function): " ~ checkLeapYear2(2004));
41 | print("Is 2100 a leap year (2nd function): " ~ checkLeapYear2(2100));
42 | print("Is 2012 a leap year (2nd function): " ~ checkLeapYear2(2012));
43 |
44 | # From https://github.com/CraftTweaker/CraftTweaker-Examples
--------------------------------------------------------------------------------
/Mod Manager/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from "@sveltejs/adapter-static"
2 | import preprocess from "svelte-preprocess"
3 |
4 | /** @type {import("@sveltejs/kit").Config} */
5 | const config = {
6 | kit: {
7 | adapter: adapter({
8 | fallback: "index.html"
9 | })
10 | },
11 | preprocess: preprocess()
12 | }
13 |
14 | export default config
15 |
--------------------------------------------------------------------------------
/Mod Manager/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: ["./src/**/*.{html,svelte,js,ts}"],
3 | theme: {
4 | extend: {}
5 | },
6 | plugins: []
7 | }
8 |
--------------------------------------------------------------------------------
/Mod Manager/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "module": "esnext",
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "strict": true,
8 | "types": [
9 | "vite/client",
10 | "node"
11 | ],
12 | "typeRoots": [
13 | "node_modules/@types"
14 | ],
15 | "lib": [
16 | "ESNext"
17 | ],
18 | "importsNotUsedAsValues": "error",
19 | "isolatedModules": true,
20 | "sourceMap": true,
21 | "esModuleInterop": true,
22 | "skipLibCheck": true,
23 | "forceConsistentCasingInFileNames": true,
24 | "baseUrl": ".",
25 | "allowJs": true,
26 | "checkJs": false,
27 | "paths": {
28 | "$lib": [
29 | "src/lib"
30 | ],
31 | "$lib/*": [
32 | "src/lib/*"
33 | ],
34 | "$app/*": [
35 | ".svelte/dev/runtime/app/*",
36 | ".svelte/build/runtime/app/*"
37 | ]
38 | },
39 | "resolveJsonModule": true
40 | },
41 | "include": [
42 | "src/**/*.d.ts",
43 | "src/**/*.ts",
44 | "src/**/*.svelte",
45 | "src/electron.js"
46 | ]
47 | }
--------------------------------------------------------------------------------
/Mod Manager/vite.config.js:
--------------------------------------------------------------------------------
1 | import { builtinModules } from "module"
2 | import { sveltekit } from "@sveltejs/kit/vite"
3 |
4 | /** @type {import('vite').UserConfig} */
5 | const config = {
6 | plugins: [sveltekit()],
7 | build: {
8 | rollupOptions: {
9 | external: [...builtinModules.flatMap((p) => [p, `node:${p}`])]
10 | }
11 | }
12 | }
13 |
14 | export default config
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # simple-mod-framework
2 | A mod framework for HITMAN 3 that allows the automatic synthesis of mods from source files.
3 |
4 | You can download an artifact (nightly) version of the framework from [here](https://nightly.link/atampy25/simple-mod-framework/workflows/artifact/main/Output.zip).
--------------------------------------------------------------------------------
/Third-Party/7z-LICENSE:
--------------------------------------------------------------------------------
1 | 7-Zip
2 | ~~~~~
3 | License for use and distribution
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | 7-Zip Copyright (C) 1999-2022 Igor Pavlov.
7 |
8 | The licenses for files are:
9 |
10 | 1) 7z.dll:
11 | - The "GNU LGPL" as main license for most of the code
12 | - The "GNU LGPL" with "unRAR license restriction" for some code
13 | - The "BSD 3-clause License" for some code
14 | 2) All other files: the "GNU LGPL".
15 |
16 | Redistributions in binary form must reproduce related license information from this file.
17 |
18 | Note:
19 | You can use 7-Zip on any computer, including a computer in a commercial
20 | organization. You don't need to register or pay for 7-Zip.
21 |
22 |
23 | GNU LGPL information
24 | --------------------
25 |
26 | This library is free software; you can redistribute it and/or
27 | modify it under the terms of the GNU Lesser General Public
28 | License as published by the Free Software Foundation; either
29 | version 2.1 of the License, or (at your option) any later version.
30 |
31 | This library is distributed in the hope that it will be useful,
32 | but WITHOUT ANY WARRANTY; without even the implied warranty of
33 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 | Lesser General Public License for more details.
35 |
36 | You can receive a copy of the GNU Lesser General Public License from
37 | http://www.gnu.org/
38 |
39 |
40 |
41 |
42 | BSD 3-clause License
43 | --------------------
44 |
45 | The "BSD 3-clause License" is used for the code in 7z.dll that implements LZFSE data decompression.
46 | That code was derived from the code in the "LZFSE compression library" developed by Apple Inc,
47 | that also uses the "BSD 3-clause License":
48 |
49 | ----
50 | Copyright (c) 2015-2016, Apple Inc. All rights reserved.
51 |
52 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
53 |
54 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
55 |
56 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
57 | in the documentation and/or other materials provided with the distribution.
58 |
59 | 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived
60 | from this software without specific prior written permission.
61 |
62 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
63 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
64 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
65 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 | ----
69 |
70 |
71 |
72 |
73 | unRAR license restriction
74 | -------------------------
75 |
76 | The decompression engine for RAR archives was developed using source
77 | code of unRAR program.
78 | All copyrights to original unRAR code are owned by Alexander Roshal.
79 |
80 | The license for original unRAR code has the following restriction:
81 |
82 | The unRAR sources cannot be used to re-create the RAR compression algorithm,
83 | which is proprietary. Distribution of modified unRAR sources in separate form
84 | or as a part of other software is permitted, provided that it is clearly
85 | stated in the documentation and source comments that the code may
86 | not be used to develop a RAR (WinRAR) compatible archiver.
87 |
88 |
89 | --
90 | Igor Pavlov
91 |
--------------------------------------------------------------------------------
/Third-Party/7z.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/7z.dll
--------------------------------------------------------------------------------
/Third-Party/7z.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/7z.exe
--------------------------------------------------------------------------------
/Third-Party/HMLanguageTools.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/HMLanguageTools.exe
--------------------------------------------------------------------------------
/Third-Party/HMTextureTools.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/HMTextureTools.exe
--------------------------------------------------------------------------------
/Third-Party/OREStool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/OREStool.exe
--------------------------------------------------------------------------------
/Third-Party/TonyTools-LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021+ Anthony Fuller
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Third-Party/h6xtea.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/h6xtea.exe
--------------------------------------------------------------------------------
/Third-Party/quickentity-3.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/quickentity-3.exe
--------------------------------------------------------------------------------
/Third-Party/quickentity-rs.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/quickentity-rs.exe
--------------------------------------------------------------------------------
/Third-Party/xdelta3-LICENSE:
--------------------------------------------------------------------------------
1 | Licensed under the Apache License, Version 2.0 (the "License");
2 | you may not use this file except in compliance with the License.
3 | You may obtain a copy of the License at
4 |
5 | http://www.apache.org/licenses/LICENSE-2.0
6 |
7 | Unless required by applicable law or agreed to in writing, software
8 | distributed under the License is distributed on an "AS IS" BASIS,
9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | See the License for the specific language governing permissions and
11 | limitations under the License.
--------------------------------------------------------------------------------
/Third-Party/xdelta3.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/Third-Party/xdelta3.exe
--------------------------------------------------------------------------------
/cleanPackageDefinition.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/cleanPackageDefinition.txt
--------------------------------------------------------------------------------
/cleanThumbs.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atampy25/simple-mod-framework/6c4bdabfa8bb17323c8c6ccb61c0f2e4b78c7214/cleanThumbs.dat
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | runtimePath: 'C:\\Users\\User\\Documents\\Apps\\Games\\Epic Games\\HITMAN3\\Runtime',
3 | skipIntro: true,
4 | outputToSeparateDirectory: true,
5 | loadOrder: [],
6 | modOptions: {},
7 | outputConfigToAppDataOnDeploy: true
8 | }
--------------------------------------------------------------------------------
/docs/Command Line Arguments.md:
--------------------------------------------------------------------------------
1 | `Deploy.exe` accepts three command line arguments:
2 | ```powershell
3 | .\Deploy --useConsoleLogging # Whether to use Node.js console logging instead of the default fancy logging
4 | .\Deploy --pauseAfterLogging # Whether to pause execution after each log entry
5 | .\Deploy --doNotPause # Whether to never pause after errors
6 | .\Deploy --logLevel verbose --logLevel debug --logLevel info --logLevel warn --logLevel error # The log levels to enable
7 | ```
8 |
9 | These arguments can be mixed together, but note that console logging does not respect set log levels, and will always log the default levels (`debug` onwards).
--------------------------------------------------------------------------------
/docs/Config.md:
--------------------------------------------------------------------------------
1 | The config.json file looks like this:
2 | ```jsonc
3 | {
4 | "runtimePath": "..\\Runtime",
5 | "retailPath": "..\\Retail",
6 | "skipIntro": true,
7 | "outputToSeparateDirectory": false,
8 | "loadOrder": [],
9 | "modOptions": {
10 | "Atampy26.RealisticAI": ["Normal"]
11 | },
12 | "outputConfigToAppDataOnDeploy": true
13 | }
14 | ```
15 |
16 | Load order is top-first - a mod lower in the load order will load later and thus overwrite mods further up.
17 |
18 | The `skipIntro` key will automatically patch the game to skip the intro and load directly into the "Press ENTER" screen.
19 |
20 | The `runtimePath` key must be configured to the location of your Runtime folder (it defaults to `..\Runtime`, so the framework is placed in `HITMAN3\any folder`). This is automatically set to `..\Retail\Runtime` on the Microsoft platform. Use double backslashes (`\\`).
21 |
22 | The `retailPath` key must be configured to the location of your Retail folder (it defaults to `..\Retail`, so the framework is placed in `HITMAN3\any folder`). Use double backslashes (`\\`).
23 |
24 | The `modOptions` key configures enabled mod options.
25 |
26 | The `outputToSeparateDirectory` key will change the output directory from the runtime path to a folder called `Output`. This is useful if you need to copy RPKGs, like if you want to play with mods on Linux.
27 |
28 | The `outputConfigToAppDataOnDeploy` key will automatically output the effective config to `%localappdata%\Simple Mod Framework` at the end of a deploy. This is used for interfacing with other programs.
--------------------------------------------------------------------------------
/docs/Folder Structure.md:
--------------------------------------------------------------------------------
1 | The folder structure for a mod looks like this:
2 | ```
3 | MyAmazingMod/
4 | ├─ manifest.json
5 | ├─ content folder/
6 | │ ├─ chunk0/
7 | │ │ ├─ Vamprism.contract.json
8 | │ │ ├─ repo edits.repository.json
9 | │ │ ├─ 0098B17A37DE.GFXF
10 | │ │ ├─ GlobalDataPatch.entity.patch.json
11 | │ ├─ chunk1/
12 | │ │ ├─ ...
13 | ├─ blobs folder/
14 | │ ├─ images/
15 | │ │ ├─ unlockables/
16 | │ │ │ ├─ theBestUnlockable.jpg
17 | ```
18 | `MyAmazingMod` can be placed in the load order.
19 |
20 | The manifest.json controls what the content and blobs folders must be named.
21 |
22 | The content folder contains chunk folders, which contain files (and folders, the chunk folder is recursively checked for all files). These files can be raw files or special files. The current special file types are:
23 |
24 | | **File type** | **Contents** |
25 | |-----------------------|------------------------------------------------------------------------------|
26 | | `entity.json` | A QuickEntity JSON file that will replace the entity it targets |
27 | | `entity.patch.json` | A QuickEntity patch JSON that will patch the entity it targets |
28 | | `unlockables.json` | Unlockables to be put in the unlockables ORES |
29 | | `repository.json` | Repository items to be placed in the repository |
30 | | `contract.json` | A contract that will be added to the contracts ORES |
31 | | `JSON.patch.json` | An RFC6902 JSON patch that will be applied to the hash the file specifies |
32 | | `material.json` | An RPKG tool material JSON that will replace/add the targeted material |
33 | | `clng.json` | A HMLanguages CLNG JSON that will replace/add the targeted file |
34 | | `ditl.json` | A HMLanguages DITL JSON that will replace/add the targeted file |
35 | | `dlge.json` | A HMLanguages DLGE JSON that will replace/add the targeted file |
36 | | `locr.json` | A HMLanguages LOCR JSON that will replace/add the targeted file |
37 | | `rtlv.json` | A HMLanguages RTLV JSON that will replace/add the targeted file |
38 | | `texture.tga` | A TGA to rebuild into a game texture (TEXT only or TEXT and TEXD) |
39 | | `sfx.wem` | A Wwise sound effect to patch a WWEV file with |
40 | | `delta` | A VCDiff delta file to patch the specified file with |
41 |
42 | The names of special files do not matter - it is their extensions that do, **except for texture.tga, sfx.wem and delta files**. Raw files, which any non-special file is, are placed directly into the built RPKG and so must be named like usual.
43 |
44 | *Note: these are file types, not file names - instead of adding "repository.json" to your mod, add "edits.repository.json".*
45 |
46 | If a chunk meta file named chunkX.meta is placed at the top level of the chunk folder, the framework will overwrite the chunk with the content in the content folder. This allows for the creation of new chunks. Make sure you don't do this if you're trying to patch an existing chunk, or you may overwrite your game files!
47 |
48 | The blobs folder contains blobs, which follow the same filepath as the folder structure and which will be placed into the blobs ORES. In the example, `theBestUnlockable.jpg` would be assigned the path `images/unlockables/theBestUnlockable.jpg`.
--------------------------------------------------------------------------------
/docs/Index.md:
--------------------------------------------------------------------------------
1 | [Command Line Arguments](Command%20Line%20Arguments.md)
2 |
3 | [Config](Config.md)
4 |
5 | [Folder Structure](Folder%20Structure.md)
6 |
7 | [Making a Mod](Making%20a%20Mod.md)
8 |
9 | [Manifest](Manifest.md)
10 |
11 | [Mod Manager](Mod%20Manager.md)
12 |
13 | [Mod Updates](Mod%20Updates.md)
14 |
15 | [RPKG Mods](RPKG%20Mods.md)
16 |
17 | [Special File Types](Special%20File%20Types.md)
18 |
19 | [Scripts](Scripts.md)
--------------------------------------------------------------------------------
/docs/Mod Manager.md:
--------------------------------------------------------------------------------
1 | The framework comes with a GUI mod manager - you're looking at it. It is capable of managing deploy order, importing RPKG and framework.zip mods and helping in the creation of your own mods.
2 |
3 | ## Framework ZIP files
4 | A framework ZIP file is extracted directly to the `Mods` folder. For example, if you are packaging `MyAmazingMod`:
5 | ```
6 | MyAmazingMod/
7 | ├─ manifest.json
8 | ├─ content folder/
9 | │ ├─ chunk0/
10 | │ │ ├─ Vamprism.contract.json
11 | │ │ ├─ 0098B17A37DE.GFXF
12 | │ │ ├─ GlobalDataPatch.entity.patch.json
13 | │ ├─ chunk1/
14 | │ │ ├─ ...
15 | ├─ blobs folder/
16 | │ ├─ images/
17 | │ │ ├─ unlockables/
18 | │ │ │ ├─ theBestUnlockable.jpg
19 | ```
20 | then your folder structure for the framework.zip file should look like this:
21 | ```
22 | MyAmazingMod.framework.zip
23 | ├─ MyAmazingMod/
24 | │ ├─ manifest.json
25 | │ ├─ ...
26 | ```
27 |
28 | In essence, **zip the folder, not its contents**. Bundling multiple modules through multiple folders isn't recommended - you should use mod options (see [Manifest](Manifest.md)).
29 |
30 | Alternative archive formats (including RAR and 7z) are supported, though ZIP is still usually the easiest for people to work with (and RAR is usually the worst). If your mod is big, though, distributing it as a 7z file is probably a good idea.
--------------------------------------------------------------------------------
/docs/Mod Updates.md:
--------------------------------------------------------------------------------
1 | Mods can automatically update themselves if an update link is provided; this will display an indicator in the Mod Manager whenever a mod has a new update and will allow the user to click a button to automatically download and install the new version.
2 |
3 | The easiest way of providing automatic updates is to use the mod template at `https://github.com/atampy25/smf-mod`, which will automatically configure and manage updates. In addition, using the template allows SMF to combine all new update changelogs together, while mods which don't use it will only show the latest changelog. For example, if a mod is updated to 1.1.0 with the message "- Add new feature" and updated to 1.2.0 with the message "- Improve existing feature", a user updating from 1.0.0 to 1.2.0 will only see "- Improve existing feature" and will be unaware of anything other than the latest message. If the mod uses the GitHub template, the user will instead see:
4 | - Add new feature
5 | - Improve existing feature
6 | which provides a better experience.
7 |
8 | Update manifests (static JSONs linked to in the manifest) have the following format:
9 | ```jsonc
10 | {
11 | "version": "1.0.1", // Your mod's current version (make sure it's even with the manifest's version) - make sure to use semantic versioning (Major.Minor.Patch)
12 | "changelog": "I made it better", // Changes since last version (if your version is 1.0.0 just write Initial release or something)
13 | "url": "https://hitman-resources.netlify.app/framework/updates/exampleMod.framework.zip" // The file that will be downloaded and extracted when updating the mod (the archive file for your mod)
14 | }
15 | ```
--------------------------------------------------------------------------------
/docs/RPKG Mods.md:
--------------------------------------------------------------------------------
1 | RPKG mods can be used with the framework easily, even if they lack some of the compatibility and user experience features the framework offers, like patching and manifest metadata.
2 |
3 | The folder structure for importing an RPKG mod looks like this:
4 | ```
5 | MyAmazingMod/
6 | ├─ chunk0/
7 | │ ├─ any filename.rpkg
8 | │ ├─ multiple files supported.rpkg
9 | ├─ chunk1/
10 | │ ├─ another file.rpkg
11 | ```
12 |
13 | `MyAmazingMod` can be placed in the load order.
14 |
15 | The GUI supports importing single RPKGs, and will automatically create this structure.
--------------------------------------------------------------------------------
/docs/Scripts.md:
--------------------------------------------------------------------------------
1 | The framework includes a system for augmenting deploys using TypeScript code. You won't need to use this unless you're doing something especially unique, or you're looking to automatically generate parts of your mod. Whatever the case, the scripting system lets you do anything you can do with just JSON and more.
2 |
3 | To create a mod script, you can add a `scripts` key to the top-level of your manifest or an option. The first element of the array is the entry point; this file should export the necessary functions. All other elements are transpiled but not directly used by the framework, and are optional; if you break up your scripts into multiple files, you'll need to add them here.
4 |
5 | ```jsonc
6 | {
7 | /* Paths to TypeScript files that can alter deployment of the mod.
8 | * The first item is considered to be the entry point; it must export the necessary functions.
9 | * Any additional files are transpiled but not used directly; they can be imported from the entry point. */
10 | "scripts": [
11 | "mod.ts", // entry point
12 | "helpers.ts", // helper
13 | "somethingElse.ts" // helper
14 | ]
15 | }
16 | ```
17 |
18 | Entry points should export three functions which are called by the framework: `analysis` (called during mod analysis; this is where you should auto-generate your mod), `beforeDeploy` (this is where anything load-order sensitive should happen) and `afterDeploy` (this is where you should clean things up).
19 |
20 | ```ts
21 | interface ModScript extends NodeModule {
22 | /** A function to run immediately after mod analysis - alter the deploy instruction to modify how the framework deploys the mod. */
23 | analysis(context: ModContext, modAPI: ModAPI): Promise
24 |
25 | /** A function that runs immediately before the mod deploy begins - a staging folder is created but the mod has not had anything deployed. */
26 | beforeDeploy(context: ModContext, modAPI: ModAPI): Promise
27 |
28 | /** A function that runs immediately after the mod deploy ends - the deploy instruction has been processed. */
29 | afterDeploy(context: ModContext, modAPI: ModAPI): Promise
30 |
31 | /** You must provide a caching policy for this script. It's used to ensure that changes in how your mod scripts function are properly accounted for when caching other files. Scripts themselves are never cached. */
32 | cachingPolicy: CachePolicy
33 | }
34 |
35 | interface CachePolicy {
36 | /** A list of hashes that your script may affect, alter, create or write in any way. */
37 | affected: string[]
38 | }
39 | ```
40 |
41 | These hooks are given two arguments, `ModContext` and `ModAPI`. The context contains information about the current deployment, as well as an assigned temporary folder for working with files and the path of the mod (for anything that should persist). The API contains functions for dealing with RPKG, logging, the shell, QuickEntity and a few other things.
42 |
43 | ## Best practices
44 | Make sure you use the assigned temporary folder for dealing with files; it's automatically cleared when your scripts complete and in the future could be used for other purposes.
45 |
46 | Instead of using child_process directly, you should use the `execCommand` function of the `ModAPI`. It automatically logs its execution, helping with debugging. Similarly, you should use the included RPKG wrapper functions instead of calling it yourself; the wrapper functions are usually faster than executing the EXE as they re-use the same instance, which keeps things loaded in memory.
47 |
48 | Try to use the framework's manifest features and special file types whenever possible instead of mod scripting - unlike mod scripting, they can be cached, and any changes or fixes made to them will require no intervention from you.
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simple-mod-framework",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "compiled/main.js",
6 | "dependencies": {
7 | "@sentry/node": "^7.29.0",
8 | "@sentry/tracing": "^7.29.0",
9 | "arg": "^5.0.2",
10 | "chalk": "^4.1.2",
11 | "clarify": "^2.1.0",
12 | "decimal.js": "^10.3.1",
13 | "eventemitter-asyncresource": "^1.0.0",
14 | "filtrex": "^3.0.0",
15 | "fs-extra": "^10.1.0",
16 | "hash-wasm": "^4.9.0",
17 | "hdr-histogram-js": "^3.0.0",
18 | "hdr-histogram-percentiles-obj": "^3.0.0",
19 | "json5": "^2.2.2",
20 | "klaw-sync": "^6.0.0",
21 | "lodash.isequal": "^4.5.0",
22 | "lodash.mergewith": "^4.6.2",
23 | "lossless-json": "^1.0.5",
24 | "luxon": "^3.0.1",
25 | "md5": "^2.3.0",
26 | "md5-file": "^5.0.0",
27 | "minimist": "^1.2.6",
28 | "promisify-child-process": "^4.1.1",
29 | "rfc6902": "^5.0.1",
30 | "semver": "^7.3.8",
31 | "tslib": "^2.4.0",
32 | "typescript": "^4.7.4"
33 | },
34 | "devDependencies": {
35 | "@types/fs-extra": "^9.0.13",
36 | "@types/klaw-sync": "^6.0.1",
37 | "@types/lodash.mergewith": "^4.6.7",
38 | "@types/lossless-json": "^1.0.1",
39 | "@types/luxon": "^3.0.0",
40 | "@types/md5": "^2.3.2",
41 | "@types/semver": "^7.3.13",
42 | "@typescript-eslint/eslint-plugin": "^5.33.0",
43 | "@typescript-eslint/parser": "^5.33.0",
44 | "eslint": "^8.31.0",
45 | "prettier": "^2.7.1",
46 | "prettier-eslint": "^15.0.1"
47 | },
48 | "scripts": {
49 | "test": "echo \"Error: no test specified\" && exit 1"
50 | },
51 | "bin": "compiled/main.js",
52 | "pkg": {
53 | "scripts": [
54 | "node_modules/piscina/dist/src/worker.js",
55 | "compiled/patchWorker.js"
56 | ]
57 | },
58 | "author": "Atampy26",
59 | "license": "LGPL-3.0-only"
60 | }
61 |
--------------------------------------------------------------------------------
/piscina/.taprc:
--------------------------------------------------------------------------------
1 | check-coverage: false
2 | color: true
3 | coverage: true
4 | coverage-report:
5 | - html
6 | - text
7 | jobs: 2
8 | no-browser: true
9 | test-env: TS_NODE_PROJECT=test/tsconfig.json
10 | test-ignore: $.
11 | test-regex: ((\/|^)(tests?|__tests?__)\/.*|\.(tests?|spec)|^\/?tests?)\.([mc]js|ts)$
12 | timeout: 60
13 | ts: true
14 |
--------------------------------------------------------------------------------
/piscina/dist/esm-wrapper.mjs:
--------------------------------------------------------------------------------
1 | import mod from "./src/index.js"
2 |
3 | export default mod
4 | export const Piscina = mod.Piscina
5 | export const isWorkerThread = mod.isWorkerThread
6 | export const move = mod.move
7 | export const queueOptionsSymbol = mod.queueOptionsSymbol
8 | export const transferableSymbol = mod.transferableSymbol
9 | export const valueSymbol = mod.valueSymbol
10 | export const version = mod.version
11 | export const workerData = mod.workerData
12 |
--------------------------------------------------------------------------------
/piscina/dist/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "piscina",
3 | "version": "3.1.0",
4 | "description": "A fast, efficient Node.js Worker Thread Pool implementation",
5 | "main": "./dist/src/index.js",
6 | "exports": {
7 | "import": "./dist/esm-wrapper.mjs",
8 | "require": "./dist/src/index.js"
9 | },
10 | "types": "./dist/src/index.d.ts",
11 | "scripts": {
12 | "build": "tsc && gen-esm-wrapper . dist/esm-wrapper.mjs",
13 | "lint": "standardx \"**/*.{ts,mjs,js,cjs}\" | snazzy",
14 | "test": "npm run lint && npm run build && npm run test-only",
15 | "test-only": "tap --ts",
16 | "prepack": "npm run build"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/piscinajs/piscina.git"
21 | },
22 | "keywords": [
23 | "fast",
24 | "worker threads",
25 | "thread pool",
26 | "wade wilson"
27 | ],
28 | "author": "James M Snell ",
29 | "contributors": [
30 | "Anna Henningsen ",
31 | "Matteo Collina "
32 | ],
33 | "license": "MIT",
34 | "devDependencies": {
35 | "@types/node": "^15.0.1",
36 | "@typescript-eslint/eslint-plugin": "^4.22.0",
37 | "@typescript-eslint/parser": "^4.22.0",
38 | "abort-controller": "^3.0.0",
39 | "concat-stream": "^2.0.0",
40 | "gen-esm-wrapper": "^1.1.1",
41 | "snazzy": "^9.0.0",
42 | "standardx": "^7.0.0",
43 | "tap": "^15.0.6",
44 | "ts-node": "^9.1.1",
45 | "typescript": "^4.2.4"
46 | },
47 | "dependencies": {
48 | "eventemitter-asyncresource": "^1.0.0",
49 | "hdr-histogram-js": "^2.0.1",
50 | "hdr-histogram-percentiles-obj": "^3.0.0"
51 | },
52 | "optionalDependencies": {
53 | "nice-napi": "^1.0.2"
54 | },
55 | "eslintConfig": {
56 | "rules": {
57 | "semi": [
58 | "error",
59 | "always"
60 | ],
61 | "no-unused-vars": "off",
62 | "no-use-before-define": "off",
63 | "no-unreachable-loop": "off",
64 | "no-dupe-class-members": "off",
65 | "@typescript-eslint/no-unused-vars": "error"
66 | },
67 | "globals": {
68 | "SharedArrayBuffer": true,
69 | "Atomics": true,
70 | "AbortController": true,
71 | "MessageChannel": true
72 | }
73 | },
74 | "standardx": {
75 | "parser": "@typescript-eslint/parser",
76 | "plugins": [
77 | "@typescript-eslint/eslint-plugin"
78 | ]
79 | },
80 | "bugs": {
81 | "url": "https://github.com/piscinajs/piscina/issues"
82 | },
83 | "homepage": "https://github.com/piscinajs/piscina#readme",
84 | "directories": {
85 | "example": "examples",
86 | "test": "test"
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/piscina/dist/src/common.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import type { MessagePort } from "worker_threads"
3 | export interface StartupMessage {
4 | filename: string | null
5 | name: string
6 | port: MessagePort
7 | sharedBuffer: Int32Array
8 | useAtomics: boolean
9 | niceIncrement: number
10 | }
11 | export interface RequestMessage {
12 | taskId: number
13 | task: any
14 | filename: string
15 | name: string
16 | }
17 | export interface ReadyMessage {
18 | ready: true
19 | }
20 | export interface ResponseMessage {
21 | taskId: number
22 | result: any
23 | error: Error | null
24 | }
25 | export declare const commonState: {
26 | isWorkerThread: boolean
27 | workerData: undefined
28 | }
29 | export declare const kTransferable: unique symbol
30 | export declare const kValue: unique symbol
31 | export declare const kQueueOptions: unique symbol
32 | export declare function isTransferable(value: any): boolean
33 | export declare function isMovable(value: any): boolean
34 | export declare function markMovable(value: object): void
35 | export interface Transferable {
36 | readonly [kTransferable]: object
37 | readonly [kValue]: object
38 | }
39 | export interface Task {
40 | readonly [kQueueOptions]: object | null
41 | }
42 | export interface TaskQueue {
43 | readonly size: number
44 | shift(): Task | null
45 | remove(task: Task): void
46 | push(task: Task): void
47 | }
48 | export declare function isTaskQueue(value: any): boolean
49 | export declare const kRequestCountField = 0
50 | export declare const kResponseCountField = 1
51 | export declare const kFieldCount = 2
52 |
--------------------------------------------------------------------------------
/piscina/dist/src/common.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 | Object.defineProperty(exports, "__esModule", { value: true })
3 | exports.kFieldCount =
4 | exports.kResponseCountField =
5 | exports.kRequestCountField =
6 | exports.isTaskQueue =
7 | exports.markMovable =
8 | exports.isMovable =
9 | exports.isTransferable =
10 | exports.kQueueOptions =
11 | exports.kValue =
12 | exports.kTransferable =
13 | exports.commonState =
14 | void 0
15 | exports.commonState = {
16 | isWorkerThread: false,
17 | workerData: undefined
18 | }
19 | // Internal symbol used to mark Transferable objects returned
20 | // by the Piscina.move() function
21 | const kMovable = Symbol("Piscina.kMovable")
22 | exports.kTransferable = Symbol.for("Piscina.transferable")
23 | exports.kValue = Symbol.for("Piscina.valueOf")
24 | exports.kQueueOptions = Symbol.for("Piscina.queueOptions")
25 | // True if the object implements the Transferable interface
26 | function isTransferable(value) {
27 | return value != null && typeof value === "object" && exports.kTransferable in value && exports.kValue in value
28 | }
29 | exports.isTransferable = isTransferable
30 | // True if object implements Transferable and has been returned
31 | // by the Piscina.move() function
32 | function isMovable(value) {
33 | return isTransferable(value) && value[kMovable] === true
34 | }
35 | exports.isMovable = isMovable
36 | function markMovable(value) {
37 | Object.defineProperty(value, kMovable, {
38 | enumerable: false,
39 | configurable: true,
40 | writable: true,
41 | value: true
42 | })
43 | }
44 | exports.markMovable = markMovable
45 | function isTaskQueue(value) {
46 | return typeof value === "object" && value !== null && "size" in value && typeof value.shift === "function" && typeof value.remove === "function" && typeof value.push === "function"
47 | }
48 | exports.isTaskQueue = isTaskQueue
49 | exports.kRequestCountField = 0
50 | exports.kResponseCountField = 1
51 | exports.kFieldCount = 2
52 | //# sourceMappingURL=common.js.map
53 |
--------------------------------------------------------------------------------
/piscina/dist/src/common.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/common.ts"],"names":[],"mappings":";;;AAoBC,CAAC;AAQW,QAAA,WAAW,GAAG;IACzB,cAAc,EAAE,KAAK;IACrB,UAAU,EAAE,SAAS;CACtB,CAAC;AAEF,6DAA6D;AAC7D,iCAAiC;AACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAC/B,QAAA,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACnD,QAAA,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACvC,QAAA,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AAEhE,2DAA2D;AAC3D,SAAgB,cAAc,CAAE,KAAW;IACzC,OAAO,KAAK,IAAI,IAAI;QACb,OAAO,KAAK,KAAK,QAAQ;QACzB,qBAAa,IAAI,KAAK;QACtB,cAAM,IAAI,KAAK,CAAC;AACzB,CAAC;AALD,wCAKC;AAED,+DAA+D;AAC/D,iCAAiC;AACjC,SAAgB,SAAS,CAAE,KAAW;IACpC,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;AAC3D,CAAC;AAFD,8BAEC;AAED,SAAgB,WAAW,CAAE,KAAc;IACzC,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE;QACrC,UAAU,EAAE,KAAK;QACjB,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;AACL,CAAC;AAPD,kCAOC;AAkBD,SAAgB,WAAW,CAAE,KAAW;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,MAAM,IAAI,KAAK;QACf,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU;QACjC,OAAO,KAAK,CAAC,MAAM,KAAK,UAAU;QAClC,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;AAC1C,CAAC;AAPD,kCAOC;AAEY,QAAA,kBAAkB,GAAG,CAAC,CAAC;AACvB,QAAA,mBAAmB,GAAG,CAAC,CAAC;AACxB,QAAA,WAAW,GAAG,CAAC,CAAC"}
--------------------------------------------------------------------------------
/piscina/dist/src/index.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Worker, MessagePort } from "worker_threads"
3 | import EventEmitterAsyncResource from "eventemitter-asyncresource"
4 | import { Transferable, TaskQueue } from "./common"
5 | interface AbortSignalEventTargetAddOptions {
6 | once: boolean
7 | }
8 | interface AbortSignalEventTarget {
9 | addEventListener: (name: "abort", listener: () => void, options?: AbortSignalEventTargetAddOptions) => void
10 | removeEventListener: (name: "abort", listener: () => void) => void
11 | aborted?: boolean
12 | }
13 | interface AbortSignalEventEmitter {
14 | off: (name: "abort", listener: () => void) => void
15 | once: (name: "abort", listener: () => void) => void
16 | }
17 | declare type AbortSignalAny = AbortSignalEventTarget | AbortSignalEventEmitter
18 | declare type ResourceLimits = Worker extends {
19 | resourceLimits?: infer T
20 | }
21 | ? T
22 | : {}
23 | declare type EnvSpecifier = typeof Worker extends {
24 | new (
25 | filename: never,
26 | options?: {
27 | env: infer T
28 | }
29 | ): Worker
30 | }
31 | ? T
32 | : never
33 | interface Options {
34 | filename?: string | null
35 | name?: string
36 | minThreads?: number
37 | maxThreads?: number
38 | idleTimeout?: number
39 | maxQueue?: number | "auto"
40 | concurrentTasksPerWorker?: number
41 | useAtomics?: boolean
42 | resourceLimits?: ResourceLimits
43 | argv?: string[]
44 | execArgv?: string[]
45 | env?: EnvSpecifier
46 | workerData?: any
47 | taskQueue?: TaskQueue
48 | niceIncrement?: number
49 | trackUnmanagedFds?: boolean
50 | }
51 | interface FilledOptions extends Options {
52 | filename: string | null
53 | name: string
54 | minThreads: number
55 | maxThreads: number
56 | idleTimeout: number
57 | maxQueue: number
58 | concurrentTasksPerWorker: number
59 | useAtomics: boolean
60 | taskQueue: TaskQueue
61 | niceIncrement: number
62 | }
63 | interface RunOptions {
64 | transferList?: TransferList
65 | filename?: string | null
66 | signal?: AbortSignalAny | null
67 | name?: string | null
68 | }
69 | declare type TransferList = MessagePort extends {
70 | postMessage(value: any, transferList: infer T): any
71 | }
72 | ? T
73 | : never
74 | declare type TransferListItem = TransferList extends (infer T)[] ? T : never
75 | declare class Piscina extends EventEmitterAsyncResource {
76 | #private
77 | constructor(options?: Options)
78 | /** @deprecated Use run(task, options) instead **/
79 | runTask(task: any, transferList?: TransferList, filename?: string, abortSignal?: AbortSignalAny): Promise
80 | /** @deprecated Use run(task, options) instead **/
81 | runTask(task: any, transferList?: TransferList, filename?: AbortSignalAny, abortSignal?: undefined): Promise
82 | /** @deprecated Use run(task, options) instead **/
83 | runTask(task: any, transferList?: string, filename?: AbortSignalAny, abortSignal?: undefined): Promise
84 | /** @deprecated Use run(task, options) instead **/
85 | runTask(task: any, transferList?: AbortSignalAny, filename?: undefined, abortSignal?: undefined): Promise
86 | run(task: any, options?: RunOptions): Promise
87 | destroy(): Promise
88 | get options(): FilledOptions
89 | get threads(): Worker[]
90 | get queueSize(): number
91 | get completed(): number
92 | get waitTime(): any
93 | get runTime(): any
94 | get utilization(): number
95 | get duration(): number
96 | static get isWorkerThread(): boolean
97 | static get workerData(): any
98 | static get version(): string
99 | static get Piscina(): typeof Piscina
100 | static move(val: Transferable | TransferListItem | ArrayBufferView | ArrayBuffer | MessagePort): ArrayBuffer | ArrayBufferView | MessagePort | Transferable
101 | static get transferableSymbol(): symbol
102 | static get valueSymbol(): symbol
103 | static get queueOptionsSymbol(): symbol
104 | }
105 | export = Piscina
106 |
--------------------------------------------------------------------------------
/piscina/dist/src/worker.d.ts:
--------------------------------------------------------------------------------
1 | export {}
2 |
--------------------------------------------------------------------------------
/piscina/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "_from": "piscina",
3 | "_id": "piscina@3.1.0",
4 | "_inBundle": false,
5 | "_integrity": "sha512-KTW4sjsCD34MHrUbx9eAAbuUSpVj407hQSgk/6Epkg0pbRBmv4a3UX7Sr8wxm9xYqQLnsN4mFOjqGDzHAdgKQg==",
6 | "_location": "/piscina",
7 | "_phantomChildren": {},
8 | "_requested": {
9 | "type": "tag",
10 | "registry": true,
11 | "raw": "piscina",
12 | "name": "piscina",
13 | "escapedName": "piscina",
14 | "rawSpec": "",
15 | "saveSpec": null,
16 | "fetchSpec": "latest"
17 | },
18 | "_requiredBy": [
19 | "#USER",
20 | "/"
21 | ],
22 | "_resolved": "https://registry.npmjs.org/piscina/-/piscina-3.1.0.tgz",
23 | "_shasum": "2333636865b6cb69c5a370bbc499a98cabcf3e04",
24 | "_spec": "piscina",
25 | "_where": "C:\\Users\\User\\Documents\\Github\\simple-mod-framework",
26 | "author": {
27 | "name": "James M Snell",
28 | "email": "jasnell@gmail.com"
29 | },
30 | "bugs": {
31 | "url": "https://github.com/piscinajs/piscina/issues"
32 | },
33 | "bundleDependencies": false,
34 | "contributors": [
35 | {
36 | "name": "Anna Henningsen",
37 | "email": "anna@addaleax.net"
38 | },
39 | {
40 | "name": "Matteo Collina",
41 | "email": "matteo.collina@gmail.com"
42 | }
43 | ],
44 | "dependencies": {
45 | "eventemitter-asyncresource": "^1.0.0",
46 | "hdr-histogram-js": "^2.0.1",
47 | "hdr-histogram-percentiles-obj": "^3.0.0",
48 | "nice-napi": "^1.0.2"
49 | },
50 | "deprecated": false,
51 | "description": "A fast, efficient Node.js Worker Thread Pool implementation",
52 | "devDependencies": {
53 | "@types/node": "^15.0.1",
54 | "@typescript-eslint/eslint-plugin": "^4.22.0",
55 | "@typescript-eslint/parser": "^4.22.0",
56 | "abort-controller": "^3.0.0",
57 | "concat-stream": "^2.0.0",
58 | "gen-esm-wrapper": "^1.1.1",
59 | "snazzy": "^9.0.0",
60 | "standardx": "^7.0.0",
61 | "tap": "^15.0.6",
62 | "ts-node": "^9.1.1",
63 | "typescript": "^4.2.4"
64 | },
65 | "directories": {
66 | "example": "examples"
67 | },
68 | "eslintConfig": {
69 | "rules": {
70 | "semi": [
71 | "error",
72 | "always"
73 | ],
74 | "no-unused-vars": "off",
75 | "no-use-before-define": "off",
76 | "no-unreachable-loop": "off",
77 | "no-dupe-class-members": "off",
78 | "@typescript-eslint/no-unused-vars": "error"
79 | },
80 | "globals": {
81 | "SharedArrayBuffer": true,
82 | "Atomics": true,
83 | "AbortController": true,
84 | "MessageChannel": true
85 | }
86 | },
87 | "exports": {
88 | "import": "./dist/esm-wrapper.mjs",
89 | "require": "./dist/src/index.js"
90 | },
91 | "homepage": "https://github.com/piscinajs/piscina#readme",
92 | "keywords": [
93 | "fast",
94 | "worker threads",
95 | "thread pool",
96 | "wade wilson"
97 | ],
98 | "license": "MIT",
99 | "main": "./dist/src/index.js",
100 | "name": "piscina",
101 | "optionalDependencies": {
102 | "nice-napi": "^1.0.2"
103 | },
104 | "repository": {
105 | "type": "git",
106 | "url": "git+https://github.com/piscinajs/piscina.git"
107 | },
108 | "scripts": {
109 | "build": "tsc && gen-esm-wrapper . dist/esm-wrapper.mjs",
110 | "lint": "standardx \"**/*.{ts,mjs,js,cjs}\" | snazzy",
111 | "prepack": "npm run build"
112 | },
113 | "standardx": {
114 | "parser": "@typescript-eslint/parser",
115 | "plugins": [
116 | "@typescript-eslint/eslint-plugin"
117 | ]
118 | },
119 | "types": "./dist/src/index.d.ts",
120 | "version": "3.1.0"
121 | }
122 |
--------------------------------------------------------------------------------
/rome.json:
--------------------------------------------------------------------------------
1 | {
2 | "linter": {
3 | "enabled": true,
4 | "rules": {
5 | "recommended": true
6 | },
7 | "ignore": ["*.js"]
8 | },
9 | "formatter": {
10 | "lineWidth": 200,
11 | "ignore": ["*.js"]
12 | },
13 | "javascript": {
14 | "formatter": {
15 | "semicolons": "asNeeded",
16 | "trailingComma": "none"
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/rust/.npmignore:
--------------------------------------------------------------------------------
1 | target
2 | Cargo.lock
3 | .cargo
4 | .github
5 | npm
6 | .eslintrc
7 | .prettierignore
8 | rustfmt.toml
9 | yarn.lock
10 | *.node
11 | .yarn
12 | __test__
13 | renovate.json
14 |
--------------------------------------------------------------------------------
/rust/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | nodeLinker: node-modules
2 |
3 | yarnPath: .yarn/releases/yarn-3.6.0.cjs
4 |
--------------------------------------------------------------------------------
/rust/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | edition = "2021"
3 | name = "smf-rust"
4 | version = "0.0.0"
5 |
6 | [lib]
7 | crate-type = ["cdylib"]
8 |
9 | [dependencies]
10 | human-sort = "0.2.2"
11 | # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
12 | napi = { version = "2.10.2", default-features = false, features = ["napi4"] }
13 | napi-derive = "2.9.3"
14 | regex = "1.7.0"
15 | sysinfo = "0.28.4"
16 | walkdir = "2.3.2"
17 |
18 | [build-dependencies]
19 | napi-build = "2.0.1"
20 |
21 | [profile.release]
22 | lto = true
23 |
--------------------------------------------------------------------------------
/rust/build.rs:
--------------------------------------------------------------------------------
1 | extern crate napi_build;
2 |
3 | fn main() {
4 | napi_build::setup();
5 | }
6 |
--------------------------------------------------------------------------------
/rust/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "smf-rust",
3 | "version": "0.0.0",
4 | "main": "index.js",
5 | "types": "index.d.ts",
6 | "napi": {
7 | "name": "rust",
8 | "triples": {
9 | "defaults": false,
10 | "additional": [
11 | "x86_64-pc-windows-msvc"
12 | ]
13 | }
14 | },
15 | "private": true,
16 | "license": "LGPL-3.0-only",
17 | "devDependencies": {
18 | "@napi-rs/cli": "^2.13.3",
19 | "ava": "^4.3.3"
20 | },
21 | "ava": {
22 | "timeout": "3m"
23 | },
24 | "engines": {
25 | "node": ">= 10"
26 | },
27 | "scripts": {
28 | "artifacts": "napi artifacts",
29 | "build": "napi build --platform --release",
30 | "build:debug": "napi build --platform",
31 | "prepublishOnly": "napi prepublish -t npm",
32 | "test": "ava",
33 | "version": "napi version"
34 | },
35 | "packageManager": "yarn@3.6.0"
36 | }
37 |
--------------------------------------------------------------------------------
/rust/rustfmt.toml:
--------------------------------------------------------------------------------
1 | unstable_features = true
2 | hard_tabs = true
3 | match_block_trailing_comma = false
4 | trailing_comma = "Never"
--------------------------------------------------------------------------------
/rust/src/lib.rs:
--------------------------------------------------------------------------------
1 | #[macro_use]
2 | extern crate napi_derive;
3 |
4 | use std::{
5 | cmp::Ordering,
6 | env,
7 | ffi::OsStr,
8 | fs,
9 | path::{Path, PathBuf},
10 | };
11 |
12 | use human_sort::compare;
13 | use regex::Regex;
14 | use sysinfo::{Disk, DiskExt, RefreshKind, System, SystemExt};
15 | use walkdir::WalkDir;
16 |
17 | #[napi]
18 | pub fn stage_dependencies_from(from_folder: String, to_folder: String) {
19 | let re_rpkg = Regex::new(r"(?i)00[0-9A-F]*\..*?\\(chunk[0-9]*(?:patch[0-9]*)?)\\").unwrap();
20 | let re_rpkg_chunk =
21 | Regex::new(r"(?i)00[0-9A-F]*\..*?\\(chunk[0-9]*)(?:patch[0-9]*)?\\").unwrap();
22 | let re_meta = Regex::new(r"(?i)chunk[0-9]*(?:patch[0-9]*)?\.meta").unwrap();
23 |
24 | // Walk folder, get files, extract RPKG names for paths
25 | let mut all_files = WalkDir::new(from_folder)
26 | .into_iter()
27 | .filter_map(|x| x.ok())
28 | .filter(|x| x.file_type().is_file())
29 | .map(|x| {
30 | (
31 | re_rpkg
32 | .captures_iter(x.path().to_str().unwrap())
33 | .next()
34 | .unwrap()[1]
35 | .to_owned(),
36 | re_rpkg_chunk
37 | .captures_iter(x.path().to_str().unwrap())
38 | .next()
39 | .unwrap()[1]
40 | .to_owned(),
41 | x.path().to_owned(),
42 | )
43 | })
44 | .collect::>();
45 |
46 | // Sort by RPKG in descending order
47 | all_files.sort_by(|(rpkg_a, chunk_a, _), (rpkg_b, chunk_b, _)| {
48 | match compare(chunk_a, chunk_b) {
49 | // If chunks are the same, compare patches in descending order
50 | Ordering::Equal => compare(rpkg_a, rpkg_b).reverse(),
51 |
52 | // If chunks are different, compare chunks in ascending order
53 | _ => compare(chunk_a, chunk_b),
54 | }
55 | });
56 |
57 | // Include only first versions of files (sorted already so the right versions will be used)
58 | let mut all_files_superseded: Vec = vec![];
59 | for (_, _, path) in all_files {
60 | if !all_files_superseded
61 | .iter()
62 | .any(|x| x.file_name().unwrap() == path.file_name().unwrap())
63 | {
64 | all_files_superseded.push(path);
65 | }
66 | }
67 |
68 | // Remove all chunk metas
69 | all_files_superseded.retain(|x| !re_meta.is_match(x.file_name().unwrap().to_str().unwrap()));
70 |
71 | // Ensure staging folder exists
72 | if !Path::new("staging").join(&to_folder).is_dir() {
73 | fs::create_dir(Path::new("staging").join(&to_folder)).unwrap();
74 | }
75 |
76 | // Copy all to staging
77 | for file_path in all_files_superseded {
78 | let p = Path::new("staging")
79 | .join(&to_folder)
80 | .join(file_path.file_name().unwrap());
81 |
82 | if !p.exists() {
83 | if p.extension().and_then(OsStr::to_str) == Some("meta")
84 | && p.with_extension("meta.json").exists()
85 | {
86 | continue;
87 | }
88 |
89 | fs::copy(&file_path, p).unwrap();
90 | }
91 | }
92 | }
93 |
94 | #[napi]
95 | pub fn free_disk_space() -> Result {
96 | let cur_path = env::current_dir()?;
97 | let sys = System::new_with_specifics(RefreshKind::new().with_disks_list());
98 |
99 | let cur_disk: &Disk;
100 | if cur_path.to_string_lossy().to_lowercase().starts_with("z:\\") {
101 | // most likely running inside wine, default to first disk
102 | cur_disk = &sys.disks().get(0).expect("Couldn't get current disk!");
103 | } else {
104 | cur_disk = sys.disks()
105 | .iter()
106 | .find_map(|x| {
107 | if cur_path
108 | .to_string_lossy()
109 | .to_lowercase()
110 | .starts_with(&x.mount_point().to_str()?.to_lowercase())
111 | {
112 | Some(x)
113 | } else {
114 | None
115 | }
116 | })
117 | .expect("Couldn't get current disk!");
118 | }
119 |
120 | Ok(cur_disk.available_space() as f64)
121 | }
122 |
--------------------------------------------------------------------------------
/src/core-singleton.ts:
--------------------------------------------------------------------------------
1 | import core from "./core"
2 |
3 | export const FrameworkVersion = core.FrameworkVersion
4 | export const rpkgInstance = core.rpkgInstance
5 | export const config = core.config
6 | export const logger = core.logger
7 | export const isDevBuild = core.isDevBuild
8 | export const args = core.args
9 | export const cleanExit = core.cleanExit
10 |
11 | export default {
12 | FrameworkVersion,
13 | rpkgInstance,
14 | config,
15 | logger,
16 | isDevBuild,
17 | args,
18 | cleanExit
19 | }
20 |
--------------------------------------------------------------------------------
/src/difference.ts:
--------------------------------------------------------------------------------
1 | import { logger } from "./core-singleton"
2 |
3 | export default async function difference(
4 | oldMap: { [x: string]: { hash: string; dependencies: Array; affected: Array } },
5 | newMap: { [x: string]: { hash: string; dependencies: Array; affected: Array } }
6 | ) {
7 | await logger.info("Invalidating cache")
8 |
9 | const invalidFiles = []
10 |
11 | const invalidData = []
12 | const validData = []
13 |
14 | await logger.verbose("Calculating changed files")
15 |
16 | const changedFiles = []
17 | for (const [filePath, newData] of Object.entries(newMap)) {
18 | const oldData = oldMap[filePath]
19 |
20 | if (!oldData || oldData.hash !== newData.hash) {
21 | changedFiles.push(filePath)
22 | }
23 | }
24 |
25 | for (const [filePath, oldData] of Object.entries(oldMap)) {
26 | const newData = newMap[filePath]
27 |
28 | if (!newData) {
29 | changedFiles.push(filePath)
30 | }
31 | }
32 |
33 | await logger.verbose("Calculating hashes to invalidate")
34 |
35 | const invalidatedHashes: string[] = []
36 | for (const changedFile of changedFiles) {
37 | invalidFiles.push(changedFile)
38 |
39 | oldMap[changedFile] && invalidatedHashes.push(...oldMap[changedFile].affected)
40 | newMap[changedFile] && invalidatedHashes.push(...newMap[changedFile].affected)
41 | }
42 |
43 | await logger.verbose("Invalidating dependencies")
44 |
45 | // do ten cycles of propagation
46 | for (let i = 0; i < 10; i++) {
47 | for (const [filePath, newData] of Object.entries(newMap)) {
48 | const oldData = oldMap[filePath]
49 |
50 | if (invalidatedHashes.some((a) => (oldData || { dependencies: [] }).dependencies.includes(a) || newData.dependencies.includes(a))) {
51 | invalidatedHashes.push(...[...(oldData || { affected: [] }).affected, ...newData.affected])
52 | }
53 | }
54 | }
55 |
56 | for (const [filePath, newData] of Object.entries(newMap)) {
57 | const oldData = oldMap[filePath]
58 |
59 | if (invalidatedHashes.some((a) => (oldData || { dependencies: [] }).dependencies.includes(a) || newData.dependencies.includes(a))) {
60 | invalidFiles.push(filePath)
61 | }
62 | }
63 |
64 | await logger.verbose("Summarising")
65 |
66 | for (const [filePath, data] of Object.entries(newMap)) {
67 | if (!invalidFiles.includes(filePath)) {
68 | validData.push({ filePath, data })
69 | } else {
70 | invalidData.push({ filePath, data })
71 | }
72 | }
73 |
74 | return {
75 | invalidData,
76 | cachedData: validData
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/quickentity-3.ts:
--------------------------------------------------------------------------------
1 | import child_process from "child_process"
2 | import { logger } from "./core-singleton"
3 |
4 | // Shim for QuickEntity 3.0 executable
5 |
6 | const execCommand = function (command: string) {
7 | void logger.verbose(`Executing QN 3.0 command ${command}`)
8 | child_process.execSync(command, { stdio: [ "pipe", "pipe", "inherit" ] })
9 | }
10 |
11 | export async function convert(game: string, TEMP: string, TEMPmeta: string, TBLU: string, TBLUmeta: string, output: string) {
12 | execCommand(
13 | `"Third-Party\\quickentity-3.exe" entity convert --input-factory "${TEMP}" --input-factory-meta "${TEMPmeta}" --input-blueprint "${TBLU}" --input-blueprint-meta "${TBLUmeta}" --output "${output}" --lossless`
14 | )
15 | }
16 |
17 | export async function generate(game: string, input: string, TEMP: string, TEMPmeta: string, TBLU: string, TBLUmeta: string) {
18 | execCommand(
19 | `"Third-Party\\quickentity-3.exe" entity generate --input "${input}" --output-factory "${TEMP}" --output-factory-meta "${TEMPmeta}" --output-blueprint "${TBLU}" --output-blueprint-meta "${TBLUmeta}"`
20 | )
21 | }
22 |
23 | export async function applyPatchJSON(original: string, patch: string, output: string) {
24 | execCommand(`"Third-Party\\quickentity-3.exe" patch apply --input "${original}" --patch "${patch}" --output "${output}"`)
25 | }
26 |
--------------------------------------------------------------------------------
/src/quickentity-rs.ts:
--------------------------------------------------------------------------------
1 | import child_process from "child_process"
2 | import { logger } from "./core-singleton"
3 |
4 | // Shim for QuickEntity 3.1 executable
5 |
6 | const execCommand = function (command: string) {
7 | void logger.verbose(`Executing QN 3.1 command ${command}`)
8 | child_process.execSync(command, { stdio: [ "pipe", "inherit", "inherit" ] })
9 | }
10 |
11 | export async function convert(game: string, TEMP: string, TEMPmeta: string, TBLU: string, TBLUmeta: string, output: string) {
12 | execCommand(
13 | `"Third-Party\\quickentity-rs.exe" entity convert --input-factory "${TEMP}" --input-factory-meta "${TEMPmeta}" --input-blueprint "${TBLU}" --input-blueprint-meta "${TBLUmeta}" --output "${output}" --lossless`
14 | )
15 | }
16 |
17 | export async function generate(game: string, input: string, TEMP: string, TEMPmeta: string, TBLU: string, TBLUmeta: string) {
18 | execCommand(
19 | `"Third-Party\\quickentity-rs.exe" entity generate --input "${input}" --output-factory "${TEMP}" --output-factory-meta "${TEMPmeta}" --output-blueprint "${TBLU}" --output-blueprint-meta "${TBLUmeta}"`
20 | )
21 | }
22 |
23 | export async function createPatchJSON(original: string, modified: string, output: string) {
24 | execCommand(`"Third-Party\\quickentity-rs.exe" patch generate --input1 "${original}" --input2 "${modified}" --output "${output}" --format-fix`)
25 | }
26 |
27 | export async function applyPatchJSON(original: string, patch: string, output: string) {
28 | execCommand(`"Third-Party\\quickentity-rs.exe" patch apply --input "${original}" --patch "${patch}" --output "${output}" --permissive --format-fix`)
29 | }
30 |
--------------------------------------------------------------------------------
/src/rpkg.ts:
--------------------------------------------------------------------------------
1 | import child_process from "child_process"
2 | import fs from "fs"
3 | import json5 from "json5"
4 | import path from "path"
5 |
6 | require("clarify")
7 |
8 | const config = json5.parse(fs.readFileSync(path.join(process.cwd(), "config.json"), "utf8"))
9 |
10 | class RPKGInstance {
11 | rpkgProcess: child_process.ChildProcessWithoutNullStreams
12 |
13 | output: string
14 | previousOutput: string
15 |
16 | initialised: boolean
17 | ready: boolean
18 |
19 | shouldExit: boolean
20 |
21 | constructor() {
22 | this.rpkgProcess = child_process.spawn(path.join(process.cwd(), "Third-Party", "rpkg-cli"), ["-i"])
23 | this.output = ""
24 | this.previousOutput = ""
25 | this.initialised = false
26 | this.ready = false
27 | this.shouldExit = false
28 |
29 | this.rpkgProcess.stdout.on("data", (data) => {
30 | this.output += String(data)
31 |
32 | if (this.output.endsWith("RPKG> ")) {
33 | if (!this.initialised) {
34 | this.initialised = true
35 | this.ready = false
36 | this.output = ""
37 | this.previousOutput = ""
38 | return
39 | }
40 |
41 | this.previousOutput = this.output
42 | this.output = ""
43 | this.ready = true
44 | }
45 | })
46 |
47 | this.rpkgProcess.on("close", () => {
48 | if (!this.shouldExit) {
49 | console.error("Fatal error!")
50 | console.error("RPKG process exited unexpectedly with output:")
51 |
52 | for (const line of this.output.split("\n")) {
53 | console.log(line)
54 | }
55 |
56 | setTimeout(() => process.exit(1), 2000)
57 | }
58 | })
59 | }
60 |
61 | async waitForInitialised() {
62 | // yes, bad, pls tell me how to make good
63 | return new Promise(waitForInitialised.bind(this))
64 | }
65 |
66 | async callFunction(func: string): Promise {
67 | this.ready = false
68 |
69 | this.rpkgProcess.stdin.write(func)
70 | this.rpkgProcess.stdin.write("\n")
71 |
72 | return new Promise(waitForReady.bind(this))
73 | }
74 |
75 | async getRPKGOfHash(hash: string): Promise {
76 | const result = [
77 | ...(await this.callFunction(`-hash_probe "${path.resolve(process.cwd(), config.runtimePath)}" -filter "${hash}"`)).matchAll(/is in RPKG file: (chunk[0-9]*(?:patch[1-9])?)\.rpkg/g)
78 | ]
79 |
80 | return result
81 | .map((a) => a[1])
82 | .sort((a, b) => {
83 | const aChunk = /(chunk[0-9]*)(?:patch[0-9]*)?/gi.exec(a)![1]
84 | const bChunk = /(chunk[0-9]*)(?:patch[0-9]*)?/gi.exec(b)![1]
85 |
86 | if (aChunk.localeCompare(bChunk) !== 0) {
87 | return aChunk.localeCompare(bChunk, undefined, {
88 | numeric: true,
89 | sensitivity: "base"
90 | })
91 | } else {
92 | return b.localeCompare(a, undefined, {
93 | numeric: true,
94 | sensitivity: "base"
95 | })
96 | }
97 | })[0]
98 | }
99 |
100 | exit() {
101 | this.shouldExit = true
102 | this.rpkgProcess.kill()
103 | }
104 | }
105 |
106 | function waitForInitialised(resolve: (result: string) => unknown) {
107 | // yes, bad, pls tell me how to make good
108 | if (this.initialised) {
109 | resolve(this.previousOutput)
110 | } else {
111 | setTimeout(waitForInitialised.bind(this, resolve), 100)
112 | }
113 | }
114 |
115 | function waitForReady(resolve: (result: string) => unknown) {
116 | // yes, bad, pls tell me how to make good
117 | if (this.ready) {
118 | resolve(this.previousOutput.slice(0, -8).replace(/Running command: .*\r\n\r\n/g, ""))
119 | } else {
120 | setTimeout(waitForReady.bind(this, resolve), 100)
121 | }
122 | }
123 |
124 | export default RPKGInstance
125 |
--------------------------------------------------------------------------------
/src/typescript.ts:
--------------------------------------------------------------------------------
1 | import fs from "fs-extra"
2 | import path from "path"
3 | import ts from "typescript"
4 |
5 | export function compile(fileNames: string[], options: ts.CompilerOptions, rootDir: string) {
6 | fs.ensureDirSync(path.join(process.cwd(), "compiled"))
7 | const program = ts.createProgram(fileNames, options)
8 | program.emit(undefined, (filename, data) => {
9 | fs.ensureDirSync(path.join(process.cwd(), "compiled", path.dirname(path.relative(rootDir, filename))))
10 | fs.writeFileSync(path.join(process.cwd(), "compiled", path.relative(rootDir, filename)), data)
11 |
12 | // rome-ignore lint/performance/noDelete: lmao
13 | delete require.cache[require.resolve(path.join(process.cwd(), "compiled", path.relative(rootDir, filename)))]
14 | })
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "./compiled",
4 | "allowJs": true,
5 | "target": "ES2019",
6 | "module": "CommonJS",
7 | "esModuleInterop": true,
8 | "noImplicitAny": true,
9 | "strictNullChecks": true,
10 | "importsNotUsedAsValues": "error",
11 | "sourceMap": true,
12 | "inlineSources": true,
13 | "sourceRoot": "/",
14 | "noEmitHelpers": true,
15 | "importHelpers": true,
16 | "declaration": true,
17 | "resolveJsonModule": true
18 | },
19 | "include": [
20 | "./src/**/*"
21 | ]
22 | }
--------------------------------------------------------------------------------