Compare commits
40 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c92a88f03f | |||
| 97f6fc5844 | |||
| a3baa53bdd | |||
| f65bc37dd3 | |||
| 9830c10b6f | |||
| 1f9aee329e | |||
| 235f8aef39 | |||
| 3819db1ce4 | |||
| 9f6c117c84 | |||
| 357af820bf | |||
| 116eb216d0 | |||
| deedda7648 | |||
| fe7fb028bd | |||
| c9d8a81153 | |||
| 0f627fee53 | |||
| bab175eb24 | |||
| 0a35000118 | |||
| 47c6bba8cb | |||
| 1ae598f06f | |||
| bc5e21680e | |||
| 6bff0bd5ac | |||
| 2adce05703 | |||
| 26432693e8 | |||
| 241a97eb78 | |||
| c61d42f23e | |||
| 4c2e0e4175 | |||
| f1834f83dc | |||
| 2bbc7cdc42 | |||
| 6a3b81ec0d | |||
| 738d579a81 | |||
| 1aaf148ce4 | |||
| 5c3240ed8d | |||
| 4681e908f7 | |||
| 6373d92fea | |||
| 401edf05c0 | |||
| f0cf155ae8 | |||
| 1b26cacc4d | |||
| e26baae865 | |||
| 3b2d886f58 | |||
| 23fe6d10f5 |
31 changed files with 279 additions and 2413 deletions
|
|
@ -1,2 +1,5 @@
|
|||
# The absolute path to the Foundry installation to create symlinks to
|
||||
FOUNDRY_ROOT=""
|
||||
|
||||
# The manifest file for the module/system
|
||||
MANIFEST="./system.json"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
on: [ workflow_dispatch ]
|
||||
env:
|
||||
MANIFEST: "system.json"
|
||||
jobs:
|
||||
create-artifacts:
|
||||
name: "Create artifacts"
|
||||
create-draft-release:
|
||||
name: "Create Draft Release"
|
||||
runs-on: act
|
||||
outputs:
|
||||
version: ${{steps.version.outputs.version}}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm clean-install
|
||||
|
|
@ -14,7 +20,7 @@ jobs:
|
|||
run: cat system.json | echo version=`jq -r ".version"` >> "$FORGEJO_OUTPUT"
|
||||
|
||||
- name: Assert that the tag doesn't exist
|
||||
run: node scripts/tagExists.mjs
|
||||
run: node scripts/src/tagExists.mjs
|
||||
env:
|
||||
TAG_NAME: "v${{steps.version.outputs.version}}"
|
||||
|
||||
|
|
@ -24,73 +30,53 @@ jobs:
|
|||
- name: Remove compendia source
|
||||
run: "rm -rf packs/**/_source"
|
||||
|
||||
- name: Compress files
|
||||
run: zip -r release.zip langs module styles templates README.md assets LICENSE
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: https://data.forgejo.org/forgejo/upload-artifact@v4
|
||||
with:
|
||||
path: |
|
||||
system.json
|
||||
release.zip
|
||||
scripts/*.mjs
|
||||
package-lock.json
|
||||
package.json
|
||||
retention-days: 7
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
forgejo-release:
|
||||
name: "Create Forgejo release"
|
||||
runs-on: act
|
||||
needs:
|
||||
- create-artifacts
|
||||
if: vars.RELEASE_TO_FORGEJO == 'yes'
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: https://data.forgejo.org/forgejo/download-artifact@v4
|
||||
with:
|
||||
merge-multiple: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm i
|
||||
|
||||
- id: version
|
||||
run: cat system.json | echo version=`jq -r ".version"` >> "$FORGEJO_OUTPUT"
|
||||
|
||||
- name: Update manifest
|
||||
run: node scripts/prepareManifest.mjs
|
||||
run: node scripts/src/prepareManifest.mjs
|
||||
env:
|
||||
DOWNLOAD_URL: "${{forgejo.server_url}}/${{forgejo.repository}}/releases/download/v${{steps.version.outputs.version}}/release.zip"
|
||||
LATEST_URL: "${{forgejo.server_url}}/${{forgejo.repository}}/releases/download/latest/system.json"
|
||||
|
||||
- name: Add manifest into release archive
|
||||
run: zip release.zip --update system.json
|
||||
- name: Compress files
|
||||
run: zip -r release.zip langs module styles templates README.md assets LICENSE ${{env.MANIFEST}}
|
||||
|
||||
- name: Upload archive to s3
|
||||
run: node scripts/uploadToS3.mjs
|
||||
env:
|
||||
TAG: "v${{steps.version.outputs.version}}"
|
||||
FILE: "release.zip"
|
||||
S3_BUCKET: "${{vars.S3_BUCKET}}"
|
||||
S3_REGION: "${{vars.S3_REGION}}"
|
||||
S3_KEY: "${{secrets.S3_KEY}}"
|
||||
S3_SECRET: "${{secrets.S3_SECRET}}"
|
||||
S3_ENDPOINT: "${{vars.S3_ENDPOINT}}"
|
||||
|
||||
- name: Upload manifest to s3
|
||||
run: node scripts/uploadToS3.mjs
|
||||
env:
|
||||
TAG: "v${{steps.version.outputs.version}}"
|
||||
FILE: "system.json"
|
||||
S3_BUCKET: "${{vars.S3_BUCKET}}"
|
||||
S3_REGION: "${{vars.S3_REGION}}"
|
||||
S3_KEY: "${{secrets.S3_KEY}}"
|
||||
S3_SECRET: "${{secrets.S3_SECRET}}"
|
||||
S3_ENDPOINT: "${{vars.S3_ENDPOINT}}"
|
||||
|
||||
- name: Create draft release
|
||||
run: node scripts/createForgejoRelease.mjs
|
||||
- name: Create forgejo release
|
||||
run: node scripts/src/createForgejoRelease.mjs
|
||||
env:
|
||||
TAG: "v${{steps.version.outputs.version}}"
|
||||
CDN_URL: "${{vars.CDN_URL}}"
|
||||
|
||||
wiki-release-artifact:
|
||||
name: "Add Wiki to Release"
|
||||
runs-on: act
|
||||
needs:
|
||||
- create-draft-release
|
||||
steps:
|
||||
- name: Checkout main code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: "Clone wiki repo"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: "${{forgejo.repository}}.wiki"
|
||||
ref: "main"
|
||||
path: "wiki"
|
||||
token: ${{forgejo.token}}
|
||||
|
||||
- name: "Install dependencies"
|
||||
run: "pwd; npm i"
|
||||
|
||||
- name: "Remove development folders"
|
||||
run: "rm -rf .git .vscode"
|
||||
working-directory: "wiki"
|
||||
|
||||
- name: "Compress wiki folder"
|
||||
run: "zip -r wiki.zip ."
|
||||
working-directory: "wiki"
|
||||
|
||||
- name: "Upload wiki archive"
|
||||
run: "node scripts/src/uploadReleaseAsset.mjs"
|
||||
env:
|
||||
ASSET: "wiki/wiki.zip"
|
||||
TAG: "v${{needs.create-draft-release.outputs.version}}"
|
||||
|
|
|
|||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "scripts"]
|
||||
path = scripts
|
||||
url = https://git.varify.ca/Foundry/scripts.git
|
||||
|
|
@ -10,6 +10,10 @@
|
|||
"name": "Players Can Manage Attributes",
|
||||
"hint": "This allows players who have edit access to a document to be able to edit what attributes those characters have via the attribute editor"
|
||||
},
|
||||
"initiativeFormula": {
|
||||
"name": "Initiative Formula",
|
||||
"hint": "The dice formula used for initiative, this can reference attributes on the actor. If the actor doesn't have the attribute it will be interpreted as 0."
|
||||
},
|
||||
"sheetDefaultHeight": {
|
||||
"name": "Default Actor Sheet Height",
|
||||
"hint": "The height that all actor sheets will open at unless overwridden for that sheet specifically. This setting will not affect already opened sheets."
|
||||
|
|
@ -36,9 +40,31 @@
|
|||
"Key": "Key",
|
||||
"Value": "Value",
|
||||
"no-data-submitted": "No data submitted",
|
||||
"data-query-notif-header": "Data Query Notification"
|
||||
"data-query-notif-header": "Data Query Notification",
|
||||
"cancel": "Cancel",
|
||||
"confirm-and-close": "Confirm and Close",
|
||||
"save-and-close": "Save and Close",
|
||||
"delete": "Delete",
|
||||
"resizable": "Resizable",
|
||||
"not-resizable": "Not Resizable"
|
||||
},
|
||||
"Apps": {
|
||||
"Ask": {
|
||||
"title": "Questions",
|
||||
"invalid-input-type": "Invalid input type provided: {type}"
|
||||
},
|
||||
"AttributeManager": {
|
||||
"title": "Attributes: {name}",
|
||||
"has-max": "Has Maximum?",
|
||||
"name-placeholder": "Attribute Name...",
|
||||
"no-attributes": "No attributes yet",
|
||||
"add-new-attribute": "Add New Attribute"
|
||||
},
|
||||
"PlayerSheet": {
|
||||
"manage-attributes": "Manage Attributes",
|
||||
"current-value": "Current value",
|
||||
"max-value": "Maximum value"
|
||||
},
|
||||
"QueryStatus": {
|
||||
"title": "Information Request Status",
|
||||
"user-disconnected-tooltip": "This user is not logged in to Foundry",
|
||||
|
|
@ -55,7 +81,8 @@
|
|||
"label": "Height"
|
||||
},
|
||||
"Resizable": {
|
||||
"label": "Resizable"
|
||||
"label": "Resizable",
|
||||
"placeholder": "Default ({placeholder})"
|
||||
},
|
||||
"tabs": {
|
||||
"foundry": "Foundry",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { __ID__, filePath } from "../consts.mjs";
|
||||
import { localizer } from "../utils/localizer.mjs";
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ export class Ask extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
width: 330,
|
||||
},
|
||||
window: {
|
||||
title: `Questions`,
|
||||
title: `taf.Apps.Ask.title`,
|
||||
resizable: true,
|
||||
minimizable: true,
|
||||
contentTag: `form`,
|
||||
|
|
@ -80,7 +81,10 @@ export class Ask extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
|
||||
for (const input of inputs) {
|
||||
if (!validInputTypes.includes(input.type)) {
|
||||
input.details = `Invalid input type provided: ${input.type}`;
|
||||
input.details = localizer(
|
||||
`taf.Apps.Ask.invalid-input-type`,
|
||||
{ type: input.type },
|
||||
);
|
||||
input.type = `error`;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { __ID__, filePath } from "../consts.mjs";
|
||||
import { attributeSorter } from "../utils/attributeSort.mjs";
|
||||
import { localizer } from "../utils/localizer.mjs";
|
||||
import { toID } from "../utils/toID.mjs";
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
|
@ -52,7 +53,10 @@ export class AttributeManager extends HandlebarsApplicationMixin(ApplicationV2)
|
|||
};
|
||||
|
||||
get title() {
|
||||
return `Attributes: ${this.#doc.name}`;
|
||||
return localizer(
|
||||
`taf.Apps.AttributeManager.title`,
|
||||
this.#doc,
|
||||
);
|
||||
};
|
||||
// #endregion Instance Data
|
||||
|
||||
|
|
@ -102,7 +106,6 @@ export class AttributeManager extends HandlebarsApplicationMixin(ApplicationV2)
|
|||
attrs.push({
|
||||
id,
|
||||
name: data.name,
|
||||
displayName: data.isNew ? `New Attribute` : data.name,
|
||||
sort: data.sort,
|
||||
isRange: data.isRange,
|
||||
isNew: data.isNew ?? false,
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
|
|||
|
||||
controls.push({
|
||||
icon: `fa-solid fa-at`,
|
||||
label: `Manage Attributes`,
|
||||
label: `taf.Apps.PlayerSheet.manage-attributes`,
|
||||
action: `manageAttributes`,
|
||||
visible: () => {
|
||||
const isGM = game.user.isGM;
|
||||
|
|
@ -167,7 +167,6 @@ export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
|
|||
event.stopPropagation();
|
||||
if ( event.detail > 1 ) { return }
|
||||
|
||||
// const docSheetConfigWidth = TAFDocumentSheetConfig.DEFAULT_OPTIONS.position.width;
|
||||
new TAFDocumentSheetConfig({
|
||||
document: this.document,
|
||||
position: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { __ID__, filePath } from "../consts.mjs";
|
||||
import { getDefaultSizing } from "../utils/getSizing.mjs";
|
||||
import { localizer } from "../utils/localizer.mjs";
|
||||
|
||||
const { diffObject, expandObject, flattenObject } = foundry.utils;
|
||||
const { DocumentSheetConfig } = foundry.applications.apps;
|
||||
|
|
@ -74,7 +75,9 @@ export class TAFDocumentSheetConfig extends DocumentSheetConfig {
|
|||
const defaults = getDefaultSizing();
|
||||
context.placeholders = {
|
||||
...defaults,
|
||||
resizable: defaults.resizable ? `Resizable` : `Not Resizable`,
|
||||
resizable: defaults.resizable
|
||||
? localizer(`taf.misc.resizable`)
|
||||
: localizer(`taf.misc.not-resizable`),
|
||||
};
|
||||
|
||||
// Custom values from document itself
|
||||
|
|
@ -88,9 +91,15 @@ export class TAFDocumentSheetConfig extends DocumentSheetConfig {
|
|||
|
||||
// Static prep
|
||||
context.resizeOptions = [
|
||||
{ label: `Default (${context.placeholders.resizable})`, value: `` },
|
||||
{ label: `Resizable`, value: `true` },
|
||||
{ label: `No Resizing`, value: `false` },
|
||||
{
|
||||
label: localizer(
|
||||
`taf.Apps.TAFDocumentSheetConfig.Resizable.placeholder`,
|
||||
{ placeholder: context.placeholders.resizable },
|
||||
),
|
||||
value: ``,
|
||||
},
|
||||
{ label: localizer(`taf.misc.resizable`), value: `true` },
|
||||
{ label: localizer(`taf.misc.not-resizable`), value: `false` },
|
||||
];
|
||||
};
|
||||
// #endregion Data Prep
|
||||
|
|
|
|||
9
module/documents/Combatant.mjs
Normal file
9
module/documents/Combatant.mjs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { __ID__ } from "../consts.mjs";
|
||||
|
||||
const { Combatant } = foundry.documents;
|
||||
|
||||
export class TAFCombatant extends Combatant {
|
||||
_getInitiativeFormula() {
|
||||
return game.settings.get(__ID__, `initiativeFormula`);
|
||||
};
|
||||
};
|
||||
|
|
@ -7,6 +7,7 @@ import { PlayerData } from "../data/Player.mjs";
|
|||
|
||||
// Documents
|
||||
import { TAFActor } from "../documents/Actor.mjs";
|
||||
import { TAFCombatant } from "../documents/Combatant.mjs";
|
||||
import { TAFItem } from "../documents/Item.mjs";
|
||||
import { TAFTokenDocument } from "../documents/Token.mjs";
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ Hooks.on(`init`, () => {
|
|||
|
||||
CONFIG.Token.documentClass = TAFTokenDocument;
|
||||
CONFIG.Actor.documentClass = TAFActor;
|
||||
CONFIG.Combatant.documentClass = TAFCombatant;
|
||||
|
||||
CONFIG.Actor.dataModels.player = PlayerData;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,16 @@ import { __ID__ } from "../consts.mjs";
|
|||
const { NumberField, StringField } = foundry.data.fields;
|
||||
|
||||
export function registerWorldSettings() {
|
||||
|
||||
game.settings.register(__ID__, `initiativeFormula`, {
|
||||
name: `taf.settings.initiativeFormula.name`,
|
||||
hint: `taf.settings.initiativeFormula.hint`,
|
||||
config: true,
|
||||
type: String,
|
||||
default: `1d20`,
|
||||
scope: `world`,
|
||||
});
|
||||
|
||||
game.settings.register(__ID__, `canPlayersManageAttributes`, {
|
||||
name: `taf.settings.canPlayersManageAttributes.name`,
|
||||
hint: `taf.settings.canPlayersManageAttributes.hint`,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DialogManager } from "../../utils/DialogManager.mjs";
|
||||
import { close } from "../../utils/DialogManager.mjs";
|
||||
import { localizer } from "../../utils/localizer.mjs";
|
||||
|
||||
export async function queryCancel(payload) {
|
||||
|
|
@ -15,5 +15,5 @@ export async function queryCancel(payload) {
|
|||
return;
|
||||
};
|
||||
|
||||
await DialogManager.close(id);
|
||||
close(id);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DialogManager } from "../../utils/DialogManager.mjs";
|
||||
import { ask } from "../../utils/DialogManager.mjs";
|
||||
import { localizer } from "../../utils/localizer.mjs";
|
||||
import { respondedToQueries } from "../../utils/QueryManager.mjs";
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ export async function queryPrompt(payload) {
|
|||
if (users != null && !users.includes(game.user.id)) { return };
|
||||
|
||||
request.id = id;
|
||||
const result = await DialogManager.ask(request, config);
|
||||
const result = await ask(request, config);
|
||||
if (result.state === `fronted`) {
|
||||
return;
|
||||
} else if (result.state === `errored`) {
|
||||
|
|
|
|||
2121
package-lock.json
generated
2121
package-lock.json
generated
File diff suppressed because it is too large
Load diff
12
package.json
12
package.json
|
|
@ -1,18 +1,16 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"@aws-sdk/client-s3": "^3.934.0",
|
||||
"@eslint/js": "^9.8.0",
|
||||
"@foundryvtt/foundryvtt-cli": "^1.0.3",
|
||||
"@stylistic/eslint-plugin": "^2.6.1",
|
||||
"axios": "^1.13.2",
|
||||
"dotenv": "^17.2.2",
|
||||
"eslint": "^9.8.0",
|
||||
"globals": "^15.9.0"
|
||||
"globals": "^15.9.0",
|
||||
"scripts": "file:./scripts"
|
||||
},
|
||||
"scripts": {
|
||||
"data:build": "node scripts/buildCompendia.mjs",
|
||||
"data:extract": "node scripts/extractCompendia.mjs",
|
||||
"link": "node scripts/linkFoundry.mjs",
|
||||
"data:build": "node scripts/src/buildCompendia.mjs",
|
||||
"data:extract": "node scripts/src/extractCompendia.mjs",
|
||||
"link": "node scripts/src/linkFoundry.mjs",
|
||||
"lint": "eslint --fix",
|
||||
"lint:nofix": "eslint"
|
||||
}
|
||||
|
|
|
|||
1
scripts
Submodule
1
scripts
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 06fb33b35ff446dee613afe271b6fe2ff976735a
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
import { compilePack } from "@foundryvtt/foundryvtt-cli";
|
||||
import { existsSync } from "fs";
|
||||
import { join } from "path";
|
||||
import { readFile } from "fs/promises";
|
||||
|
||||
async function main() {
|
||||
const system = JSON.parse(await readFile(`./system.json`, `utf-8`));
|
||||
|
||||
if (!system.packs || system.packs.length === 0) {
|
||||
console.log(`No compendium packs defined`);
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
for (const compendium of system.packs) {
|
||||
console.debug(`Packing ${compendium.label} (${compendium.name})`);
|
||||
let src = join(process.cwd(), compendium.path, `_source`);
|
||||
if (!existsSync(src)) {
|
||||
console.warn(`${compendium.path} doesn't exist, skipping.`)
|
||||
continue;
|
||||
};
|
||||
await compilePack(
|
||||
src,
|
||||
join(process.cwd(), compendium.path),
|
||||
{ recursive: true },
|
||||
);
|
||||
console.debug(`Finished packing ${compendium.name}`);
|
||||
};
|
||||
|
||||
console.log(`Finished packing compendia`)
|
||||
};
|
||||
|
||||
main();
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
import axios from "axios";
|
||||
|
||||
const {
|
||||
TAG,
|
||||
FORGEJO_SERVER_URL: WEB_URL,
|
||||
FORGEJO_API_URL: API,
|
||||
FORGEJO_REPOSITORY: REPO,
|
||||
FORGEJO_TOKEN: TOKEN,
|
||||
CDN_URL,
|
||||
} = process.env;
|
||||
|
||||
async function addReleaseAsset(releaseID, name) {
|
||||
return axios.post(
|
||||
`${API}/repos/${REPO}/releases/${releaseID}/assets`,
|
||||
{ external_url: `${CDN_URL}/${REPO}/${TAG}/${name}`, },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `token ${TOKEN}`,
|
||||
"Content-Type": `multipart/form-data`,
|
||||
},
|
||||
params: { name },
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
async function main() {
|
||||
|
||||
// Initial Release Data
|
||||
const release = await axios.post(
|
||||
`${API}/repos/${REPO}/releases`,
|
||||
{
|
||||
name: TAG,
|
||||
tag_name: TAG,
|
||||
draft: true,
|
||||
hide_archive_links: true,
|
||||
target_commitish: `main`,
|
||||
body: `<!-- Manifest URL: ${WEB_URL}/${REPO}/releases/download/${TAG}/system.json -->`,
|
||||
},
|
||||
{
|
||||
headers: { Authorization: `token ${TOKEN}` },
|
||||
}
|
||||
);
|
||||
|
||||
try {
|
||||
await addReleaseAsset(release.data.id, `release.zip`);
|
||||
await addReleaseAsset(release.data.id, `system.json`);
|
||||
} catch (e) {
|
||||
console.error(`Failed to add assets to the release`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
console.log(`Release created`);
|
||||
};
|
||||
|
||||
main();
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
import { readFile } from "fs/promises";
|
||||
import { join } from "path";
|
||||
import { extractPack } from "@foundryvtt/foundryvtt-cli";
|
||||
|
||||
async function main() {
|
||||
const system = JSON.parse(await readFile(`./system.json`, `utf-8`));
|
||||
|
||||
if (!system.packs || system.packs.length === 0) {
|
||||
console.log(`No compendium packs defined`);
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
for (const compendium of system.packs) {
|
||||
console.debug(`Unpacking ${compendium.label} (${compendium.name})`);
|
||||
let src = join(process.cwd(), compendium.path, `_source`);
|
||||
await extractPack(
|
||||
join(process.cwd(), compendium.path),
|
||||
src,
|
||||
{ recursive: true },
|
||||
);
|
||||
console.debug(`Finished packing ${compendium.name}`);
|
||||
};
|
||||
|
||||
console.log(`Finished unpacking compendia`);
|
||||
};
|
||||
|
||||
main();
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import { existsSync } from "fs";
|
||||
import { symlink, unlink } from "fs/promises";
|
||||
import { join } from "path";
|
||||
import { config } from "dotenv";
|
||||
|
||||
config({ quiet: true });
|
||||
|
||||
const root = process.env.FOUNDRY_ROOT;
|
||||
|
||||
// Early exit
|
||||
if (!root) {
|
||||
console.error(`Must provide a FOUNDRY_ROOT environment variable`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
// Assert Foundry exists
|
||||
if (!existsSync(root)) {
|
||||
console.error(`Foundry root not found.`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
// Removing existing symlink
|
||||
if (existsSync(`foundry`)) {
|
||||
console.log(`Attempting to unlink foundry instance`);
|
||||
try {
|
||||
await unlink(`foundry`);
|
||||
} catch {
|
||||
console.error(`Failed to unlink foundry folder.`);
|
||||
process.exit(1);
|
||||
};
|
||||
};
|
||||
|
||||
// Account for if the root is pointing at an Electron install
|
||||
let targetRoot = root;
|
||||
if (existsSync(join(root, `resources`, `app`))) {
|
||||
console.log(`Switching to use the "${root}/resources/app" directory`);
|
||||
targetRoot = join(root, `resources`, `app`);
|
||||
};
|
||||
|
||||
// Create symlink
|
||||
console.log(`Linking foundry source into folder`)
|
||||
try {
|
||||
await symlink(targetRoot, `foundry`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
};
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
const invalids = game.actors.invalidDocumentIds;
|
||||
invalids.forEach(id => {
|
||||
game.actors.getInvalid(id).delete();
|
||||
});
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
const invalids = game.items.invalidDocumentIds;
|
||||
invalids.forEach(id => {
|
||||
game.items.getInvalid(id).delete();
|
||||
});
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
The intent of this script is to do all of the modifications of the
|
||||
manifest file that we need to do in order to release the system.
|
||||
This can include removing dev-only fields/attributes that end
|
||||
users will never, and should never, care about nor need.
|
||||
*/
|
||||
import { readFile, writeFile } from "fs/promises";
|
||||
|
||||
const MANIFEST_PATH = `system.json`;
|
||||
|
||||
const {
|
||||
DOWNLOAD_URL,
|
||||
LATEST_URL,
|
||||
} = process.env;
|
||||
|
||||
let manifest;
|
||||
try {
|
||||
manifest = JSON.parse(await readFile(MANIFEST_PATH, `utf-8`));
|
||||
console.log(`Manifest loaded from disk`);
|
||||
} catch {
|
||||
console.error(`Failed to parse manifest file.`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
console.log(`Updating download/manifest URLs`)
|
||||
manifest.download = DOWNLOAD_URL;
|
||||
manifest.manifest = LATEST_URL;
|
||||
|
||||
// Filter out dev-only resources
|
||||
if (manifest.esmodules) {
|
||||
console.log(`Removing dev-only esmodules`);
|
||||
manifest.esmodules = manifest.esmodules.filter(
|
||||
filepath => !filepath.startsWith(`dev/`)
|
||||
);
|
||||
};
|
||||
|
||||
// Remove dev flags
|
||||
console.log(`Cleaning up flags`);
|
||||
delete manifest.flags?.hotReload;
|
||||
if (Object.keys(manifest.flags).length === 0) {
|
||||
delete manifest.flags;
|
||||
};
|
||||
|
||||
await writeFile(MANIFEST_PATH, JSON.stringify(manifest, undefined, `\t`));
|
||||
console.log(`Manifest written back to disk`);
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
import axios from "axios";
|
||||
|
||||
const {
|
||||
TAG_NAME,
|
||||
FORGEJO_API_URL: API_URL,
|
||||
FORGEJO_REPOSITORY: REPO,
|
||||
FORGEJO_TOKEN: TOKEN,
|
||||
} = process.env;
|
||||
|
||||
|
||||
async function main() {
|
||||
|
||||
if (!TAG_NAME) {
|
||||
console.log(`Tag name must not be blank`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
const requestURL = `${API_URL}/repos/${REPO}/tags/${TAG_NAME}`;
|
||||
|
||||
const response = await axios.get(
|
||||
requestURL,
|
||||
{
|
||||
headers: { Authorization: `token ${TOKEN}` },
|
||||
validateStatus: () => true,
|
||||
},
|
||||
);
|
||||
|
||||
// We actually *want* an error when the tag exists, instead of when
|
||||
// it doesn't
|
||||
if (response.status === 200) {
|
||||
console.log(`Tag with name "${TAG_NAME}" already exists`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
console.log(`Tag with name "${TAG_NAME}" not found, proceeding`);
|
||||
};
|
||||
|
||||
main();
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
||||
import { createReadStream } from "fs";
|
||||
|
||||
const requiredEnvVariables = [
|
||||
`TAG`, `FILE`,
|
||||
`FORGEJO_REPOSITORY`,
|
||||
`S3_BUCKET`, `S3_REGION`, `S3_KEY`, `S3_SECRET`, `S3_ENDPOINT`,
|
||||
];
|
||||
|
||||
async function main() {
|
||||
|
||||
// Assert all of the required env variables are present
|
||||
const missing = [];
|
||||
for (const envVar of requiredEnvVariables) {
|
||||
if (!(envVar in process.env)) {
|
||||
missing.push(envVar);
|
||||
};
|
||||
};
|
||||
if (missing.length > 0) {
|
||||
console.error(`Missing the following required environment variables: ${missing.join(`, `)}`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
const {
|
||||
TAG,
|
||||
S3_ENDPOINT,
|
||||
S3_REGION,
|
||||
S3_KEY,
|
||||
S3_SECRET,
|
||||
S3_BUCKET,
|
||||
FILE,
|
||||
FORGEJO_REPOSITORY: REPO,
|
||||
} = process.env;
|
||||
|
||||
const s3Client = new S3Client({
|
||||
endpoint: S3_ENDPOINT,
|
||||
forcePathStyle: false,
|
||||
region: S3_REGION,
|
||||
credentials: {
|
||||
accessKeyId: S3_KEY,
|
||||
secretAccessKey: S3_SECRET
|
||||
},
|
||||
});
|
||||
|
||||
const name = FILE.split(`/`).at(-1);
|
||||
|
||||
const params = {
|
||||
Bucket: S3_BUCKET,
|
||||
Key: `${REPO}/${TAG}/${name}`,
|
||||
Body: createReadStream(FILE),
|
||||
ACL: "public-read",
|
||||
METADATA: {
|
||||
"x-repo-version": TAG,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await s3Client.send(new PutObjectCommand(params));
|
||||
console.log("Upload successful");
|
||||
} catch (err) {
|
||||
console.error("Upload to s3 failed");
|
||||
};
|
||||
};
|
||||
|
||||
main();
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
"id": "taf",
|
||||
"title": "Text-Based Actors",
|
||||
"description": "An intentionally minimalist system that enables you to play rules-light games without getting in your way!",
|
||||
"version": "2.4.0",
|
||||
"version": "2.5.0",
|
||||
"download": "",
|
||||
"manifest": "",
|
||||
"url": "https://git.varify.ca/Foundry/taf",
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
type="button"
|
||||
data-action="cancel"
|
||||
>
|
||||
Cancel
|
||||
{{localize "taf.misc.cancel"}}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
>
|
||||
Confirm and Close
|
||||
{{localize "taf.misc.confirm-and-close"}}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
type="text"
|
||||
data-bind="{{ attr.id }}.name"
|
||||
value="{{ attr.name }}"
|
||||
placeholder="Attribute Name..."
|
||||
placeholder="{{localize "taf.Apps.AttributeManager.name-placeholder"}}"
|
||||
>
|
||||
{{else}}
|
||||
<span>{{ attr.name }}</span>
|
||||
{{/if}}
|
||||
<label>
|
||||
Has Maximum?
|
||||
{{localize "taf.Apps.AttributeManager.has-max"}}
|
||||
<input
|
||||
type="checkbox"
|
||||
data-bind="{{ attr.id }}.isRange"
|
||||
|
|
@ -32,10 +32,12 @@
|
|||
type="button"
|
||||
data-action="removeAttribute"
|
||||
>
|
||||
Delete
|
||||
{{localize "taf.misc.delete"}}
|
||||
</button>
|
||||
</div>
|
||||
{{else}}
|
||||
<p>No attributes yet</p>
|
||||
<p>
|
||||
{{localize "taf.Apps.AttributeManager.no-attributes"}}
|
||||
</p>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
type="button"
|
||||
data-action="addNew"
|
||||
>
|
||||
Add New Attribute
|
||||
{{localize "taf.Apps.AttributeManager.add-new-attribute"}}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
>
|
||||
Save and Close
|
||||
{{localize "taf.misc.save-and-close"}}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
class="attr-range__value"
|
||||
name="{{attr.path}}.value"
|
||||
value="{{attr.value}}"
|
||||
aria-label="Current value"
|
||||
aria-label="{{localize "taf.Apps.PlayerSheet.current-value"}}"
|
||||
data-tooltip="@{{ attr.id }}{{#if attr.isRange}}.value{{/if}}"
|
||||
>
|
||||
{{#if attr.isRange}}
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
class="attr-range__max"
|
||||
name="{{attr.path}}.max"
|
||||
value="{{attr.max}}"
|
||||
aria-label="Maximum value"
|
||||
aria-label="{{localize "taf.Apps.PlayerSheet.max-value"}}"
|
||||
data-tooltip="@{{ attr.id }}.max"
|
||||
>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@
|
|||
name="name"
|
||||
class="large"
|
||||
value="{{actor.name}}"
|
||||
placeholder="{{ localize 'Name' }}"
|
||||
placeholder="{{ localize "Name" }}"
|
||||
/>
|
||||
</header>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue