├── .github └── workflows │ ├── nodejs.yml │ └── release.yml ├── .gitignore ├── .prettierrc ├── CHANGELOG.md ├── Dockerfile ├── README.md ├── build.sh ├── docker-compose.yml ├── license-scriptcraft.txt ├── license.md ├── package-lock.json ├── package.json ├── resources ├── ScriptCraft-3.4.0-patched.zip ├── bukkit.yml ├── eula.txt ├── h2.jar ├── js │ ├── INSTALLATION.md │ ├── __jasmine │ │ ├── index.js │ │ ├── index.ts │ │ └── jasmine.js │ ├── __types__ │ │ └── global.d.ts │ ├── sma-bootstrap │ │ ├── README.md │ │ ├── index.js │ │ ├── index.ts │ │ ├── lib │ │ │ ├── find.js │ │ │ └── loader.js │ │ ├── pluginLoader │ │ │ ├── PluginLoader.js │ │ │ ├── PluginLoader.ts │ │ │ ├── TestLoader.js │ │ │ └── TestLoader.ts │ │ ├── polyfills │ │ │ ├── array-filter.js │ │ │ ├── array-filter.ts │ │ │ ├── array-find.js │ │ │ ├── array-find.ts │ │ │ ├── array-from.js │ │ │ ├── array-from.ts │ │ │ ├── array-includes.js │ │ │ ├── array-includes.ts │ │ │ ├── event-emitter.js │ │ │ ├── event-emitter.ts │ │ │ ├── index.js │ │ │ ├── index.ts │ │ │ ├── object-assign.js │ │ │ ├── object-assign.ts │ │ │ ├── promise.js │ │ │ ├── string.js │ │ │ └── string.ts │ │ └── require │ │ │ ├── patch-require.js │ │ │ ├── patch-require.ts │ │ │ └── require.js │ └── tsconfig.json ├── paperclip.jar ├── plugins │ ├── BossBarAPI_v2.4.2.jar │ ├── CamundaPlugin-1.0.0-SNAPSHOT.jar │ ├── DurableMap-1.0.jar │ ├── Essentials-2.x-SNAPSHOT.jar │ ├── HolographicDisplays-2.4.2-SNAPSHOT.jar │ ├── MinecraftRestConsole-1.8.jar │ ├── MotdManager-Reloaded.jar │ ├── MotdManager-Reloaded │ │ └── config.yml │ ├── Multiverse-Core-4.1.0.jar │ ├── ProtocolLib-4.5.0.jar │ ├── Scriptcraft-ME-3.2.0.jar │ └── worldedit-bukkit-7.1.0-rc-1.jar ├── s ├── scriptcraft.jar └── start.sh ├── run.sh └── test ├── HolographicDisplays.jar ├── run.sh ├── test-plugin-2 ├── dst │ └── autoload │ │ ├── _1.js │ │ └── _2.js ├── fs.js └── package.json └── test-plugin └── plugins └── index.js /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [8.x, 10.x, 12.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - run: npm install 21 | - run: npm run build --if-present 22 | - run: npm test 23 | env: 24 | CI: true 25 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | 3 | on: 4 | push: 5 | # Sequence of patterns matched against refs/tags 6 | tags: 7 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 8 | 9 | jobs: 10 | build: 11 | name: Create Release 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | - run: npm install 20 | - run: npm run build --if-present 21 | - run: npm test 22 | env: 23 | CI: true 24 | - name: Build project # This would actually build your project, using zip for an example artifact 25 | run: | 26 | zip -r sma-patch resources/js 27 | - name: Create Release 28 | id: create_release 29 | uses: actions/create-release@v1 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 32 | with: 33 | tag_name: ${{ github.ref }} 34 | release_name: Release ${{ github.ref }} 35 | body: | 36 | Changes in this Release 37 | - First Change 38 | - Second Change 39 | draft: false 40 | prerelease: false 41 | - name: Upload Release Asset 42 | id: upload-release-asset 43 | uses: actions/upload-release-asset@v1.0.1 44 | env: 45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | with: 47 | upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 48 | asset_path: ./sma-patch.zip 49 | asset_name: sma-patch.zip 50 | asset_content_type: application/zip 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | cache 4 | ScriptCraft-3.4.0-src 5 | .DS_Store -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "semi": false, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changes 2 | 3 | 0.1.2 - Added Essentials Bukkit Plugin. 4 | 0.1.3 - Added support for `smaPluginConfig` key in plugins' `package.json` file. 5 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM openjdk:8u171-jdk-alpine3.8 2 | FROM oracle/graalvm-ce:19.3.1-java8 3 | # Expose Minecraft server port 4 | EXPOSE 25565 5 | 6 | WORKDIR /_server_ 7 | COPY ./resources ./ 8 | 9 | RUN yum install unzip -y && \ 10 | mkdir scriptcraft && \ 11 | cd scriptcraft && \ 12 | unzip ../ScriptCraft-3.4.0-patched.zip && \ 13 | mv js/* . && \ 14 | rm -rf js && \ 15 | cd .. 16 | RUN rm -rf ScriptCraft* 17 | RUN mv js/sma-bootstrap scriptcraft/plugins/ 18 | RUN mkdir -p scriptcraft-plugins/__jasmine/* 19 | RUN mv js/__jasmine/* scriptcraft-plugins/__jasmine/ 20 | 21 | ENTRYPOINT /_server_/start.sh 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scriptcraft Modular Architecture 2 | 3 | [![](https://images.microbadger.com/badges/version/magikcraft/scriptcraft:1.15.2.svg)](https://hub.docker.com/repository/docker/magikcraft/scriptcraft/ 'Paperclip 1.15.2 and GraalVM') 4 | 5 | Scriptcraft Modular Architecture (SMA) adds support for modular plugins that live outside the `scriptcraft` root directory. 6 | 7 | This provides isolation of custom plugin files, allowing plugins to live in their own repositories and be loaded via configuration - for example by mounting them in a docker container. 8 | 9 | It also means that you can update the Scriptcraft version without impacting your own code. 10 | 11 | ## Docker image 12 | 13 | A [built Docker image](https://hub.docker.com/repository/docker/magikcraft/scriptcraft) is available from Docker Hub: 14 | 15 | ``` 16 | docker pull magikcraft/scriptcraft 17 | ``` 18 | 19 | ## Scriptcraft Version 20 | 21 | This uses [Scriptcraft 3.4.0](https://github.com/Magikcraft/ScriptCraft/tree/3.4.0-patched) patched to fix issue [#410](https://github.com/walterhiggins/ScriptCraft/issues/410). See the [README-Magikcraft.md](https://github.com/Magikcraft/ScriptCraft/blob/3.4.0-patched/README-Magikcraft.md) file for instructions on building a patched version. 22 | 23 | Uses the [Scriptcraft Multi-engine plugin](https://github.com/Magikcraft/scriptcraft-multi-engine). 24 | 25 | ## Base image 26 | 27 | From 1.15.2, the base image is [oracle/graalvm-ce:19.3.1-java8](https://hub.docker.com/r/oracle/graalvm-ce/tags), to use the new Polyglot GraalVM. 28 | 29 | ## Versions 30 | 31 | - Paperclip [build #71](https://papermc.io/downloads). 32 | - H2 1.4.200 33 | - [CamundaPlugin](https://github.com/jwulf/camunda-minecraft-plugin) 34 | 35 | ## To Run 36 | 37 | ```bash 38 | docker run -it -p 25665:25565 magikcraft/scriptcraft 39 | ``` 40 | 41 | For an example on starting the docker container with SMA plugins, refer to the example in the `test` directory. 42 | 43 | ## Note on getting op 44 | 45 | When the server starts, you need to give yourself `op`. At the server console, type this: 46 | 47 | ``` 48 | op {your-minecraft-name-goes-here} 49 | ``` 50 | 51 | Make sure that you put your minecraft username in there. So, for example, if your Minecraft name is Rob123, you would type: 52 | 53 | ``` 54 | op Rob123 55 | ``` 56 | 57 | ## Included plugins 58 | 59 | - Minecraft REST console 60 | - Holographic Displays 61 | - Essentials 62 | - Motd Manager Reloaded 63 | - Multiverse Core 64 | - ProtocolLib 65 | - World Edit 66 | - Boss Bar 67 | - Durable Map 68 | 69 | ## Run with Modular Plugins 70 | 71 | See the `run.sh` file for an example of how to mount modular scriptcraft plugins in the Docker image. 72 | 73 | ## Building 74 | 75 | To build the image, run: 76 | 77 | ```bash 78 | docker build -t magikcraft/scriptcraft . 79 | ``` 80 | 81 | ## Scriptcraft Modular Architecture 82 | 83 | ## Rationale 84 | 85 | We initially developed our plugins for Magikcraft and MCT1 (Minecraft for Type 1 Diabetes) inside Scriptcraft. This meant we had code spread between Scriptcraft's `lib`, `module`, and `plugins` folders. Upgrading Scriptcraft was a complex undertaking with multiple touch points. 86 | 87 | Also, when we wanted to open source parts of our code base, we had to either get it accepted into Scriptcraft upstream, or make it available as a patch on top of Scriptcraft, or a fork of Scriptcraft. 88 | 89 | We developed the Scriptcraft Modular Architecture to allow us to easily integrate code with Scriptcraft at run-time, while keeping it in a separate repository. 90 | 91 | ## Implementation 92 | 93 | 1. We put a directory outside scriptcraft and load additional modules in there. So the directory structure looks like this: 94 | 95 | ``` 96 | minecraft 97 | - scriptcraft-plugins 98 | - magikcraft 99 | - mct1 100 | - scriptcraft 101 | ``` 102 | 103 | 2. We mount a custom bootstrap into `scriptcraft/plugins` via docker. This bootstrap is loaded by Scriptcraft's standard plugin loading. 104 | 105 | 3. The bootstrap: 106 | 107 | - Replaces the standard scriptcraft implementation of `require` at run-time. This custom require adds the `scriptcraft-plugins` to the require resolution search paths. 108 | 109 | - Scans each SMA plugin for a `package.json` file. If found, checks for a `scriptcraft_load_dir` key. If present, the contents of the directory specified in this key are autoloaded. 110 | 111 | - If no `package.json` is found in an SMA plugin, or if it does not specify a `scriptcraft_load_dir`, then the bootstrap looks for a `plugin` folder in the SMA plugin, and loads everything in there if it is present. 112 | 113 | ## Module Resolution 114 | 115 | The SMA `require` searches the standard Scriptcraft locations first, then checks the scriptcraft-plugins directory. As an example, here is how `magikcraft/fs` gets resolved: 116 | 117 | ``` 118 | scriptcraft/lib/magicraft/fs 119 | scriptcraft/modules/magikcraft/fs 120 | scriptcraft/../scriptcraft-plugins/magikcraft/fs 121 | ``` 122 | 123 | **Note:** in SMA plugins you do not get the magic of searching `lib` and `module` subdirectories in your SMA plugin. The path is literal. So `magikcraft/fs` will resolve `scriptcraft-plugins/magikcraft/fs`, but not: 124 | 125 | `scriptcraft-plugins/magikcraft/lib/fs`, or 126 | 127 | `scriptcraft-plugins/magikcraft/modules/fs`. 128 | 129 | ## Polyfills 130 | 131 | The Scriptcraft Modular Architecture environment includes a number of ES6 polyfills. Our code at Magikcraft is written in TypeScript, and we missed a number of modern features while coding, so we added polyfills to the runtime to support the following: 132 | 133 | - `Array.prototype.find` 134 | - `Array.prototype.from` 135 | - `Array.prototype.includes` 136 | - `EventEmitter` 137 | - `Object.assign` 138 | - `Promise` 139 | - `String.prototype.includes` 140 | - `String.prototype.repeat` 141 | - `String.prototype.padStart` 142 | - `String.prototype.padEnd` 143 | 144 | ## Making a SMA Plugin 145 | 146 | The easiest way to make an SMA Plugin is using the [Scriptcraft-SMA Yeoman generator](https://www.npmjs.com/package/generator-sma-plugin). 147 | 148 | For an example of a Scriptcraft SMA plugin, refer to [MCT1](https://github.com/Magikcraft/mct1). 149 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | MINECRAFT_TAG=1.15.2 2 | npm run build && docker build --no-cache -t magikcraft/scriptcraft:$MINECRAFT_TAG . 3 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | volumes: 4 | worlds: 5 | 6 | services: 7 | minecraft: 8 | image: magikcraft/scriptcraft:1.15.2 9 | container_name: minecraft 10 | ports: 11 | - '25565:25565' 12 | - '8086:8086' 13 | environment: 14 | - MINECRAFT_EULA_ACCEPTED=true 15 | volumes: 16 | - ./cache:/_server_/cache 17 | - worlds:/_server_/worlds 18 | # To load SMA plugins 19 | # Create a directory called scriptcraft-plugins and npm install any SMA plugins there 20 | # with npm install --prefix ./scriptcraft-plugins 21 | # And uncomment the following line 22 | # - ./scriptcraft-plugins:/_server_/scriptcraft-plugins 23 | # To add BPMN processes and handlers 24 | # Create a directory called bpmn and put them in there 25 | # And uncomment the following line: 26 | # - ./bpmn:/_server_/plugins/CamundaPlugin 27 | -------------------------------------------------------------------------------- /license-scriptcraft.txt: -------------------------------------------------------------------------------- 1 | Portions of this code are from Scriptcraft, including scriptcraft.jar and Scriptcraft-3.4.0.zip. 2 | Some individual files are modified versions, and those files contain a comment at the top identifying them. 3 | Those portions of the code are licensed under the MIT License below. 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2016 Walter Higgins 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | # Blue Oak Model License 2 | 3 | Version 1.0.0 4 | 5 | ## Purpose 6 | 7 | This license gives everyone as much permission to work with 8 | this software as possible, while protecting contributors 9 | from liability. 10 | 11 | ## Acceptance 12 | 13 | In order to receive this license, you must agree to its 14 | rules. The rules of this license are both obligations 15 | under that agreement and conditions to your license. 16 | You must not do anything with this software that triggers 17 | a rule that you cannot or will not follow. 18 | 19 | ## Copyright 20 | 21 | Each contributor licenses you to do everything with this 22 | software that would otherwise infringe that contributor's 23 | copyright in it. 24 | 25 | ## Notices 26 | 27 | You must ensure that everyone who gets a copy of 28 | any part of this software from you, with or without 29 | changes, also gets the text of this license or a link to 30 | . 31 | 32 | ## Excuse 33 | 34 | If anyone notifies you in writing that you have not 35 | complied with [Notices](#notices), you can keep your 36 | license by taking all practical steps to comply within 30 37 | days after the notice. If you do not do so, your license 38 | ends immediately. 39 | 40 | ## Patent 41 | 42 | Each contributor licenses you to do everything with this 43 | software that would otherwise infringe any patent claims 44 | they can license or become able to license. 45 | 46 | ## Reliability 47 | 48 | No contributor can revoke this license. 49 | 50 | ## No Liability 51 | 52 | ***As far as the law allows, this software comes as is, 53 | without any warranty or condition, and no contributor 54 | will be liable to anyone for any damages related to this 55 | software or this license, under any kind of legal claim.*** -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scriptcraft-modular-arch", 3 | "version": "0.3.1", 4 | "description": "Scriptcraft Modular Architecture via Docker", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "echo \"No tests\" && exit 0", 11 | "dev": "cd resources/js && tsc -w", 12 | "build": "cd resources/js && tsc " 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/Magikcraft/scriptcraft-modular-arch.git" 17 | }, 18 | "keywords": [ 19 | "minecraft", 20 | "scriptcraft", 21 | "javascript" 22 | ], 23 | "author": "Josh Wulf ", 24 | "license": "ISC", 25 | "bugs": { 26 | "url": "https://github.com/Magikcraft/scriptcraft-modular-arch/issues" 27 | }, 28 | "homepage": "https://github.com/Magikcraft/scriptcraft-modular-arch#readme", 29 | "husky": { 30 | "hooks": { 31 | "pre-commit": "tsc && git add . && lint-staged" 32 | } 33 | }, 34 | "lint-staged": { 35 | "*.{ts,json,css,md}": [ 36 | "prettier --write", 37 | "git add" 38 | ] 39 | }, 40 | "devDependencies": { 41 | "husky": "^1.3.1", 42 | "lint-staged": "^8.1.5", 43 | "prettier": "^1.16.4", 44 | "typescript": "^3.3.4000" 45 | }, 46 | "private": true, 47 | "dependencies": { 48 | "@types/jasmine": "^3.3.12" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /resources/ScriptCraft-3.4.0-patched.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/ScriptCraft-3.4.0-patched.zip -------------------------------------------------------------------------------- /resources/bukkit.yml: -------------------------------------------------------------------------------- 1 | # This is the main configuration file for Bukkit. 2 | # As you can see, there's actually not that much to configure without any plugins. 3 | # For a reference for any variable inside this file, check out the Bukkit Wiki at 4 | # https://www.spigotmc.org/go/bukkit-yml 5 | # 6 | # If you need help on this file, feel free to join us on irc or leave a message 7 | # on the forums asking for advice. 8 | # 9 | # IRC: #spigot @ irc.spi.gt 10 | # (If this means nothing to you, just go to https://www.spigotmc.org/go/irc ) 11 | # Forums: https://www.spigotmc.org/ 12 | # Bug tracker: https://www.spigotmc.org/go/bugs 13 | 14 | 15 | settings: 16 | allow-end: true 17 | warn-on-overload: true 18 | permissions-file: permissions.yml 19 | update-folder: update 20 | plugin-profiling: false 21 | connection-throttle: 4000 22 | query-plugins: true 23 | deprecated-verbose: default 24 | shutdown-message: Server closed 25 | world-container: worlds 26 | disable: 27 | watchdog: true 28 | spawn-limits: 29 | monsters: 70 30 | animals: 15 31 | water-animals: 5 32 | ambient: 15 33 | chunk-gc: 34 | period-in-ticks: 600 35 | load-threshold: 0 36 | ticks-per: 37 | animal-spawns: 400 38 | monster-spawns: 1 39 | autosave: 6000 40 | aliases: now-in-commands.yml -------------------------------------------------------------------------------- /resources/eula.txt: -------------------------------------------------------------------------------- 1 | #By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula). 2 | #and also agreeing that tacos are tasty. 3 | #Tue Dec 12 11:15:20 AEST 2017 4 | eula=true -------------------------------------------------------------------------------- /resources/h2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/h2.jar -------------------------------------------------------------------------------- /resources/js/INSTALLATION.md: -------------------------------------------------------------------------------- 1 | # Installing the ScriptCraft Modular Architecture Patch 2 | 3 | ```bash 4 | # Add the Magikcraft bootstrap shim to ScriptCraft's normal startup 5 | mv js/sma-bootstrap ${server}/scriptcraft/plugins/ 6 | # Add Jasmine as an SMA plugin 7 | mkdir -p ${server}/scriptcraft-plugins/__jasmine/ 8 | mv js/__jasmine/* ${server}/scriptcraft-plugins/__jasmine/ 9 | ``` 10 | -------------------------------------------------------------------------------- /resources/js/__jasmine/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (_) try { 17 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [op[0] & 2, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | Object.defineProperty(exports, "__esModule", { value: true }); 38 | // Load Jasmine test libraries 39 | var log = function (msg) { return console.log("[Test] " + msg); }; 40 | function loadJasmine() { 41 | return __awaiter(this, void 0, void 0, function () { 42 | var jasmine, env, jsm, failures; 43 | return __generator(this, function (_a) { 44 | global.window = this; 45 | log('Loading Jasmine'); 46 | load("./scriptcraft-plugins/__jasmine/jasmine.js"); 47 | jasmine = jasmineRequire.core(jasmineRequire); 48 | env = jasmine.getEnv(); 49 | jsm = jasmineRequire.interface(jasmine, env); 50 | jsm.describe('Bootloader', function () { 51 | jsm.it('loads Jasmine', function () { 52 | jsm.expect(true).toBe(true); 53 | }); 54 | }); 55 | failures = 0; 56 | env.addReporter({ 57 | jasmineStarted: function (suiteInfo) { 58 | log('Running suite with ' + suiteInfo.totalSpecsDefined + ' tests'); 59 | }, 60 | suiteStarted: function (suite) { 61 | log(' '); 62 | log('\u001b[35m' + suite.description + '...\u001b[0m'); 63 | }, 64 | specStarted: function (result) { 65 | // log(' ' + result.description) 66 | }, 67 | specDone: function (result) { 68 | var status = result.status === 'passed' 69 | ? '\u001b[32mpassed\u001b[0m' 70 | : '\u001b[31mfailed\u001b[0m'; 71 | log(' ' + result.description + ': ' + status); 72 | for (var i = 0; i < result.failedExpectations.length; i++) { 73 | failures++; 74 | log('\u001b[31m Failure: ' + 75 | result.failedExpectations[i].message + 76 | '\u001b[0m'); 77 | // log(' ' + result.failedExpectations[i].stack) 78 | } 79 | }, 80 | suiteDone: function (result) { 81 | // log(JSON.stringify(result)) 82 | }, 83 | jasmineDone: function () { 84 | var success = 0; 85 | if (failures > 0) { 86 | log(failures + " Jasmine tests have failed."); 87 | success = 1; 88 | } 89 | else { 90 | log('All Jasmine tests succeeded!'); 91 | } 92 | log('All tests are now complete.'); // Do not change this string - it is a signal to exit the container 93 | var system = Java.type('java.lang.System'); 94 | system.exit(success); 95 | }, 96 | }); 97 | global.describe = jsm.describe; 98 | global.it = jsm.it; 99 | global.expect = jsm.expect; 100 | // Load all tests 101 | return [2 /*return*/, env]; 102 | }); 103 | }); 104 | } 105 | exports.loadJasmine = loadJasmine; 106 | -------------------------------------------------------------------------------- /resources/js/__jasmine/index.ts: -------------------------------------------------------------------------------- 1 | declare const jasmineRequire 2 | declare const load 3 | // Load Jasmine test libraries 4 | const log = msg => console.log(`[Test] ${msg}`) 5 | 6 | export async function loadJasmine() { 7 | global.window = this 8 | log('Loading Jasmine') 9 | load(`./scriptcraft-plugins/__jasmine/jasmine.js`) 10 | 11 | const jasmine = jasmineRequire.core(jasmineRequire) 12 | const env = jasmine.getEnv() 13 | const jsm = jasmineRequire.interface(jasmine, env) 14 | 15 | jsm.describe('Bootloader', () => { 16 | jsm.it('loads Jasmine', () => { 17 | jsm.expect(true).toBe(true) 18 | }) 19 | }) 20 | 21 | let failures = 0 22 | 23 | env.addReporter({ 24 | jasmineStarted: function(suiteInfo) { 25 | log('Running suite with ' + suiteInfo.totalSpecsDefined + ' tests') 26 | }, 27 | 28 | suiteStarted: function(suite) { 29 | log(' ') 30 | log('\u001b[35m' + suite.description + '...\u001b[0m') 31 | }, 32 | 33 | specStarted: function(result) { 34 | // log(' ' + result.description) 35 | }, 36 | 37 | specDone: function(result) { 38 | const status = 39 | result.status === 'passed' 40 | ? '\u001b[32mpassed\u001b[0m' 41 | : '\u001b[31mfailed\u001b[0m' 42 | log(' ' + result.description + ': ' + status) 43 | 44 | for (var i = 0; i < result.failedExpectations.length; i++) { 45 | failures++ 46 | log( 47 | '\u001b[31m Failure: ' + 48 | result.failedExpectations[i].message + 49 | '\u001b[0m' 50 | ) 51 | // log(' ' + result.failedExpectations[i].stack) 52 | } 53 | }, 54 | suiteDone: function(result) { 55 | // log(JSON.stringify(result)) 56 | }, 57 | 58 | jasmineDone: function() { 59 | let success = 0 60 | if (failures > 0) { 61 | log(`${failures} Jasmine tests have failed.`) 62 | success = 1 63 | } else { 64 | log('All Jasmine tests succeeded!') 65 | } 66 | log('All tests are now complete.') // Do not change this string - it is a signal to exit the container 67 | const system = Java.type('java.lang.System') 68 | system.exit(success) 69 | }, 70 | }) 71 | 72 | global.describe = jsm.describe 73 | global.it = jsm.it 74 | global.expect = jsm.expect 75 | 76 | // Load all tests 77 | return env 78 | } 79 | -------------------------------------------------------------------------------- /resources/js/__types__/global.d.ts: -------------------------------------------------------------------------------- 1 | declare const java: any 2 | declare const Java: any 3 | declare const config: any 4 | declare const global: any 5 | declare const require: any 6 | declare const console: any 7 | declare const __dirname: string 8 | declare const setTimeout: any 9 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/README.md: -------------------------------------------------------------------------------- 1 | # Magikcraft Bootstrap 2 | 3 | Bootstrap sequence: 4 | 5 | 0. Load the ES6 polyfills into the global scope. 6 | 1. Patch `require` so that modules can be resolved from `scriptcraft-plugins`. 7 | 2. Scan the `scriptcraft-plugins` directory. 8 | 3. Autoload the contents of any `plugins` sub-directories in the SMA plugins. 9 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var smaPath = 'scriptcraft-plugins'; 3 | var testMode = java.lang.System.getenv('TEST_MODE') === 'true'; 4 | var requireDebug = java.lang.System.getenv('DEBUG_REQUIRE') === 'true'; 5 | /** 6 | * Cannot use require('magikcraft/*') until we patch require. 7 | */ 8 | var log = function (msg) { return console.log("[SMA] " + msg); }; 9 | log('============================'); 10 | log('=== Scriptcraft Modular Architecture Plugin'); 11 | log('== ©2019 www.magikcraft.io'); 12 | log('== portions ©2016 Walter Higgens'); 13 | log('============================'); 14 | if (testMode) { 15 | log('Test mode enabled.'); 16 | } 17 | /** 18 | * Load ES6 polyfills globally. 19 | */ 20 | require('./polyfills').sync(); // tslint:disable-line 21 | global.__requireDebug = requireDebug; 22 | require = require('./require/patch-require').patch(); 23 | /** 24 | * We use a path relative to the root, 25 | * because we lost our context when we patched require. 26 | */ 27 | log('Loading SMA plugins'); 28 | var SMAPluginLoader = require('./plugins/sma-bootstrap/pluginLoader/PluginLoader').SMAPluginLoader; 29 | var pluginLoader = new SMAPluginLoader(smaPath); 30 | pluginLoader.loadSMAPlugins(testMode).then(function (testLoaders) { 31 | if (testMode) { 32 | var loadJasmine = require('../scriptcraft-plugins/__jasmine').loadJasmine; 33 | loadJasmine().then(function (env) { 34 | log('Loading test suites...'); 35 | testLoaders.map(function (t) { return t && t.loadTests && t.loadTests(); }); 36 | log('Waiting 5 seconds, then starting test suite...'); 37 | setTimeout(function () { return env.execute(); }, 5000); 38 | }); 39 | } 40 | }); 41 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/index.ts: -------------------------------------------------------------------------------- 1 | const smaPath = 'scriptcraft-plugins' 2 | const testMode = java.lang.System.getenv('TEST_MODE') === 'true' 3 | const requireDebug = java.lang.System.getenv('DEBUG_REQUIRE') === 'true' 4 | 5 | /** 6 | * Cannot use require('magikcraft/*') until we patch require. 7 | */ 8 | const log = msg => console.log(`[SMA] ${msg}`) 9 | 10 | log('============================') 11 | log('=== Scriptcraft Modular Architecture Plugin') 12 | log('== ©2019 www.magikcraft.io') 13 | log('== portions ©2016 Walter Higgens') 14 | log('============================') 15 | 16 | if (testMode) { 17 | log('Test mode enabled.') 18 | } 19 | /** 20 | * Load ES6 polyfills globally. 21 | */ 22 | require('./polyfills').sync() // tslint:disable-line 23 | 24 | global.__requireDebug = requireDebug 25 | /** 26 | * Replace the global require with our custom implementation. 27 | * 28 | * The custom require: 29 | * 0. Adds the `scriptcraft-plugins` directory to the search path. 30 | */ 31 | ;(require as any) = require('./require/patch-require').patch() 32 | 33 | /** 34 | * We use a path relative to the root, 35 | * because we lost our context when we patched require. 36 | */ 37 | 38 | log('Loading SMA plugins') 39 | const { 40 | SMAPluginLoader, 41 | } = require('./plugins/sma-bootstrap/pluginLoader/PluginLoader') 42 | const pluginLoader = new SMAPluginLoader(smaPath) 43 | pluginLoader.loadSMAPlugins(testMode).then(testLoaders => { 44 | if (testMode) { 45 | const { loadJasmine } = require('../scriptcraft-plugins/__jasmine') 46 | 47 | loadJasmine().then(env => { 48 | log('Loading test suites...') 49 | testLoaders.map(t => t && t.loadTests && t.loadTests()) 50 | log('Waiting 5 seconds, then starting test suite...') 51 | setTimeout(() => env.execute(), 5000) 52 | }) 53 | } 54 | }) 55 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/lib/find.js: -------------------------------------------------------------------------------- 1 | /* 2 | This file is MIT-licensed code from Scriptcraft 3 | See license-scriptcraft.txt 4 | */ 5 | 'use strict'; 6 | var File = java.io.File; 7 | module.exports = function find(dir, filter) { 8 | var result = []; 9 | function recurse(dir, store) { 10 | var files, 11 | len, 12 | i, 13 | file, 14 | dirfile = new File(dir); 15 | 16 | if (typeof filter == 'undefined') { 17 | files = dirfile.list(); 18 | } else { 19 | files = dirfile.list(filter); 20 | } 21 | len = files.length; 22 | i = 0; 23 | for (; i < len; i++) { 24 | file = new File(dir + '/' + files[i]); 25 | if (file.isDirectory()) { 26 | recurse(file.canonicalPath, store); 27 | } else { 28 | store.push(('' + file.canonicalPath).replace(/\\\\/g, '/')); 29 | } 30 | } 31 | } 32 | recurse(dir, result); 33 | return result; 34 | }; 35 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/lib/loader.js: -------------------------------------------------------------------------------- 1 | /* 2 | This file is modified MIT-licensed code from Scriptcraft 3 | See license-scriptcraft.txt 4 | */ 5 | 'use strict'; 6 | /*global persist,exports,config,__plugin,require*/ 7 | var find = require('./find'); 8 | /* 9 | plugin management 10 | */ 11 | var _plugins = {}; 12 | 13 | var JFile = java.io.File; 14 | 15 | // var PluginsRootDir = new JFile('scriptcraft'); 16 | // var PluginsRootDir = new JFile('scriptcraft-magikcraft'); 17 | 18 | function _plugin( 19 | /* String */ moduleName, 20 | /* Object */ moduleObject, 21 | isPersistent 22 | ) { 23 | // 24 | // don't load plugin more than once 25 | // 26 | if (typeof _plugins[moduleName] != 'undefined') { 27 | return _plugins[moduleName].module; 28 | } 29 | 30 | var pluginData = { persistent: isPersistent, module: moduleObject }; 31 | if (typeof moduleObject.store == 'undefined') { 32 | moduleObject.store = {}; 33 | } 34 | _plugins[moduleName] = pluginData; 35 | 36 | if (isPersistent) { 37 | moduleObject.store = persist(moduleName, moduleObject.store); 38 | } 39 | return moduleObject; 40 | } 41 | 42 | function _autoload(context, pluginDir, options) { 43 | /* 44 | Reload all of the .js files in the given directory 45 | */ 46 | 47 | var sourceFiles = [], 48 | property, 49 | module, 50 | pluginPath; 51 | sourceFiles = find(new JFile(pluginDir)); 52 | 53 | var len = sourceFiles.length; 54 | if (config && config.verbose) { 55 | console.info(len + ' scriptcraft plugins found in ' + pluginDir); 56 | } 57 | 58 | // Alphabetically sort files 59 | sourceFiles = sourceFiles.sort(); 60 | 61 | for (var i = 0; i < len; i++) { 62 | pluginPath = sourceFiles[i]; 63 | if (!pluginPath.match(/\.js$/)) { 64 | continue; 65 | } 66 | module = {}; 67 | 68 | try { 69 | module = require(pluginPath, options); 70 | for (property in module) { 71 | /* 72 | all exports in plugins become members of context object 73 | */ 74 | context[property] = module[property]; 75 | } 76 | } catch (e) { 77 | var msg = 'Plugin ' + pluginPath + ' ' + e; 78 | console.error(msg); 79 | } 80 | } 81 | } 82 | exports.plugin = _plugin; 83 | exports.autoloadAlphabetically = _autoload; 84 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/pluginLoader/PluginLoader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (_) try { 17 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [op[0] & 2, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | Object.defineProperty(exports, "__esModule", { value: true }); 38 | var TestLoader_1 = require("./TestLoader"); 39 | var File = java.io.File; 40 | var log = function (msg) { return console.log("[SMA] " + msg); }; 41 | var loader = require("../lib/loader"); 42 | var canonize = function (file) { return '' + file.getCanonicalPath().replaceAll('\\\\', '/'); }; 43 | var SMAPluginLoader = /** @class */ (function () { 44 | function SMAPluginLoader(smaPath) { 45 | var _this = this; 46 | this.testMode = false; 47 | this.testLoaders = []; 48 | this.filterHiddenFiles = function (file) { return file.getName().indexOf('.') != 0; }; 49 | this.absolutePluginPath = function (p) { return _this.smaPluginsRootDirName + "/" + p; }; 50 | this.smaPluginsRootDir = new File(smaPath); 51 | this.smaPluginsRootDirName = canonize(this.smaPluginsRootDir); 52 | } 53 | SMAPluginLoader.prototype.loadSMAPlugins = function (testMode) { 54 | return __awaiter(this, void 0, void 0, function () { 55 | var smaPlugins, packages; 56 | return __generator(this, function (_a) { 57 | switch (_a.label) { 58 | case 0: 59 | if (__disableSMAPluginLoading) { 60 | log('SMA Plugin loading disabled'); 61 | return [2 /*return*/]; 62 | } 63 | this.testMode = testMode; 64 | log("Searching for SMA plugins in " + this.smaPluginsRootDir); 65 | smaPlugins = this.smaPluginsRootDir.list(this.filterHiddenFiles); 66 | if (!smaPlugins) { 67 | log('No SMA plugins found.'); 68 | return [2 /*return*/]; 69 | } 70 | packages = this.getPackages(smaPlugins); 71 | if (!!testMode) return [3 /*break*/, 2]; 72 | return [4 /*yield*/, this.autoLoad(packages)]; 73 | case 1: 74 | _a.sent(); 75 | _a.label = 2; 76 | case 2: 77 | log('SMA plugin loading complete.'); 78 | return [2 /*return*/, this.testLoaders]; 79 | } 80 | }); 81 | }); 82 | }; 83 | SMAPluginLoader.prototype.autoLoad = function (packages) { 84 | return __awaiter(this, void 0, void 0, function () { 85 | var loadDirs; 86 | var _this = this; 87 | return __generator(this, function (_a) { 88 | switch (_a.label) { 89 | case 0: return [4 /*yield*/, packages]; 90 | case 1: 91 | loadDirs = (_a.sent()) 92 | .map(function (p) { 93 | return _this.getLoadDirectoryFromPackageJson(p) || 94 | _this.checkDefaultPluginsDir(p); 95 | }) 96 | .filter(function (t) { return t; }); 97 | // Map, rather than forEach, for synchronisation 98 | return [2 /*return*/, loadDirs.map(function (d) { 99 | try { 100 | log("Loading " + d + "..."); 101 | loader.autoloadAlphabetically(global, d); 102 | log("Loaded " + d + "."); 103 | } 104 | catch (e) { 105 | log("Error encountered while loading " + d); 106 | log(e); 107 | } 108 | })]; 109 | } 110 | }); 111 | }); 112 | }; 113 | SMAPluginLoader.prototype.getPackages = function (smaPlugins) { 114 | return __awaiter(this, void 0, void 0, function () { 115 | var packages, addPackage, len, i, name, isNamespacedPackageDir, namespace, namespacedDir, namespacedPlugins, n, pkgName; 116 | var _this = this; 117 | return __generator(this, function (_a) { 118 | packages = []; 119 | addPackage = function (name) { return __awaiter(_this, void 0, void 0, function () { 120 | var path, testLoader; 121 | return __generator(this, function (_a) { 122 | log("Found plugin: " + name); 123 | path = this.absolutePluginPath("" + name); 124 | packages.push({ 125 | name: name, 126 | path: path, 127 | }); 128 | if (this.testMode) { 129 | testLoader = new TestLoader_1.TestLoader(path); 130 | testLoader.findTests(); 131 | this.testLoaders.push(testLoader); 132 | } 133 | return [2 /*return*/]; 134 | }); 135 | }); }; 136 | len = smaPlugins.length; 137 | for (i = 0; i < len; i++) { 138 | name = void 0; 139 | if (smaPlugins[i] === '__jasmine' || 140 | smaPlugins[i] === 'node_modules') { 141 | continue; 142 | } 143 | isNamespacedPackageDir = smaPlugins[i].indexOf('@') === 0; 144 | if (isNamespacedPackageDir) { 145 | namespace = smaPlugins[i]; 146 | namespacedDir = new File(this.absolutePluginPath("" + namespace)); 147 | namespacedPlugins = namespacedDir.list(this.filterHiddenFiles); 148 | for (n = 0; n < namespacedPlugins.length; n++) { 149 | pkgName = namespacedPlugins[n]; 150 | name = namespace + "/" + pkgName; 151 | addPackage(name); 152 | } 153 | } 154 | else { 155 | name = smaPlugins[i]; 156 | addPackage(name); 157 | } 158 | } 159 | return [2 /*return*/, packages]; 160 | }); 161 | }); 162 | }; 163 | SMAPluginLoader.prototype.getLoadDirectoryFromPackageJson = function (_a) { 164 | var path = _a.path, name = _a.name; 165 | try { 166 | var pkgJson = require(path + "/package.json"); 167 | log("Found " + name + "/package.json"); 168 | var loadDir = pkgJson.scriptcraft_load_dir || 169 | (pkgJson.smaPluginConfig && 170 | pkgJson.smaPluginConfig.scriptcraft_load_dir); 171 | if (loadDir) { 172 | log(name + " package.json scriptcraft_load_dir: " + loadDir); 173 | log("Scanning " + name + "/" + loadDir); 174 | var file = new File(path + "/" + loadDir); 175 | if (file.isDirectory()) { 176 | log("Found autoload directory " + name + "/" + loadDir); 177 | return ('' + file.canonicalPath).replace(/\\\\/g, '/'); 178 | } 179 | } 180 | } 181 | catch (e) { } 182 | }; 183 | SMAPluginLoader.prototype.checkDefaultPluginsDir = function (_a) { 184 | var path = _a.path, name = _a.name; 185 | var file = new File(path + "/plugins"); 186 | if (file.isDirectory()) { 187 | log("Found autoload directory " + name + "/plugins"); 188 | return ('' + file.canonicalPath).replace(/\\\\/g, '/'); 189 | } 190 | }; 191 | return SMAPluginLoader; 192 | }()); 193 | exports.SMAPluginLoader = SMAPluginLoader; 194 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/pluginLoader/PluginLoader.ts: -------------------------------------------------------------------------------- 1 | declare const __disableSMAPluginLoading: boolean 2 | import { TestLoader } from './TestLoader' 3 | const File = java.io.File 4 | 5 | const log = msg => console.log(`[SMA] ${msg}`) 6 | 7 | const loader = require(`../lib/loader`) 8 | const canonize = file => '' + file.getCanonicalPath().replaceAll('\\\\', '/') 9 | 10 | export class SMAPluginLoader { 11 | smaPluginsRootDirName: any 12 | smaPluginsRootDir: any 13 | testMode: boolean = false 14 | testLoaders: TestLoader[] = [] 15 | constructor(smaPath: string) { 16 | this.smaPluginsRootDir = new File(smaPath) 17 | this.smaPluginsRootDirName = canonize(this.smaPluginsRootDir) 18 | } 19 | 20 | filterHiddenFiles = file => file.getName().indexOf('.') != 0 21 | absolutePluginPath = p => `${this.smaPluginsRootDirName}/${p}` 22 | 23 | async loadSMAPlugins(testMode) { 24 | if (__disableSMAPluginLoading) { 25 | log('SMA Plugin loading disabled') 26 | return 27 | } 28 | this.testMode = testMode 29 | log(`Searching for SMA plugins in ${this.smaPluginsRootDir}`) 30 | 31 | const smaPlugins = this.smaPluginsRootDir.list(this.filterHiddenFiles) 32 | if (!smaPlugins) { 33 | log('No SMA plugins found.') 34 | return 35 | } 36 | 37 | // testLoader is populated in here 38 | const packages = this.getPackages(smaPlugins) 39 | 40 | // Do not run autoloading code if we are in test mode 41 | if (!testMode) { 42 | await this.autoLoad(packages) 43 | } 44 | 45 | log('SMA plugin loading complete.') 46 | return this.testLoaders 47 | } 48 | 49 | async autoLoad(packages) { 50 | const loadDirs = (await packages) 51 | .map( 52 | p => 53 | this.getLoadDirectoryFromPackageJson(p) || 54 | this.checkDefaultPluginsDir(p) 55 | ) 56 | .filter(t => t) 57 | 58 | // Map, rather than forEach, for synchronisation 59 | return loadDirs.map(d => { 60 | try { 61 | log(`Loading ${d}...`) 62 | loader.autoloadAlphabetically(global, d) 63 | log(`Loaded ${d}.`) 64 | } catch (e) { 65 | log(`Error encountered while loading ${d}`) 66 | log(e) 67 | } 68 | }) 69 | } 70 | 71 | async getPackages(smaPlugins: any) { 72 | const packages: { name: string; path: string }[] = [] 73 | 74 | const addPackage = async (name: string) => { 75 | log(`Found plugin: ${name}`) 76 | const path = this.absolutePluginPath(`${name}`) 77 | packages.push({ 78 | name, 79 | path, 80 | }) 81 | if (this.testMode) { 82 | const testLoader = new TestLoader(path) 83 | testLoader.findTests() 84 | this.testLoaders.push(testLoader) 85 | } 86 | } 87 | 88 | const len = smaPlugins.length 89 | for (let i = 0; i < len; i++) { 90 | let name 91 | if ( 92 | smaPlugins[i] === '__jasmine' || 93 | smaPlugins[i] === 'node_modules' 94 | ) { 95 | continue 96 | } 97 | // Check for package namespaces like @magikcraft or @scriptcraft 98 | const isNamespacedPackageDir = smaPlugins[i].indexOf('@') === 0 99 | if (isNamespacedPackageDir) { 100 | const namespace = smaPlugins[i] 101 | const namespacedDir = new File( 102 | this.absolutePluginPath(`${namespace}`) 103 | ) 104 | const namespacedPlugins = namespacedDir.list( 105 | this.filterHiddenFiles 106 | ) 107 | for (let n = 0; n < namespacedPlugins.length; n++) { 108 | const pkgName = namespacedPlugins[n] 109 | name = `${namespace}/${pkgName}` 110 | addPackage(name) 111 | } 112 | } else { 113 | name = smaPlugins[i] 114 | addPackage(name) 115 | } 116 | } 117 | return packages 118 | } 119 | 120 | getLoadDirectoryFromPackageJson({ path, name }) { 121 | try { 122 | const pkgJson = require(`${path}/package.json`) 123 | log(`Found ${name}/package.json`) 124 | const loadDir = 125 | pkgJson.scriptcraft_load_dir || 126 | (pkgJson.smaPluginConfig && 127 | pkgJson.smaPluginConfig.scriptcraft_load_dir) 128 | if (loadDir) { 129 | log(`${name} package.json scriptcraft_load_dir: ${loadDir}`) 130 | log(`Scanning ${name}/${loadDir}`) 131 | const file = new File(`${path}/${loadDir}`) 132 | if (file.isDirectory()) { 133 | log(`Found autoload directory ${name}/${loadDir}`) 134 | return ('' + file.canonicalPath).replace(/\\\\/g, '/') 135 | } 136 | } 137 | } catch (e) {} 138 | } 139 | 140 | checkDefaultPluginsDir({ path, name }) { 141 | const file = new File(`${path}/plugins`) 142 | if (file.isDirectory()) { 143 | log(`Found autoload directory ${name}/plugins`) 144 | return ('' + file.canonicalPath).replace(/\\\\/g, '/') 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/pluginLoader/TestLoader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var File = java.io.File; 4 | var log = function (msg) { return console.log("[SMA: Test] " + msg); }; 5 | var canonize = function (file) { return '' + file.getCanonicalPath().replaceAll('\\\\', '/'); }; 6 | var filterTestDirs = function (dir, file) { return file.indexOf('__test') == 0; }; 7 | var filterTestFiles = function (dir, file) { return file.indexOf('.spec.js') != -1; }; 8 | var TestLoader = /** @class */ (function () { 9 | function TestLoader(path) { 10 | this.tests = []; 11 | this.path = new File(path); 12 | } 13 | TestLoader.prototype.findTests = function () { 14 | var _this = this; 15 | log("Looking for tests in " + this.path); 16 | return Java.from(this.path.list(filterTestDirs)) 17 | .map(function (n) { 18 | var testDirPath = _this.path + "/" + n; 19 | log("Looking for tests in " + testDirPath); 20 | var fileInTestDir = new File(testDirPath); 21 | if (fileInTestDir.isDirectory()) { 22 | Java.from(fileInTestDir.list(filterTestFiles)).map(function (t) { 23 | var specPath = testDirPath + "/" + t; 24 | log("Loading " + specPath); 25 | _this.tests.push(specPath); // canonize(`${t}`)) 26 | return specPath; 27 | }); 28 | } 29 | }) 30 | .filter(function (l) { return l && l.length > 0; }); 31 | }; 32 | TestLoader.prototype.loadTests = function () { 33 | return this.tests.map(function (t) { return require(t); }); 34 | }; 35 | return TestLoader; 36 | }()); 37 | exports.TestLoader = TestLoader; 38 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/pluginLoader/TestLoader.ts: -------------------------------------------------------------------------------- 1 | const File = java.io.File 2 | const log = msg => console.log(`[SMA: Test] ${msg}`) 3 | 4 | const canonize = file => '' + file.getCanonicalPath().replaceAll('\\\\', '/') 5 | const filterTestDirs = (dir, file) => file.indexOf('__test') == 0 6 | const filterTestFiles = (dir, file) => file.indexOf('.spec.js') != -1 7 | 8 | export class TestLoader { 9 | path: any 10 | tests: string[] = [] 11 | 12 | constructor(path: string) { 13 | this.path = new File(path) 14 | } 15 | 16 | findTests() { 17 | log(`Looking for tests in ${this.path}`) 18 | return Java.from(this.path.list(filterTestDirs)) 19 | .map(n => { 20 | const testDirPath = `${this.path}/${n}` 21 | log(`Looking for tests in ${testDirPath}`) 22 | 23 | const fileInTestDir = new File(testDirPath) 24 | if (fileInTestDir.isDirectory()) { 25 | Java.from(fileInTestDir.list(filterTestFiles)).map(t => { 26 | const specPath = `${testDirPath}/${t}` 27 | log(`Loading ${specPath}`) 28 | this.tests.push(specPath) // canonize(`${t}`)) 29 | return specPath 30 | }) 31 | } 32 | }) 33 | .filter(l => l && l.length > 0) 34 | } 35 | 36 | loadTests() { 37 | return this.tests.map(t => require(t)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/array-filter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | console.log('= Array.filter'); 3 | if (!Array.prototype.filter) 4 | Array.prototype.filter = function (func, thisArg) { 5 | 'use strict'; 6 | if (!((typeof func === 'function') && this)) 7 | throw new TypeError(); 8 | var len = this.length >>> 0, res = new Array(len), // preallocate array 9 | t = this, c = 0, i = -1; 10 | if (thisArg === undefined) 11 | while (++i !== len) 12 | // checks to see if the key was set 13 | if (i in this) 14 | if (func(t[i], i, t)) 15 | res[c++] = t[i]; 16 | else 17 | while (++i !== len) 18 | // checks to see if the key was set 19 | if (i in this) 20 | if (func.call(thisArg, t[i], i, t)) 21 | res[c++] = t[i]; 22 | res.length = c; // shrink down array to proper size 23 | return res; 24 | }; 25 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/array-filter.ts: -------------------------------------------------------------------------------- 1 | console.log('= Array.filter') 2 | if (!Array.prototype.filter) 3 | Array.prototype.filter = function(func, thisArg) { 4 | 'use strict'; 5 | if ( ! ((typeof func === 'function') && this) ) 6 | throw new TypeError(); 7 | 8 | var len = this.length >>> 0, 9 | res = new Array(len), // preallocate array 10 | t = this, c = 0, i = -1; 11 | if (thisArg === undefined) 12 | while (++i !== len) 13 | // checks to see if the key was set 14 | if (i in this) 15 | if (func(t[i], i, t)) 16 | res[c++] = t[i]; 17 | else 18 | while (++i !== len) 19 | // checks to see if the key was set 20 | if (i in this) 21 | if (func.call(thisArg, t[i], i, t)) 22 | res[c++] = t[i]; 23 | 24 | res.length = c; // shrink down array to proper size 25 | return res; 26 | }; 27 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/array-find.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | console.log('= Array.find'); 3 | // https://tc39.github.io/ecma262/#sec-array.prototype.find 4 | if (!Array.prototype.find) { 5 | Object.defineProperty(Array.prototype, 'find', { 6 | value: function (predicate) { 7 | // 1. Let O be ? ToObject(this value). 8 | if (this == null) { 9 | throw new TypeError('"this" is null or not defined'); 10 | } 11 | var o = Object(this); 12 | // 2. Let len be ? ToLength(? Get(O, "length")). 13 | var len = o.length >>> 0; 14 | // 3. If IsCallable(predicate) is false, throw a TypeError exception. 15 | if (typeof predicate !== 'function') { 16 | throw new TypeError('predicate must be a function'); 17 | } 18 | // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. 19 | var thisArg = arguments[1]; 20 | // 5. Let k be 0. 21 | var k = 0; 22 | // 6. Repeat, while k < len 23 | while (k < len) { 24 | // a. Let Pk be ! ToString(k). 25 | // b. Let kValue be ? Get(O, Pk). 26 | // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). 27 | // d. If testResult is true, return kValue. 28 | var kValue = o[k]; 29 | if (predicate.call(thisArg, kValue, k, o)) { 30 | return kValue; 31 | } 32 | // e. Increase k by 1. 33 | k++; 34 | } 35 | // 7. Return undefined. 36 | return undefined; 37 | } 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/array-find.ts: -------------------------------------------------------------------------------- 1 | console.log('= Array.find') 2 | // https://tc39.github.io/ecma262/#sec-array.prototype.find 3 | if (!Array.prototype.find) { 4 | Object.defineProperty(Array.prototype, 'find', { 5 | value: function(predicate) { 6 | // 1. Let O be ? ToObject(this value). 7 | if (this == null) { 8 | throw new TypeError('"this" is null or not defined'); 9 | } 10 | 11 | var o = Object(this); 12 | 13 | // 2. Let len be ? ToLength(? Get(O, "length")). 14 | var len = o.length >>> 0; 15 | 16 | // 3. If IsCallable(predicate) is false, throw a TypeError exception. 17 | if (typeof predicate !== 'function') { 18 | throw new TypeError('predicate must be a function'); 19 | } 20 | 21 | // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. 22 | var thisArg = arguments[1]; 23 | 24 | // 5. Let k be 0. 25 | var k = 0; 26 | 27 | // 6. Repeat, while k < len 28 | while (k < len) { 29 | // a. Let Pk be ! ToString(k). 30 | // b. Let kValue be ? Get(O, Pk). 31 | // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). 32 | // d. If testResult is true, return kValue. 33 | var kValue = o[k]; 34 | if (predicate.call(thisArg, kValue, k, o)) { 35 | return kValue; 36 | } 37 | // e. Increase k by 1. 38 | k++; 39 | } 40 | 41 | // 7. Return undefined. 42 | return undefined; 43 | } 44 | }); 45 | } -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/array-from.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | console.log('= Array.from'); 3 | // Production steps of ECMA-262, Edition 6, 22.1.2.1 4 | if (!Array.from) { 5 | Array.from = (function () { 6 | var toStr = Object.prototype.toString; 7 | var isCallable = function (fn) { 8 | return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; 9 | }; 10 | var toInteger = function (value) { 11 | var number = Number(value); 12 | if (isNaN(number)) { 13 | return 0; 14 | } 15 | if (number === 0 || !isFinite(number)) { 16 | return number; 17 | } 18 | return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); 19 | }; 20 | var maxSafeInteger = Math.pow(2, 53) - 1; 21 | var toLength = function (value) { 22 | var len = toInteger(value); 23 | return Math.min(Math.max(len, 0), maxSafeInteger); 24 | }; 25 | // The length property of the from method is 1. 26 | return function from(arrayLike /*, mapFn, thisArg */) { 27 | // 1. Let C be the this value. 28 | var C = this; 29 | // 2. Let items be ToObject(arrayLike). 30 | var items = Object(arrayLike); 31 | // 3. ReturnIfAbrupt(items). 32 | if (arrayLike == null) { 33 | throw new TypeError('Array.from requires an array-like object - not null or undefined'); 34 | } 35 | // 4. If mapfn is undefined, then let mapping be false. 36 | var mapFn = arguments.length > 1 ? arguments[1] : void undefined; 37 | var T; 38 | if (typeof mapFn !== 'undefined') { 39 | // 5. else 40 | // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. 41 | if (!isCallable(mapFn)) { 42 | throw new TypeError('Array.from: when provided, the second argument must be a function'); 43 | } 44 | // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. 45 | if (arguments.length > 2) { 46 | T = arguments[2]; 47 | } 48 | } 49 | // 10. Let lenValue be Get(items, "length"). 50 | // 11. Let len be ToLength(lenValue). 51 | var len = toLength(items.length); 52 | // 13. If IsConstructor(C) is true, then 53 | // 13. a. Let A be the result of calling the [[Construct]] internal method 54 | // of C with an argument list containing the single item len. 55 | // 14. a. Else, Let A be ArrayCreate(len). 56 | var A = isCallable(C) ? Object(new C(len)) : new Array(len); 57 | // 16. Let k be 0. 58 | var k = 0; 59 | // 17. Repeat, while k < len… (also steps a - h) 60 | var kValue; 61 | while (k < len) { 62 | kValue = items[k]; 63 | if (mapFn) { 64 | A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); 65 | } 66 | else { 67 | A[k] = kValue; 68 | } 69 | k += 1; 70 | } 71 | // 18. Let putStatus be Put(A, "length", len, true). 72 | A.length = len; 73 | // 20. Return A. 74 | return A; 75 | }; 76 | }()); 77 | } 78 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/array-from.ts: -------------------------------------------------------------------------------- 1 | console.log('= Array.from') 2 | // Production steps of ECMA-262, Edition 6, 22.1.2.1 3 | if (!Array.from) { 4 | Array.from = (function () { 5 | var toStr = Object.prototype.toString; 6 | var isCallable = function (fn) { 7 | return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; 8 | }; 9 | var toInteger = function (value) { 10 | var number = Number(value); 11 | if (isNaN(number)) { return 0; } 12 | if (number === 0 || !isFinite(number)) { return number; } 13 | return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); 14 | }; 15 | var maxSafeInteger = Math.pow(2, 53) - 1; 16 | var toLength = function (value) { 17 | var len = toInteger(value); 18 | return Math.min(Math.max(len, 0), maxSafeInteger); 19 | }; 20 | 21 | // The length property of the from method is 1. 22 | return function from(arrayLike/*, mapFn, thisArg */) { 23 | // 1. Let C be the this value. 24 | var C = this; 25 | 26 | // 2. Let items be ToObject(arrayLike). 27 | var items = Object(arrayLike); 28 | 29 | // 3. ReturnIfAbrupt(items). 30 | if (arrayLike == null) { 31 | throw new TypeError('Array.from requires an array-like object - not null or undefined'); 32 | } 33 | 34 | // 4. If mapfn is undefined, then let mapping be false. 35 | var mapFn = arguments.length > 1 ? arguments[1] : void undefined; 36 | var T; 37 | if (typeof mapFn !== 'undefined') { 38 | // 5. else 39 | // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. 40 | if (!isCallable(mapFn)) { 41 | throw new TypeError('Array.from: when provided, the second argument must be a function'); 42 | } 43 | 44 | // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. 45 | if (arguments.length > 2) { 46 | T = arguments[2]; 47 | } 48 | } 49 | 50 | // 10. Let lenValue be Get(items, "length"). 51 | // 11. Let len be ToLength(lenValue). 52 | var len = toLength(items.length); 53 | 54 | // 13. If IsConstructor(C) is true, then 55 | // 13. a. Let A be the result of calling the [[Construct]] internal method 56 | // of C with an argument list containing the single item len. 57 | // 14. a. Else, Let A be ArrayCreate(len). 58 | var A = isCallable(C) ? Object(new C(len)) : new Array(len); 59 | 60 | // 16. Let k be 0. 61 | var k = 0; 62 | // 17. Repeat, while k < len… (also steps a - h) 63 | var kValue; 64 | while (k < len) { 65 | kValue = items[k]; 66 | if (mapFn) { 67 | A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); 68 | } else { 69 | A[k] = kValue; 70 | } 71 | k += 1; 72 | } 73 | // 18. Let putStatus be Put(A, "length", len, true). 74 | A.length = len; 75 | // 20. Return A. 76 | return A; 77 | }; 78 | }()); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/array-includes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | console.log('= Array.includes'); 3 | if (!Array.prototype.includes) { 4 | Object.defineProperty(Array.prototype, 'includes', { 5 | value: function (searchElement, fromIndex) { 6 | if (this == null) { 7 | throw new TypeError('"this" is null or not defined'); 8 | } 9 | // 1. Let O be ? ToObject(this value). 10 | var o = Object(this); 11 | // 2. Let len be ? ToLength(? Get(O, "length")). 12 | var len = o.length >>> 0; 13 | // 3. If len is 0, return false. 14 | if (len === 0) { 15 | return false; 16 | } 17 | // 4. Let n be ? ToInteger(fromIndex). 18 | // (If fromIndex is undefined, this step produces the value 0.) 19 | var n = fromIndex | 0; 20 | // 5. If n ≥ 0, then 21 | // a. Let k be n. 22 | // 6. Else n < 0, 23 | // a. Let k be len + n. 24 | // b. If k < 0, let k be 0. 25 | var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); 26 | function sameValueZero(x, y) { 27 | return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)); 28 | } 29 | // 7. Repeat, while k < len 30 | while (k < len) { 31 | // a. Let elementK be the result of ? Get(O, ! ToString(k)). 32 | // b. If SameValueZero(searchElement, elementK) is true, return true. 33 | if (sameValueZero(o[k], searchElement)) { 34 | return true; 35 | } 36 | // c. Increase k by 1. 37 | k++; 38 | } 39 | // 8. Return false 40 | return false; 41 | } 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/array-includes.ts: -------------------------------------------------------------------------------- 1 | console.log('= Array.includes') 2 | if (!(Array.prototype as any).includes) { 3 | Object.defineProperty(Array.prototype, 'includes', { 4 | value: function(searchElement, fromIndex) { 5 | 6 | if (this == null) { 7 | throw new TypeError('"this" is null or not defined'); 8 | } 9 | 10 | // 1. Let O be ? ToObject(this value). 11 | var o = Object(this); 12 | 13 | // 2. Let len be ? ToLength(? Get(O, "length")). 14 | var len = o.length >>> 0; 15 | 16 | // 3. If len is 0, return false. 17 | if (len === 0) { 18 | return false; 19 | } 20 | 21 | // 4. Let n be ? ToInteger(fromIndex). 22 | // (If fromIndex is undefined, this step produces the value 0.) 23 | var n = fromIndex | 0; 24 | 25 | // 5. If n ≥ 0, then 26 | // a. Let k be n. 27 | // 6. Else n < 0, 28 | // a. Let k be len + n. 29 | // b. If k < 0, let k be 0. 30 | var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); 31 | 32 | function sameValueZero(x, y) { 33 | return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)); 34 | } 35 | 36 | // 7. Repeat, while k < len 37 | while (k < len) { 38 | // a. Let elementK be the result of ? Get(O, ! ToString(k)). 39 | // b. If SameValueZero(searchElement, elementK) is true, return true. 40 | if (sameValueZero(o[k], searchElement)) { 41 | return true; 42 | } 43 | // c. Increase k by 1. 44 | k++; 45 | } 46 | 47 | // 8. Return false 48 | return false; 49 | } 50 | }); 51 | } -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/event-emitter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | console.log('= EventEmitter'); 3 | /*! 4 | * EventEmitter v5.2.2 - git.io/ee 5 | * Unlicense - http://unlicense.org/ 6 | * Oliver Caldwell - http://oli.me.uk/ 7 | * @preserve 8 | */ 9 | (function (e) { 10 | "use strict"; 11 | function t() { } 12 | function n(e, t) { for (var n = e.length; n--;) 13 | if (e[n].listener === t) 14 | return n; return -1; } 15 | function r(e) { return function () { return this[e].apply(this, arguments); }; } 16 | function i(e) { return "function" == typeof e || e instanceof RegExp || !(!e || "object" != typeof e) && i(e.listener); } 17 | var s = t.prototype, o = e.EventEmitter; 18 | s.getListeners = function (e) { var t, n, r = this._getEvents(); if (e instanceof RegExp) { 19 | t = {}; 20 | for (n in r) 21 | r.hasOwnProperty(n) && e.test(n) && (t[n] = r[n]); 22 | } 23 | else 24 | t = r[e] || (r[e] = []); return t; }, s.flattenListeners = function (e) { var t, n = []; for (t = 0; t < e.length; t += 1) 25 | n.push(e[t].listener); return n; }, s.getListenersAsObject = function (e) { var t, n = this.getListeners(e); return n instanceof Array && (t = {}, t[e] = n), t || n; }, s.addListener = function (e, t) { if (!i(t)) 26 | throw new TypeError("listener must be a function"); var r, s = this.getListenersAsObject(e), o = "object" == typeof t; for (r in s) 27 | s.hasOwnProperty(r) && -1 === n(s[r], t) && s[r].push(o ? t : { listener: t, once: !1 }); return this; }, s.on = r("addListener"), s.addOnceListener = function (e, t) { return this.addListener(e, { listener: t, once: !0 }); }, s.once = r("addOnceListener"), s.defineEvent = function (e) { return this.getListeners(e), this; }, s.defineEvents = function (e) { for (var t = 0; t < e.length; t += 1) 28 | this.defineEvent(e[t]); return this; }, s.removeListener = function (e, t) { var r, i, s = this.getListenersAsObject(e); for (i in s) 29 | s.hasOwnProperty(i) && -1 !== (r = n(s[i], t)) && s[i].splice(r, 1); return this; }, s.off = r("removeListener"), s.addListeners = function (e, t) { return this.manipulateListeners(!1, e, t); }, s.removeListeners = function (e, t) { return this.manipulateListeners(!0, e, t); }, s.manipulateListeners = function (e, t, n) { var r, i, s = e ? this.removeListener : this.addListener, o = e ? this.removeListeners : this.addListeners; if ("object" != typeof t || t instanceof RegExp) 30 | for (r = n.length; r--;) 31 | s.call(this, t, n[r]); 32 | else 33 | for (r in t) 34 | t.hasOwnProperty(r) && (i = t[r]) && ("function" == typeof i ? s.call(this, r, i) : o.call(this, r, i)); return this; }, s.removeEvent = function (e) { var t, n = typeof e, r = this._getEvents(); if ("string" === n) 35 | delete r[e]; 36 | else if (e instanceof RegExp) 37 | for (t in r) 38 | r.hasOwnProperty(t) && e.test(t) && delete r[t]; 39 | else 40 | delete this._events; return this; }, s.removeAllListeners = r("removeEvent"), s.emitEvent = function (e, t) { var n, r, i, s, o = this.getListenersAsObject(e); for (s in o) 41 | if (o.hasOwnProperty(s)) 42 | for (n = o[s].slice(0), i = 0; i < n.length; i++) 43 | r = n[i], !0 === r.once && this.removeListener(e, r.listener), r.listener.apply(this, t || []) === this._getOnceReturnValue() && this.removeListener(e, r.listener); return this; }, s.trigger = r("emitEvent"), s.emit = function (e) { var t = Array.prototype.slice.call(arguments, 1); return this.emitEvent(e, t); }, s.setOnceReturnValue = function (e) { return this._onceReturnValue = e, this; }, s._getOnceReturnValue = function () { return !this.hasOwnProperty("_onceReturnValue") || this._onceReturnValue; }, s._getEvents = function () { return this._events || (this._events = {}); }, t.noConflict = function () { return e.EventEmitter = o, t; }, "function" == typeof define && define.amd ? define(function () { return t; }) : "object" == typeof module && module.exports ? module.exports = t : e.EventEmitter = t; 44 | })(this || {}); 45 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/event-emitter.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable 2 | declare const define: any, module: any; 3 | 4 | console.log('= EventEmitter'); 5 | 6 | /*! 7 | * EventEmitter v5.2.2 - git.io/ee 8 | * Unlicense - http://unlicense.org/ 9 | * Oliver Caldwell - http://oli.me.uk/ 10 | * @preserve 11 | */ 12 | (function(e){"use strict";function t(){}function n(e,t){for(var n=e.length;n--;)if(e[n].listener===t)return n;return-1}function r(e){return function(){return this[e].apply(this,arguments)}}function i(e){return"function"==typeof e||e instanceof RegExp||!(!e||"object"!=typeof e)&&i(e.listener)}var s=t.prototype,o=e.EventEmitter;s.getListeners=function(e){var t,n,r=this._getEvents();if(e instanceof RegExp){t={};for(n in r)r.hasOwnProperty(n)&&e.test(n)&&(t[n]=r[n])}else t=r[e]||(r[e]=[]);return t},s.flattenListeners=function(e){var t,n=[] as any;for(t=0;t console.log(`Polyfill ${msg}`); 23 | 24 | log('============================') 25 | log('= Loading ES6 Polyfills...') 26 | global.EventEmitter = require('./event-emitter') 27 | 28 | const _sync = [ 29 | global.EventEmitter, 30 | require('./array-from'), 31 | require('./object-assign'), 32 | require('./promise'), 33 | require('./string'), 34 | require('./array-filter'), 35 | require('./array-find'), 36 | require('./array-includes') 37 | ] 38 | 39 | log('============================') 40 | 41 | export const sync = () => _sync 42 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/object-assign.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | console.log('= Object.assign'); 3 | if (typeof Object.assign != 'function') { 4 | Object.assign = function (target, varArgs) { 5 | 'use strict'; 6 | if (target == null) { // TypeError if undefined or null 7 | throw new TypeError('Cannot convert undefined or null to object'); 8 | } 9 | var to = Object(target); 10 | for (var index = 1; index < arguments.length; index++) { 11 | var nextSource = arguments[index]; 12 | if (nextSource != null) { // Skip over if undefined or null 13 | for (var nextKey in nextSource) { 14 | // Avoid bugs when hasOwnProperty is shadowed 15 | if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 16 | to[nextKey] = nextSource[nextKey]; 17 | } 18 | } 19 | } 20 | } 21 | return to; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/object-assign.ts: -------------------------------------------------------------------------------- 1 | console.log('= Object.assign') 2 | 3 | if (typeof Object.assign != 'function') { 4 | Object.assign = function (target, varArgs) { // .length of function is 2 5 | 'use strict'; 6 | if (target == null) { // TypeError if undefined or null 7 | throw new TypeError('Cannot convert undefined or null to object'); 8 | } 9 | 10 | var to = Object(target); 11 | 12 | for (var index = 1; index < arguments.length; index++) { 13 | var nextSource = arguments[index]; 14 | 15 | if (nextSource != null) { // Skip over if undefined or null 16 | for (var nextKey in nextSource) { 17 | // Avoid bugs when hasOwnProperty is shadowed 18 | if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 19 | to[nextKey] = nextSource[nextKey]; 20 | } 21 | } 22 | } 23 | } 24 | return to; 25 | }; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/promise.js: -------------------------------------------------------------------------------- 1 | !(function(e, n) { 2 | 'object' == typeof exports && 'undefined' != typeof module 3 | ? n() 4 | : 'function' == typeof define && define.amd 5 | ? define(n) 6 | : n() 7 | })(0, function() { 8 | 'use strict' 9 | function e(e) { 10 | var n = this.constructor 11 | return this.then( 12 | function(t) { 13 | return n.resolve(e()).then(function() { 14 | return t 15 | }) 16 | }, 17 | function(t) { 18 | return n.resolve(e()).then(function() { 19 | return n.reject(t) 20 | }) 21 | } 22 | ) 23 | } 24 | function n() {} 25 | function t(e) { 26 | if (!(this instanceof t)) 27 | throw new TypeError('Promises must be constructed via new') 28 | if ('function' != typeof e) throw new TypeError('not a function') 29 | ;(this._state = 0), 30 | (this._handled = !1), 31 | (this._value = undefined), 32 | (this._deferreds = []), 33 | u(e, this) 34 | } 35 | function o(e, n) { 36 | for (; 3 === e._state; ) e = e._value 37 | 0 !== e._state 38 | ? ((e._handled = !0), 39 | t._immediateFn(function() { 40 | var t = 1 === e._state ? n.onFulfilled : n.onRejected 41 | if (null !== t) { 42 | var o 43 | try { 44 | o = t(e._value) 45 | } catch (f) { 46 | return void i(n.promise, f) 47 | } 48 | r(n.promise, o) 49 | } else (1 === e._state ? r : i)(n.promise, e._value) 50 | })) 51 | : e._deferreds.push(n) 52 | } 53 | function r(e, n) { 54 | try { 55 | if (n === e) 56 | throw new TypeError('A promise cannot be resolved with itself.') 57 | if (n && ('object' == typeof n || 'function' == typeof n)) { 58 | var o = n.then 59 | if (n instanceof t) 60 | return (e._state = 3), (e._value = n), void f(e) 61 | if ('function' == typeof o) 62 | return void u( 63 | (function(e, n) { 64 | return function() { 65 | e.apply(n, arguments) 66 | } 67 | })(o, n), 68 | e 69 | ) 70 | } 71 | ;(e._state = 1), (e._value = n), f(e) 72 | } catch (r) { 73 | i(e, r) 74 | } 75 | } 76 | function i(e, n) { 77 | ;(e._state = 2), (e._value = n), f(e) 78 | } 79 | function f(e) { 80 | 2 === e._state && 81 | 0 === e._deferreds.length && 82 | t._immediateFn(function() { 83 | e._handled || t._unhandledRejectionFn(e._value) 84 | }) 85 | for (var n = 0, r = e._deferreds.length; r > n; n++) 86 | o(e, e._deferreds[n]) 87 | e._deferreds = null 88 | } 89 | function u(e, n) { 90 | var t = !1 91 | try { 92 | e( 93 | function(e) { 94 | t || ((t = !0), r(n, e)) 95 | }, 96 | function(e) { 97 | t || ((t = !0), i(n, e)) 98 | } 99 | ) 100 | } catch (o) { 101 | if (t) return 102 | ;(t = !0), i(n, o) 103 | } 104 | } 105 | var c = setTimeout 106 | ;(t.prototype['catch'] = function(e) { 107 | return this.then(null, e) 108 | }), 109 | (t.prototype.then = function(e, t) { 110 | var r = new this.constructor(n) 111 | return ( 112 | o( 113 | this, 114 | new function(e, n, t) { 115 | ;(this.onFulfilled = 'function' == typeof e ? e : null), 116 | (this.onRejected = 117 | 'function' == typeof n ? n : null), 118 | (this.promise = t) 119 | }(e, t, r) 120 | ), 121 | r 122 | ) 123 | }), 124 | (t.prototype['finally'] = e), 125 | (t.all = function(e) { 126 | return new t(function(n, t) { 127 | function o(e, f) { 128 | try { 129 | if ( 130 | f && 131 | ('object' == typeof f || 'function' == typeof f) 132 | ) { 133 | var u = f.then 134 | if ('function' == typeof u) 135 | return void u.call( 136 | f, 137 | function(n) { 138 | o(e, n) 139 | }, 140 | t 141 | ) 142 | } 143 | ;(r[e] = f), 0 == --i && n(r) 144 | } catch (c) { 145 | t(c) 146 | } 147 | } 148 | if (!e || 'undefined' == typeof e.length) 149 | throw new TypeError('Promise.all accepts an array') 150 | var r = Array.prototype.slice.call(e) 151 | if (0 === r.length) return n([]) 152 | for (var i = r.length, f = 0; r.length > f; f++) o(f, r[f]) 153 | }) 154 | }), 155 | (t.resolve = function(e) { 156 | return e && 'object' == typeof e && e.constructor === t 157 | ? e 158 | : new t(function(n) { 159 | n(e) 160 | }) 161 | }), 162 | (t.reject = function(e) { 163 | return new t(function(n, t) { 164 | t(e) 165 | }) 166 | }), 167 | (t.race = function(e) { 168 | return new t(function(n, t) { 169 | for (var o = 0, r = e.length; r > o; o++) e[o].then(n, t) 170 | }) 171 | }), 172 | (t._immediateFn = 173 | ('function' == typeof setImmediate && 174 | function(e) { 175 | setImmediate(e) 176 | }) || 177 | function(e) { 178 | c(e, 0) 179 | }), 180 | (t._unhandledRejectionFn = function(e) { 181 | ;(void 0 !== console && 182 | console && 183 | console.warn('Possible Unhandled Promise Rejection:')) || 184 | console.warn(e) 185 | }) 186 | var l = (function() { 187 | if ('undefined' != typeof self) return self 188 | if ('undefined' != typeof window) return window 189 | if ('undefined' != typeof global) return global 190 | throw Error('unable to locate global object') 191 | })() 192 | 'Promise' in l 193 | ? l.Promise.prototype['finally'] || (l.Promise.prototype['finally'] = e) 194 | : (l.Promise = t) 195 | }) 196 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/string.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | console.log('= String includes, repeat, padStart, padEnd'); 3 | if (!String.prototype.includes) { 4 | String.prototype.includes = function (search, start) { 5 | 'use strict'; 6 | if (typeof start !== 'number') { 7 | start = 0; 8 | } 9 | if (start + search.length > this.length) { 10 | return false; 11 | } 12 | else { 13 | return this.indexOf(search, start) !== -1; 14 | } 15 | }; 16 | } 17 | if (!String.prototype.repeat) { 18 | String.prototype.repeat = function (count) { 19 | 'use strict'; 20 | if (this == null) { 21 | throw new TypeError('can\'t convert ' + this + ' to object'); 22 | } 23 | var str = '' + this; 24 | count = +count; 25 | if (count != count) { 26 | count = 0; 27 | } 28 | if (count < 0) { 29 | throw new RangeError('repeat count must be non-negative'); 30 | } 31 | if (count == Infinity) { 32 | throw new RangeError('repeat count must be less than infinity'); 33 | } 34 | count = Math.floor(count); 35 | if (str.length == 0 || count == 0) { 36 | return ''; 37 | } 38 | // Ensuring count is a 31-bit integer allows us to heavily optimize the 39 | // main part. But anyway, most current (August 2014) browsers can't handle 40 | // strings 1 << 28 chars or longer, so: 41 | if (str.length * count >= 1 << 28) { 42 | throw new RangeError('repeat count must not overflow maximum string size'); 43 | } 44 | var rpt = ''; 45 | for (var i = 0; i < count; i++) { 46 | rpt += str; 47 | } 48 | return rpt; 49 | }; 50 | } 51 | // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js 52 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart 53 | if (!String.prototype.padStart) { 54 | String.prototype.padStart = function padStart(targetLength, padString) { 55 | targetLength = targetLength >> 0; //floor if number or convert non-number to 0; 56 | padString = String(padString || ' '); 57 | if (this.length > targetLength) { 58 | return String(this); 59 | } 60 | else { 61 | targetLength = targetLength - this.length; 62 | if (targetLength > padString.length) { 63 | padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed 64 | } 65 | return padString.slice(0, targetLength) + String(this); 66 | } 67 | }; 68 | } 69 | // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js 70 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd 71 | if (!String.prototype.padEnd) { 72 | String.prototype.padEnd = function padEnd(targetLength, padString) { 73 | targetLength = targetLength >> 0; //floor if number or convert non-number to 0; 74 | padString = String(padString || ' '); 75 | if (this.length > targetLength) { 76 | return String(this); 77 | } 78 | else { 79 | targetLength = targetLength - this.length; 80 | if (targetLength > padString.length) { 81 | padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed 82 | } 83 | return String(this) + padString.slice(0, targetLength); 84 | } 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/polyfills/string.ts: -------------------------------------------------------------------------------- 1 | console.log('= String includes, repeat, padStart, padEnd'); 2 | 3 | if (!String.prototype.includes) { 4 | (String.prototype as any).includes = function(search, start) { 5 | 'use strict'; 6 | if (typeof start !== 'number') { 7 | start = 0; 8 | } 9 | 10 | if (start + search.length > this.length) { 11 | return false; 12 | } else { 13 | return this.indexOf(search, start) !== -1; 14 | } 15 | }; 16 | } 17 | 18 | if (!String.prototype.repeat) { 19 | String.prototype.repeat = function(count) { 20 | 'use strict'; 21 | if (this == null) { 22 | throw new TypeError('can\'t convert ' + this + ' to object'); 23 | } 24 | var str = '' + this; 25 | count = +count; 26 | if (count != count) { 27 | count = 0; 28 | } 29 | if (count < 0) { 30 | throw new RangeError('repeat count must be non-negative'); 31 | } 32 | if (count == Infinity) { 33 | throw new RangeError('repeat count must be less than infinity'); 34 | } 35 | count = Math.floor(count); 36 | if (str.length == 0 || count == 0) { 37 | return ''; 38 | } 39 | // Ensuring count is a 31-bit integer allows us to heavily optimize the 40 | // main part. But anyway, most current (August 2014) browsers can't handle 41 | // strings 1 << 28 chars or longer, so: 42 | if (str.length * count >= 1 << 28) { 43 | throw new RangeError('repeat count must not overflow maximum string size'); 44 | } 45 | var rpt = ''; 46 | for (var i = 0; i < count; i++) { 47 | rpt += str; 48 | } 49 | return rpt; 50 | } 51 | } 52 | 53 | // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js 54 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart 55 | if (!(String.prototype as any).padStart) { 56 | (String.prototype as any).padStart = function padStart(targetLength,padString) { 57 | targetLength = targetLength>>0; //floor if number or convert non-number to 0; 58 | padString = String(padString || ' '); 59 | if (this.length > targetLength) { 60 | return String(this); 61 | } 62 | else { 63 | targetLength = targetLength-this.length; 64 | if (targetLength > padString.length) { 65 | padString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed 66 | } 67 | return padString.slice(0,targetLength) + String(this); 68 | } 69 | }; 70 | } 71 | 72 | // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js 73 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd 74 | if (!(String.prototype as any).padEnd) { 75 | (String.prototype as any).padEnd = function padEnd(targetLength,padString) { 76 | targetLength = targetLength>>0; //floor if number or convert non-number to 0; 77 | padString = String(padString || ' '); 78 | if (this.length > targetLength) { 79 | return String(this); 80 | } 81 | else { 82 | targetLength = targetLength-this.length; 83 | if (targetLength > padString.length) { 84 | padString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed 85 | } 86 | return String(this) + padString.slice(0,targetLength); 87 | } 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/require/patch-require.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | This file is modified MIT-licensed code from Scriptcraft 4 | See license-scriptcraft.txt 5 | */ 6 | Object.defineProperty(exports, "__esModule", { value: true }); 7 | var smaDirectory = '../scriptcraft-plugins'; // relative to scriptcraft dir 8 | var log = function (msg) { return console.log("[SMA] " + msg); }; 9 | function patch() { 10 | /* 11 | We're going to replace the global require function. This allows us to modify the search path for module resolution 12 | 13 | This file preps and loads it, replacing the existing global.require, and renaming 14 | it to __require. 15 | */ 16 | var path = 'scriptcraft/lib/scriptcraft.js'; 17 | var File = java.io.File; 18 | var FileReader = java.io.FileReader; 19 | var BufferedReader = java.io.BufferedReader; 20 | var canonize = function (file) { return '' + file.getCanonicalPath().replaceAll('\\\\', '/'); }; 21 | function _load(filename, warnOnFileNotFound) { 22 | var result = null; 23 | var file = filename; 24 | var r; 25 | var reader; 26 | var br; 27 | var code; 28 | var wrappedCode; 29 | if (!(filename instanceof File)) { 30 | file = new File(filename); 31 | } 32 | var canonizedFilename = canonize(file); 33 | if (file.exists()) { 34 | reader = new FileReader(file); 35 | br = new BufferedReader(reader); 36 | code = ''; 37 | try { 38 | r = br.readLine(); 39 | while (r !== null) { 40 | code += r + '\n'; 41 | r = br.readLine(); 42 | } 43 | wrappedCode = "(" + code + ")"; 44 | result = eval(wrappedCode); // tslint:disable-line 45 | // issue #103 avoid side-effects of || operator on Mac Rhino 46 | } 47 | catch (e) { 48 | log("Error evaluating " + canonizedFilename + ", " + e); 49 | } 50 | finally { 51 | try { 52 | reader.close(); 53 | } 54 | catch (re) { 55 | // fail silently on reader close error 56 | } 57 | } 58 | } 59 | else { 60 | if (warnOnFileNotFound) { 61 | log(canonizedFilename + ' not found'); 62 | } 63 | } 64 | return result; 65 | } // end _load() 66 | var jsPluginsRootDir = new File(path).parentFile.parentFile; 67 | var jsPluginsRootDirName = canonize(jsPluginsRootDir); 68 | var configRequire = _load(jsPluginsRootDirName + "/plugins/sma-bootstrap/require/require.js", true); 69 | /* 70 | setup paths to search for modules 71 | */ 72 | var modulePaths = [ 73 | jsPluginsRootDirName + "/modules/", 74 | jsPluginsRootDirName + "/lib/", 75 | jsPluginsRootDirName + "/" + smaDirectory + "/" 76 | ]; 77 | if (config.verbose) { 78 | log('Setting up CommonJS-style module system. Root Directory: ' + 79 | jsPluginsRootDirName); 80 | log('Module paths: ' + JSON.stringify(modulePaths)); 81 | } 82 | var requireHooks = { 83 | loaded: function (loadedpath) { 84 | if (config.verbose) { 85 | log("loaded " + loadedpath); 86 | } 87 | }, 88 | loading: function (loadingpath) { 89 | if (config.verbose) { 90 | log("loading " + loadingpath); 91 | } 92 | }, 93 | }; 94 | if (configRequire) { 95 | global.require = configRequire(jsPluginsRootDirName, modulePaths, requireHooks, function (code) { return eval(code); } // tslint:disable-line 96 | ); 97 | require = global.require; 98 | log('Patched global.require'); 99 | } 100 | else { 101 | log("There was a problem patching global.require!"); 102 | } 103 | return require; 104 | } 105 | exports.patch = patch; 106 | -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/require/patch-require.ts: -------------------------------------------------------------------------------- 1 | /* 2 | This file is modified MIT-licensed code from Scriptcraft 3 | See license-scriptcraft.txt 4 | */ 5 | 6 | const smaDirectory = '../scriptcraft-plugins'; // relative to scriptcraft dir 7 | 8 | const log = msg => console.log(`[SMA] ${msg}`); 9 | 10 | export function patch() { 11 | /* 12 | We're going to replace the global require function. This allows us to modify the search path for module resolution 13 | 14 | This file preps and loads it, replacing the existing global.require, and renaming 15 | it to __require. 16 | */ 17 | 18 | const path = 'scriptcraft/lib/scriptcraft.js' 19 | 20 | 21 | const File = java.io.File 22 | const FileReader = java.io.FileReader 23 | const BufferedReader = java.io.BufferedReader 24 | 25 | const canonize = (file) => '' + file.getCanonicalPath().replaceAll('\\\\', '/') 26 | 27 | function _load(filename, warnOnFileNotFound) { 28 | let result: any = null 29 | let file = filename 30 | let r 31 | let reader 32 | let br 33 | let code 34 | let wrappedCode 35 | 36 | if (!(filename instanceof File)) { 37 | file = new File(filename) 38 | } 39 | const canonizedFilename = canonize(file) 40 | 41 | if (file.exists()) { 42 | reader = new FileReader(file) 43 | br = new BufferedReader(reader) 44 | code = '' 45 | try { 46 | r = br.readLine() 47 | while (r !== null) { 48 | code += r + '\n' 49 | r = br.readLine() 50 | } 51 | wrappedCode = `(${code})` 52 | result = eval(wrappedCode) // tslint:disable-line 53 | // issue #103 avoid side-effects of || operator on Mac Rhino 54 | } catch (e) { 55 | log(`Error evaluating ${canonizedFilename}, ${e}`) 56 | } finally { 57 | try { 58 | reader.close() 59 | } catch (re) { 60 | // fail silently on reader close error 61 | } 62 | } 63 | } else { 64 | if (warnOnFileNotFound) { 65 | log(canonizedFilename + ' not found') 66 | } 67 | } 68 | return result 69 | } // end _load() 70 | 71 | const jsPluginsRootDir = new File(path).parentFile.parentFile 72 | const jsPluginsRootDirName = canonize(jsPluginsRootDir); 73 | const configRequire = _load( 74 | `${jsPluginsRootDirName}/plugins/sma-bootstrap/require/require.js`, 75 | true, 76 | ) 77 | 78 | /* 79 | setup paths to search for modules 80 | */ 81 | 82 | const modulePaths = [ 83 | `${jsPluginsRootDirName}/modules/`, 84 | `${jsPluginsRootDirName}/lib/`, 85 | `${jsPluginsRootDirName}/${smaDirectory}/` 86 | ] 87 | 88 | if (config.verbose) { 89 | log( 90 | 'Setting up CommonJS-style module system. Root Directory: ' + 91 | jsPluginsRootDirName, 92 | ) 93 | log('Module paths: ' + JSON.stringify(modulePaths)) 94 | } 95 | const requireHooks = { 96 | loaded: loadedpath => { 97 | if (config.verbose) { 98 | log(`loaded ${loadedpath}`) 99 | } 100 | }, 101 | loading: loadingpath => { 102 | if (config.verbose) { 103 | log(`loading ${loadingpath}`) 104 | } 105 | }, 106 | } 107 | 108 | if (configRequire) { 109 | global.require = configRequire( 110 | jsPluginsRootDirName, 111 | modulePaths, 112 | requireHooks, 113 | code => eval(code) // tslint:disable-line 114 | ); 115 | (require as any) = global.require; 116 | log('Patched global.require'); 117 | } else { 118 | log(`There was a problem patching global.require!`); 119 | } 120 | return require; 121 | } -------------------------------------------------------------------------------- /resources/js/sma-bootstrap/require/require.js: -------------------------------------------------------------------------------- 1 | /* 2 | This file is modified MIT-licensed code from Scriptcraft 3 | See license-scriptcraft.txt 4 | */ 5 | 6 | // DO NOT CONVERT TO TYPESCRIPT 7 | 8 | // THIS FILE MUST BE JAVASCRIPT 9 | 10 | (function (rootDir, modulePaths, hooks, evaluate) { 11 | 12 | var debug = function(message) { 13 | if (global.__requireDebug) { 14 | console.log(message) 15 | } 16 | } 17 | 18 | // make the old require available as __require 19 | global.__require = require; 20 | 21 | var File = java.io.File, 22 | FileReader = java.io.FileReader, 23 | BufferedReader = java.io.BufferedReader; 24 | 25 | function fileExists(file) { 26 | if (file.isDirectory()) { 27 | debug('File is directory: ' + file) // @DEBUG 28 | return readModuleFromDirectory(file); 29 | } else { 30 | debug('File is NOT directory: ' + file) // @DEBUG 31 | return file; 32 | } 33 | } 34 | 35 | function _canonize(file) { 36 | return '' + file.canonicalPath.replaceAll('\\\\', '/'); 37 | } 38 | 39 | function readModuleFromDirectory(dir) { 40 | 41 | debug('Searching directory ' + dir) // @DEBUG 42 | // look for a package.json file 43 | var pkgJsonFile = new File(dir, './package.json'); 44 | if (pkgJsonFile.exists()) { 45 | debug('Found package.json') // @DEBUG 46 | 47 | var pkg = scload(pkgJsonFile); 48 | var mainFile; 49 | if (pkg.main) { 50 | mainFile = new File(dir, pkg.main); 51 | } else { 52 | mainFile = new File(dir, './index.js'); 53 | } 54 | debug('package.json specifies '+ mainFile) // @DEBUG 55 | 56 | if (mainFile.exists()) { 57 | debug('Found ' + mainFile) // @DEBUG 58 | 59 | return mainFile; 60 | } else { 61 | debug('NOT found ' + mainFile) // @DEBUG 62 | debug('Found ' + dir + '/package.json, but no entry point was specified or found for the module.') 63 | return null; 64 | } 65 | } else { 66 | // look for an index.js file 67 | var indexJsFile = new File(dir, './index.js'); 68 | if (indexJsFile.exists()) { 69 | return indexJsFile; 70 | } else { 71 | debug(dir + './index.js does not exist') // @DEBUG 72 | return null; 73 | } 74 | } 75 | } 76 | 77 | 78 | /********************************************************************** 79 | ### module name resolution 80 | 81 | When resolving module names to file paths, ScriptCraft uses the following rules... 82 | 83 | 1. if the module does not begin with './' or '/' then ... 84 | 85 | 1.1 Look in the 'scriptcraft/lib' directory. If it's not there then... 86 | 1.2 Look in the 'scriptcraft/modules' directory. If it's not there then 87 | Throw an Error. 88 | 89 | 2. If the module begins with './' or '/' then ... 90 | 91 | 2.1 if the module begins with './' then it's treated as a file path. File paths are 92 | always relative to the module from which the require() call is being made. 93 | 94 | 2.2 If the module begins with '/' then it's treated as an absolute path. 95 | 96 | If the module does not have a '.js' suffix, and a file with the same name and a .js sufix exists, 97 | then the file will be loaded. 98 | 99 | 3. If the module name resolves to a directory then... 100 | 101 | 3.1 look for a package.json file in the directory and load the `main` property e.g. 102 | 103 | // package.json located in './some-library/' 104 | { 105 | "main": './some-lib.js', 106 | "name": 'some-library' 107 | } 108 | 109 | 3.2 if no package.json file exists then look for an index.js file in the directory 110 | 111 | ***/ 112 | 113 | function resolveModuleToFile(moduleName, parentDir) { 114 | debug('Resolving ' + moduleName) // @DEBUG 115 | var file = new File(moduleName), 116 | i = 0, 117 | resolvedFile; 118 | 119 | if (moduleName.indexOf('.') === 0) { 120 | // This is a relative path - we will make it absolute 121 | // This resolves paths like `../${dirname} 122 | // Without it, Scriptcraft can only do `../${dirname}/index 123 | // Will cause requiring hidden files to fail 124 | file = new File(parentDir, moduleName) 125 | } 126 | if (file.exists()) { 127 | return fileExists(file); 128 | } 129 | if (moduleName.indexOf('/') === 0) { 130 | // it's an absolute file path. We use this to include commando 131 | debug('Searching for absolute path') 132 | resolvedFile = new File(moduleName) 133 | if (resolvedFile.exists()) { 134 | debug('Resolved file: ' + resolvedFile) // @DEBUG 135 | return fileExists(resolvedFile) 136 | } 137 | resolvedFile = new File(moduleName + '.js') 138 | if (resolvedFile.exists()) { 139 | debug('Resolved file: ' + resolvedFile) // @DEBUG 140 | return fileExists(resolvedFile) 141 | } 142 | resolvedFile = new File(moduleName + '/index.js') 143 | if (resolvedFile.exists()) { 144 | debug('Resolved file: ' + resolvedFile) // @DEBUG 145 | return fileExists(resolvedFile) 146 | } 147 | return null; 148 | } 149 | if (moduleName.match(/^[^\.\/]/)) { 150 | // it's a module named like so ... 'events' , 'net/http' 151 | debug('Searching for absolute module') // @DEBUG 152 | for (; i < modulePaths.length; i++) { 153 | resolvedFile = new File( 154 | modulePaths[i] + moduleName 155 | ) 156 | 157 | if (resolvedFile.exists()) { 158 | debug('Resolved file: ' + resolvedFile) // @DEBUG 159 | 160 | return fileExists(resolvedFile) 161 | } else { 162 | // try appending a .js to the end 163 | resolvedFile = new File( 164 | modulePaths[i] + moduleName + '.js' 165 | ) 166 | if (resolvedFile.exists()) { 167 | return resolvedFile 168 | } 169 | // try appending a .js to the end 170 | resolvedFile = new File( 171 | modulePaths[i] + moduleName + '/index.js' 172 | ) 173 | debug('Resolved file: ' + resolvedFile) // @DEBUG 174 | 175 | if (resolvedFile.exists()) { 176 | return resolvedFile 177 | } 178 | } 179 | } 180 | 181 | // Now search node_modules resolution paths 182 | var nodeModulePaths = [ 183 | '/node_modules/', 184 | '/../node_modules/', 185 | '/../../node_modules/', 186 | '/../../../node_modules/' 187 | ] 188 | debug('Searching node_module paths') 189 | for (i=0; i < nodeModulePaths.length; i++) { 190 | debug('Using path ' + nodeModulePaths[i]); 191 | resolvedFile = new File(parentDir + nodeModulePaths[i] + moduleName); 192 | debug('Searching ' + resolvedFile); 193 | if (resolvedFile.exists()) { 194 | debug('Resolved:' + resolvedFile) // @DEBUG 195 | return fileExists(resolvedFile); 196 | } 197 | } 198 | } else { 199 | debug('Searching for relative module ' + moduleName + ' - looking in: ' + parentDir) // @DEBUG 200 | debug(parentDir + moduleName + ' exists: ' + (new File(parentDir, moduleName)).exists()) 201 | if ((file = new File(parentDir, moduleName)).exists()) { 202 | return fileExists(file); 203 | } else if ((file = new File(parentDir, moduleName + '.js')).exists()) { // try .js extension 204 | return file; 205 | } else if ((file = new File(parentDir, moduleName + '.json')).exists()) { // try .json extension 206 | return file; 207 | } else if ((file = new File(parentDir, moduleName + '/index.js')).exists()) { // try index.js 208 | return file; 209 | } 210 | } 211 | return null; 212 | } 213 | 214 | function _require(parentFile, path, options) { 215 | var file, 216 | canonizedFilename, 217 | moduleInfo, 218 | buffered, 219 | head = '(function(exports,module,require,__filename,__dirname){ ', 220 | code = '', 221 | line = null; 222 | 223 | if (typeof options == 'undefined') { 224 | options = { cache: true }; 225 | } else { 226 | if (typeof options.cache == 'undefined') { 227 | options.cache = true; 228 | } 229 | } 230 | debug('Requiring: parentFile: ' + parentFile) // @DEBUG 231 | debug('Requiring: path: ' + path) // @DEBUG 232 | file = resolveModuleToFile(path, parentFile); 233 | debug('Resolved file: ' + file) // @DEBUG 234 | if (!file) { 235 | 236 | var errMsg = '' + _format('require() failed to find matching file for module \'%s\'' + 237 | 'in any of the following locations \n%s <-- ## working dir ##\n', [path, parentFile.canonicalPath]); 238 | /** 239 | * This find search is helpful, but very slow with node_modules 240 | */ 241 | // if (!(('' + path).match(/^\./))) { 242 | // errMsg = errMsg + modulePaths.join('\n'); 243 | // } 244 | // var find = _require(parentFile, 'find').exports; 245 | // var allJS = []; 246 | // for (var i = 0; i < modulePaths.length; i++) { 247 | // var js = find(modulePaths[i]); 248 | // for (var j = 0; j < js.length; j++) { 249 | // if (js[j].match(/\.js$/)) { 250 | // allJS.push(js[j].replace(modulePaths[i], '')); 251 | // } 252 | // } 253 | // } 254 | // var pathL = path.toLowerCase(); 255 | // var candidates = []; 256 | // for (i = 0; i < allJS.length; i++) { 257 | // var filenameparts = allJS[i]; 258 | // var candidate = filenameparts.replace(/\.js/, ''); 259 | // var lastpart = candidate.toLowerCase(); 260 | // if (pathL.indexOf(lastpart) > -1 || lastpart.indexOf(pathL) > -1) { 261 | // candidates.push(candidate); 262 | // } 263 | // } 264 | // if (candidates.length > 0) { 265 | // errMsg += '\nBut found module/s named: ' + candidates.join(',') + ' - is this what you meant?'; 266 | // } 267 | throw new Error(errMsg); 268 | } 269 | canonizedFilename = _canonize(file); 270 | 271 | moduleInfo = _loadedModules[canonizedFilename]; 272 | if (moduleInfo) { 273 | if (options.cache) { 274 | return moduleInfo; 275 | } 276 | } 277 | if (hooks) { 278 | hooks.loading(canonizedFilename); 279 | } 280 | buffered = new BufferedReader(new FileReader(file)); 281 | while ((line = buffered.readLine()) !== null) { 282 | code += line + '\n'; 283 | } 284 | buffered.close(); // close the stream so there's no file locks 285 | 286 | if (canonizedFilename.toLowerCase().substring(canonizedFilename.length - 5) === '.json') // patch code when it is json 287 | code = 'module.exports = (' + code + ');'; 288 | 289 | moduleInfo = { 290 | loaded: false, 291 | id: canonizedFilename, 292 | exports: {}, 293 | require: _requireClosure(file.parentFile) 294 | }; 295 | var tail = '})'; 296 | code = head + code + tail; 297 | 298 | if (options.cache) { 299 | _loadedModules[canonizedFilename] = moduleInfo; 300 | } 301 | var compiledWrapper = null; 302 | try { 303 | compiledWrapper = evaluate(code); 304 | } catch (e) { 305 | /* 306 | wph 20140313 JRE8 (nashorn) gives misleading linenumber of evaluating code not evaluated code. 307 | This can be fixed by instead using __engine.eval 308 | */ 309 | throw new Error('Error evaluating module ' + path 310 | + ' line #' + e.lineNumber 311 | + ' : ' + e.message, canonizedFilename, e.lineNumber); 312 | } 313 | var __dirname = '' + file.parentFile.canonicalPath; 314 | var parameters = [ 315 | moduleInfo.exports, /* exports */ 316 | moduleInfo, /* module */ 317 | moduleInfo.require, /* require */ 318 | canonizedFilename, /* __filename */ 319 | __dirname /* __dirname */ 320 | ]; 321 | try { 322 | if (compiledWrapper) 323 | compiledWrapper 324 | .apply(moduleInfo.exports, /* this */ 325 | parameters); 326 | } catch (e) { 327 | var snippet = ''; 328 | if (('' + e.lineNumber).match(/[0-9]/)) { 329 | var lines = code.split(/\n/); 330 | if (e.lineNumber > 1) { 331 | snippet = ' ' + lines[e.lineNumber - 2] + '\n'; 332 | } 333 | snippet += '> ' + lines[e.lineNumber - 1] + '\n'; 334 | if (e.lineNumber < lines.length) { 335 | snippet += ' ' + lines[e.lineNumber] + '\n'; 336 | } 337 | } 338 | throw new Error('Error executing module ' + path 339 | + ' line #' + e.lineNumber 340 | + ' : ' + e.message + (snippet ? ('\n' + snippet) : ''), canonizedFilename, e.lineNumber); 341 | } 342 | if (hooks) { 343 | hooks.loaded(canonizedFilename); 344 | } 345 | moduleInfo.loaded = true; 346 | return moduleInfo; 347 | } 348 | 349 | function _requireClosure(parentFile) { 350 | var _boundRequire = function requireBoundToParentSMA(path, options) { 351 | var module = _require(parentFile, path, options); 352 | return module.exports; 353 | }; 354 | 355 | _boundRequire.resolve = function resolveBoundToParent(path) { 356 | return resolveModuleToFile(path, parentFile); 357 | }; 358 | _boundRequire.cache = _loadedModules; 359 | 360 | return _boundRequire; 361 | } 362 | var _loadedModules = {}; 363 | var _format = java.lang.String.format; 364 | return _requireClosure(new java.io.File(rootDir)); 365 | // last line deliberately has no semicolon! 366 | /* eslint semi: off*/ 367 | }) 368 | -------------------------------------------------------------------------------- /resources/js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "lib": [ 6 | "es2015" 7 | ], 8 | "strict": true, 9 | "noImplicitAny": false, 10 | "noImplicitThis": false, 11 | "esModuleInterop": true 12 | } 13 | } -------------------------------------------------------------------------------- /resources/paperclip.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/paperclip.jar -------------------------------------------------------------------------------- /resources/plugins/BossBarAPI_v2.4.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/BossBarAPI_v2.4.2.jar -------------------------------------------------------------------------------- /resources/plugins/CamundaPlugin-1.0.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/CamundaPlugin-1.0.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /resources/plugins/DurableMap-1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/DurableMap-1.0.jar -------------------------------------------------------------------------------- /resources/plugins/Essentials-2.x-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/Essentials-2.x-SNAPSHOT.jar -------------------------------------------------------------------------------- /resources/plugins/HolographicDisplays-2.4.2-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/HolographicDisplays-2.4.2-SNAPSHOT.jar -------------------------------------------------------------------------------- /resources/plugins/MinecraftRestConsole-1.8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/MinecraftRestConsole-1.8.jar -------------------------------------------------------------------------------- /resources/plugins/MotdManager-Reloaded.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/MotdManager-Reloaded.jar -------------------------------------------------------------------------------- /resources/plugins/MotdManager-Reloaded/config.yml: -------------------------------------------------------------------------------- 1 | #==================# 2 | # Basic Config # 3 | #==================# 4 | # sending MOTD list 5 | MotdList: 6 | - '§!§2Magikcraft.io §r§e[%ver] §r§O§7Code | Play' 7 | 8 | # if use show fake max players count feature, change this to numeric 9 | FakeMaxPlayer: disable 10 | 11 | #==================# 12 | # Debug Config # 13 | #==================# 14 | Debug: false 15 | 16 | #==================# 17 | # DO NOT TOUCH # 18 | #==================# 19 | # Do not touch this option! It is a check if you are running the recent configuration version 20 | ConfigVersion: 1 -------------------------------------------------------------------------------- /resources/plugins/Multiverse-Core-4.1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/Multiverse-Core-4.1.0.jar -------------------------------------------------------------------------------- /resources/plugins/ProtocolLib-4.5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/ProtocolLib-4.5.0.jar -------------------------------------------------------------------------------- /resources/plugins/Scriptcraft-ME-3.2.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/Scriptcraft-ME-3.2.0.jar -------------------------------------------------------------------------------- /resources/plugins/worldedit-bukkit-7.1.0-rc-1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/plugins/worldedit-bukkit-7.1.0-rc-1.jar -------------------------------------------------------------------------------- /resources/s: -------------------------------------------------------------------------------- 1 | const xml = `SequenceFlow_0krhw54SequenceFlow_0tmt5j8someFunctionSequenceFlow_0tmt5j8SequenceFlow_0krhw54` 2 | 3 | const c = server.getPluginManager().getPlugin("CamundaPlugin") 4 | 5 | c.registerHandler("someFunction", "function(execution) { var process = execution.getProcessInstanceId(); console.log('Yay!!! The job handler was called from process instance ' + process )}") 6 | 7 | c.deployBpmn("model.bpmn", xml); 8 | 9 | c.runtimeService.createProcessInstanceByKey("my-project-process").execute() 10 | -------------------------------------------------------------------------------- /resources/scriptcraft.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/resources/scriptcraft.jar -------------------------------------------------------------------------------- /resources/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # shellcheck shell=dash 3 | 4 | ROOT=/_server_ 5 | 6 | cd $ROOT || exit 1 7 | 8 | if [ "x${SERVERMEM}" = "x" ]; then 9 | SERVERMEM=2048 10 | fi 11 | 12 | if [ "x${MINECRAFT_EULA_ACCEPTED}" = "x" ]; then 13 | echo "Must accept the Minecraft EULA to proceed." 14 | exit 0 15 | fi 16 | 17 | echo "Minecraft EULA accepted." 18 | echo "Starting with ${SERVERMEM} MB of RAM" 19 | 20 | java -Xmx${SERVERMEM}m -Xms${SERVERMEM}m -cp paperclip.jar:h2.jar io.papermc.paperclip.Paperclip 21 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | MINECRAFT_TAG=1.15.2 3 | docker run -it -p 25665:25565 \ 4 | --mount source=scriptcraft-worlds,target=/_server_/worlds \ 5 | --mount source=scriptcraft-cache,target=/_server_/cache \ 6 | --mount type=bind,src=$(pwd)/resources/js/sma-bootstrap,dst=/_server_/scriptcraft/plugins/sma-bootstrap \ 7 | --mount type=bind,src=$(pwd)/test/test-plugin,dst=/_server_/scriptcraft-plugins/test \ 8 | --mount type=bind,src=$(pwd)/test/test-plugin-2,dst=/_server_/scriptcraft-plugins/test-plugin-2 \ 9 | magikcraft/scriptcraft:$MINECRAFT_TAG 10 | 11 | # The following mount demonstrates how to mount an SMA plugin in the image 12 | # --mount type=bind,src=$(pwd)/test-plugin,dst=/_server_/scriptcraft-plugins/test \ 13 | # The folllowing mount allows you to test changes to sma-bootstrap without rebuilding the image - for sma-bootstrap dev only 14 | # --mount type=bind,src=$(pwd)/resources/js/sma-bootstrap,dst=/_server_/scriptcraft/plugins/sma-bootstrap \ 15 | -------------------------------------------------------------------------------- /test/HolographicDisplays.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Magikcraft/scriptcraft-modular-arch/5d6e3da39e7cad19f984eba2142424d908eede3a/test/HolographicDisplays.jar -------------------------------------------------------------------------------- /test/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker run -it -p 25665:25565 \ 3 | --mount source=scriptcraft-worlds,target=/_server_/worlds \ 4 | --mount source=scriptcraft-cache,target=/_server_/cache \ 5 | --mount type=bind,src=$(pwd)/test-plugin,dst=/_server_/scriptcraft-plugins/test \ 6 | --mount type=bind,src=$(pwd)/test-plugin-2,dst=/_server_/scriptcraft-plugins/test-plugin-2 \ 7 | magikcraft/scriptcraft 8 | -------------------------------------------------------------------------------- /test/test-plugin-2/dst/autoload/_1.js: -------------------------------------------------------------------------------- 1 | console.log('Autoloaded from package.json: test-plugin-2/dst/autoload/_1.js'); -------------------------------------------------------------------------------- /test/test-plugin-2/dst/autoload/_2.js: -------------------------------------------------------------------------------- 1 | console.log('Autoloaded from package.json: test-plugin-2/dst/autoload/_2.js'); -------------------------------------------------------------------------------- /test/test-plugin-2/fs.js: -------------------------------------------------------------------------------- 1 | // Transitively required by `test-plugin`, a peer-dependency 2 | console.log('test-plugin-2/fs required from test-plugin'); 3 | module.exports = { 4 | read: function (filename) { 5 | return '[test-plugin-2 function] File contents of ' + filename + ' here....' 6 | } 7 | } -------------------------------------------------------------------------------- /test/test-plugin-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-plugin-2", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "fs.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "scriptcraft_load_dir": "dst/autoload" 12 | } -------------------------------------------------------------------------------- /test/test-plugin/plugins/index.js: -------------------------------------------------------------------------------- 1 | // Automatically loaded at start-up, because it is in the `plugins` sub-directory 2 | console.log("Hello! Test plugin autoloaded! About to require something from a peer plugin..."); 3 | 4 | // Plugins can require other plugins as peer-dependencies. 5 | var fs = require('test-plugin-2/fs'); 6 | console.log(fs.read('test.txt')); --------------------------------------------------------------------------------