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
|
# The absolute path to the Foundry installation to create symlinks to
|
||||||
FOUNDRY_ROOT=""
|
FOUNDRY_ROOT=""
|
||||||
|
|
||||||
|
# The manifest file for the module/system
|
||||||
|
MANIFEST="./system.json"
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,17 @@
|
||||||
on: [ workflow_dispatch ]
|
on: [ workflow_dispatch ]
|
||||||
|
env:
|
||||||
|
MANIFEST: "system.json"
|
||||||
jobs:
|
jobs:
|
||||||
create-artifacts:
|
create-draft-release:
|
||||||
name: "Create artifacts"
|
name: "Create Draft Release"
|
||||||
runs-on: act
|
runs-on: act
|
||||||
|
outputs:
|
||||||
|
version: ${{steps.version.outputs.version}}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm clean-install
|
run: npm clean-install
|
||||||
|
|
@ -14,7 +20,7 @@ jobs:
|
||||||
run: cat system.json | echo version=`jq -r ".version"` >> "$FORGEJO_OUTPUT"
|
run: cat system.json | echo version=`jq -r ".version"` >> "$FORGEJO_OUTPUT"
|
||||||
|
|
||||||
- name: Assert that the tag doesn't exist
|
- name: Assert that the tag doesn't exist
|
||||||
run: node scripts/tagExists.mjs
|
run: node scripts/src/tagExists.mjs
|
||||||
env:
|
env:
|
||||||
TAG_NAME: "v${{steps.version.outputs.version}}"
|
TAG_NAME: "v${{steps.version.outputs.version}}"
|
||||||
|
|
||||||
|
|
@ -24,73 +30,53 @@ jobs:
|
||||||
- name: Remove compendia source
|
- name: Remove compendia source
|
||||||
run: "rm -rf packs/**/_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
|
- name: Update manifest
|
||||||
run: node scripts/prepareManifest.mjs
|
run: node scripts/src/prepareManifest.mjs
|
||||||
env:
|
env:
|
||||||
DOWNLOAD_URL: "${{forgejo.server_url}}/${{forgejo.repository}}/releases/download/v${{steps.version.outputs.version}}/release.zip"
|
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"
|
LATEST_URL: "${{forgejo.server_url}}/${{forgejo.repository}}/releases/download/latest/system.json"
|
||||||
|
|
||||||
- name: Add manifest into release archive
|
- name: Compress files
|
||||||
run: zip release.zip --update system.json
|
run: zip -r release.zip langs module styles templates README.md assets LICENSE ${{env.MANIFEST}}
|
||||||
|
|
||||||
- name: Upload archive to s3
|
- name: Create forgejo release
|
||||||
run: node scripts/uploadToS3.mjs
|
run: node scripts/src/createForgejoRelease.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
|
|
||||||
env:
|
env:
|
||||||
TAG: "v${{steps.version.outputs.version}}"
|
TAG: "v${{steps.version.outputs.version}}"
|
||||||
CDN_URL: "${{vars.CDN_URL}}"
|
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",
|
"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"
|
"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": {
|
"sheetDefaultHeight": {
|
||||||
"name": "Default Actor Sheet Height",
|
"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."
|
"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",
|
"Key": "Key",
|
||||||
"Value": "Value",
|
"Value": "Value",
|
||||||
"no-data-submitted": "No data submitted",
|
"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": {
|
"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": {
|
"QueryStatus": {
|
||||||
"title": "Information Request Status",
|
"title": "Information Request Status",
|
||||||
"user-disconnected-tooltip": "This user is not logged in to Foundry",
|
"user-disconnected-tooltip": "This user is not logged in to Foundry",
|
||||||
|
|
@ -55,7 +81,8 @@
|
||||||
"label": "Height"
|
"label": "Height"
|
||||||
},
|
},
|
||||||
"Resizable": {
|
"Resizable": {
|
||||||
"label": "Resizable"
|
"label": "Resizable",
|
||||||
|
"placeholder": "Default ({placeholder})"
|
||||||
},
|
},
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"foundry": "Foundry",
|
"foundry": "Foundry",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { __ID__, filePath } from "../consts.mjs";
|
import { __ID__, filePath } from "../consts.mjs";
|
||||||
|
import { localizer } from "../utils/localizer.mjs";
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
|
|
@ -24,7 +25,7 @@ export class Ask extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
width: 330,
|
width: 330,
|
||||||
},
|
},
|
||||||
window: {
|
window: {
|
||||||
title: `Questions`,
|
title: `taf.Apps.Ask.title`,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
minimizable: true,
|
minimizable: true,
|
||||||
contentTag: `form`,
|
contentTag: `form`,
|
||||||
|
|
@ -80,7 +81,10 @@ export class Ask extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
|
|
||||||
for (const input of inputs) {
|
for (const input of inputs) {
|
||||||
if (!validInputTypes.includes(input.type)) {
|
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`;
|
input.type = `error`;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { __ID__, filePath } from "../consts.mjs";
|
import { __ID__, filePath } from "../consts.mjs";
|
||||||
import { attributeSorter } from "../utils/attributeSort.mjs";
|
import { attributeSorter } from "../utils/attributeSort.mjs";
|
||||||
|
import { localizer } from "../utils/localizer.mjs";
|
||||||
import { toID } from "../utils/toID.mjs";
|
import { toID } from "../utils/toID.mjs";
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
@ -52,7 +53,10 @@ export class AttributeManager extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
};
|
};
|
||||||
|
|
||||||
get title() {
|
get title() {
|
||||||
return `Attributes: ${this.#doc.name}`;
|
return localizer(
|
||||||
|
`taf.Apps.AttributeManager.title`,
|
||||||
|
this.#doc,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
// #endregion Instance Data
|
// #endregion Instance Data
|
||||||
|
|
||||||
|
|
@ -102,7 +106,6 @@ export class AttributeManager extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
attrs.push({
|
attrs.push({
|
||||||
id,
|
id,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
displayName: data.isNew ? `New Attribute` : data.name,
|
|
||||||
sort: data.sort,
|
sort: data.sort,
|
||||||
isRange: data.isRange,
|
isRange: data.isRange,
|
||||||
isNew: data.isNew ?? false,
|
isNew: data.isNew ?? false,
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
|
||||||
|
|
||||||
controls.push({
|
controls.push({
|
||||||
icon: `fa-solid fa-at`,
|
icon: `fa-solid fa-at`,
|
||||||
label: `Manage Attributes`,
|
label: `taf.Apps.PlayerSheet.manage-attributes`,
|
||||||
action: `manageAttributes`,
|
action: `manageAttributes`,
|
||||||
visible: () => {
|
visible: () => {
|
||||||
const isGM = game.user.isGM;
|
const isGM = game.user.isGM;
|
||||||
|
|
@ -167,7 +167,6 @@ export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if ( event.detail > 1 ) { return }
|
if ( event.detail > 1 ) { return }
|
||||||
|
|
||||||
// const docSheetConfigWidth = TAFDocumentSheetConfig.DEFAULT_OPTIONS.position.width;
|
|
||||||
new TAFDocumentSheetConfig({
|
new TAFDocumentSheetConfig({
|
||||||
document: this.document,
|
document: this.document,
|
||||||
position: {
|
position: {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { __ID__, filePath } from "../consts.mjs";
|
import { __ID__, filePath } from "../consts.mjs";
|
||||||
import { getDefaultSizing } from "../utils/getSizing.mjs";
|
import { getDefaultSizing } from "../utils/getSizing.mjs";
|
||||||
|
import { localizer } from "../utils/localizer.mjs";
|
||||||
|
|
||||||
const { diffObject, expandObject, flattenObject } = foundry.utils;
|
const { diffObject, expandObject, flattenObject } = foundry.utils;
|
||||||
const { DocumentSheetConfig } = foundry.applications.apps;
|
const { DocumentSheetConfig } = foundry.applications.apps;
|
||||||
|
|
@ -74,7 +75,9 @@ export class TAFDocumentSheetConfig extends DocumentSheetConfig {
|
||||||
const defaults = getDefaultSizing();
|
const defaults = getDefaultSizing();
|
||||||
context.placeholders = {
|
context.placeholders = {
|
||||||
...defaults,
|
...defaults,
|
||||||
resizable: defaults.resizable ? `Resizable` : `Not Resizable`,
|
resizable: defaults.resizable
|
||||||
|
? localizer(`taf.misc.resizable`)
|
||||||
|
: localizer(`taf.misc.not-resizable`),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Custom values from document itself
|
// Custom values from document itself
|
||||||
|
|
@ -88,9 +91,15 @@ export class TAFDocumentSheetConfig extends DocumentSheetConfig {
|
||||||
|
|
||||||
// Static prep
|
// Static prep
|
||||||
context.resizeOptions = [
|
context.resizeOptions = [
|
||||||
{ label: `Default (${context.placeholders.resizable})`, value: `` },
|
{
|
||||||
{ label: `Resizable`, value: `true` },
|
label: localizer(
|
||||||
{ label: `No Resizing`, value: `false` },
|
`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
|
// #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
|
// Documents
|
||||||
import { TAFActor } from "../documents/Actor.mjs";
|
import { TAFActor } from "../documents/Actor.mjs";
|
||||||
|
import { TAFCombatant } from "../documents/Combatant.mjs";
|
||||||
import { TAFItem } from "../documents/Item.mjs";
|
import { TAFItem } from "../documents/Item.mjs";
|
||||||
import { TAFTokenDocument } from "../documents/Token.mjs";
|
import { TAFTokenDocument } from "../documents/Token.mjs";
|
||||||
|
|
||||||
|
|
@ -25,6 +26,7 @@ Hooks.on(`init`, () => {
|
||||||
|
|
||||||
CONFIG.Token.documentClass = TAFTokenDocument;
|
CONFIG.Token.documentClass = TAFTokenDocument;
|
||||||
CONFIG.Actor.documentClass = TAFActor;
|
CONFIG.Actor.documentClass = TAFActor;
|
||||||
|
CONFIG.Combatant.documentClass = TAFCombatant;
|
||||||
|
|
||||||
CONFIG.Actor.dataModels.player = PlayerData;
|
CONFIG.Actor.dataModels.player = PlayerData;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,16 @@ import { __ID__ } from "../consts.mjs";
|
||||||
const { NumberField, StringField } = foundry.data.fields;
|
const { NumberField, StringField } = foundry.data.fields;
|
||||||
|
|
||||||
export function registerWorldSettings() {
|
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`, {
|
game.settings.register(__ID__, `canPlayersManageAttributes`, {
|
||||||
name: `taf.settings.canPlayersManageAttributes.name`,
|
name: `taf.settings.canPlayersManageAttributes.name`,
|
||||||
hint: `taf.settings.canPlayersManageAttributes.hint`,
|
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";
|
import { localizer } from "../../utils/localizer.mjs";
|
||||||
|
|
||||||
export async function queryCancel(payload) {
|
export async function queryCancel(payload) {
|
||||||
|
|
@ -15,5 +15,5 @@ export async function queryCancel(payload) {
|
||||||
return;
|
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 { localizer } from "../../utils/localizer.mjs";
|
||||||
import { respondedToQueries } from "../../utils/QueryManager.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 };
|
if (users != null && !users.includes(game.user.id)) { return };
|
||||||
|
|
||||||
request.id = id;
|
request.id = id;
|
||||||
const result = await DialogManager.ask(request, config);
|
const result = await ask(request, config);
|
||||||
if (result.state === `fronted`) {
|
if (result.state === `fronted`) {
|
||||||
return;
|
return;
|
||||||
} else if (result.state === `errored`) {
|
} else if (result.state === `errored`) {
|
||||||
|
|
|
||||||
2119
package-lock.json
generated
2119
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": {
|
"devDependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.934.0",
|
|
||||||
"@eslint/js": "^9.8.0",
|
"@eslint/js": "^9.8.0",
|
||||||
"@foundryvtt/foundryvtt-cli": "^1.0.3",
|
"@foundryvtt/foundryvtt-cli": "^1.0.3",
|
||||||
"@stylistic/eslint-plugin": "^2.6.1",
|
"@stylistic/eslint-plugin": "^2.6.1",
|
||||||
"axios": "^1.13.2",
|
|
||||||
"dotenv": "^17.2.2",
|
|
||||||
"eslint": "^9.8.0",
|
"eslint": "^9.8.0",
|
||||||
"globals": "^15.9.0"
|
"globals": "^15.9.0",
|
||||||
|
"scripts": "file:./scripts"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"data:build": "node scripts/buildCompendia.mjs",
|
"data:build": "node scripts/src/buildCompendia.mjs",
|
||||||
"data:extract": "node scripts/extractCompendia.mjs",
|
"data:extract": "node scripts/src/extractCompendia.mjs",
|
||||||
"link": "node scripts/linkFoundry.mjs",
|
"link": "node scripts/src/linkFoundry.mjs",
|
||||||
"lint": "eslint --fix",
|
"lint": "eslint --fix",
|
||||||
"lint:nofix": "eslint"
|
"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",
|
"id": "taf",
|
||||||
"title": "Text-Based Actors",
|
"title": "Text-Based Actors",
|
||||||
"description": "An intentionally minimalist system that enables you to play rules-light games without getting in your way!",
|
"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": "",
|
"download": "",
|
||||||
"manifest": "",
|
"manifest": "",
|
||||||
"url": "https://git.varify.ca/Foundry/taf",
|
"url": "https://git.varify.ca/Foundry/taf",
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
type="button"
|
type="button"
|
||||||
data-action="cancel"
|
data-action="cancel"
|
||||||
>
|
>
|
||||||
Cancel
|
{{localize "taf.misc.cancel"}}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
Confirm and Close
|
{{localize "taf.misc.confirm-and-close"}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@
|
||||||
type="text"
|
type="text"
|
||||||
data-bind="{{ attr.id }}.name"
|
data-bind="{{ attr.id }}.name"
|
||||||
value="{{ attr.name }}"
|
value="{{ attr.name }}"
|
||||||
placeholder="Attribute Name..."
|
placeholder="{{localize "taf.Apps.AttributeManager.name-placeholder"}}"
|
||||||
>
|
>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{ attr.name }}</span>
|
<span>{{ attr.name }}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<label>
|
<label>
|
||||||
Has Maximum?
|
{{localize "taf.Apps.AttributeManager.has-max"}}
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
data-bind="{{ attr.id }}.isRange"
|
data-bind="{{ attr.id }}.isRange"
|
||||||
|
|
@ -32,10 +32,12 @@
|
||||||
type="button"
|
type="button"
|
||||||
data-action="removeAttribute"
|
data-action="removeAttribute"
|
||||||
>
|
>
|
||||||
Delete
|
{{localize "taf.misc.delete"}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>No attributes yet</p>
|
<p>
|
||||||
|
{{localize "taf.Apps.AttributeManager.no-attributes"}}
|
||||||
|
</p>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
type="button"
|
type="button"
|
||||||
data-action="addNew"
|
data-action="addNew"
|
||||||
>
|
>
|
||||||
Add New Attribute
|
{{localize "taf.Apps.AttributeManager.add-new-attribute"}}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
Save and Close
|
{{localize "taf.misc.save-and-close"}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
class="attr-range__value"
|
class="attr-range__value"
|
||||||
name="{{attr.path}}.value"
|
name="{{attr.path}}.value"
|
||||||
value="{{attr.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}}"
|
data-tooltip="@{{ attr.id }}{{#if attr.isRange}}.value{{/if}}"
|
||||||
>
|
>
|
||||||
{{#if attr.isRange}}
|
{{#if attr.isRange}}
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
class="attr-range__max"
|
class="attr-range__max"
|
||||||
name="{{attr.path}}.max"
|
name="{{attr.path}}.max"
|
||||||
value="{{attr.max}}"
|
value="{{attr.max}}"
|
||||||
aria-label="Maximum value"
|
aria-label="{{localize "taf.Apps.PlayerSheet.max-value"}}"
|
||||||
data-tooltip="@{{ attr.id }}.max"
|
data-tooltip="@{{ attr.id }}.max"
|
||||||
>
|
>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,6 @@
|
||||||
name="name"
|
name="name"
|
||||||
class="large"
|
class="large"
|
||||||
value="{{actor.name}}"
|
value="{{actor.name}}"
|
||||||
placeholder="{{ localize 'Name' }}"
|
placeholder="{{ localize "Name" }}"
|
||||||
/>
|
/>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue