Attribute Item Subtype #76
6 changed files with 192 additions and 1 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
import { __ID__ } from "../consts.mjs";
|
import { __ID__ } from "../consts.mjs";
|
||||||
|
|
||||||
const { Actor } = foundry.documents;
|
const { Actor } = foundry.documents;
|
||||||
const { hasProperty } = foundry.utils;
|
const { hasProperty, setProperty } = foundry.utils;
|
||||||
|
|
||||||
export class TAFActor extends Actor {
|
export class TAFActor extends Actor {
|
||||||
|
|
||||||
|
|
@ -33,6 +33,12 @@ export class TAFActor extends Actor {
|
||||||
super._onEmbeddedDocumentChange(...args);
|
super._onEmbeddedDocumentChange(...args);
|
||||||
this.#sortedTypes = null;
|
this.#sortedTypes = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static migrateData(data, ...args) {
|
||||||
|
if (Object.keys(data.system?.attr ?? {}).length > 0) {
|
||||||
|
setProperty(data, `flags.${__ID__}.convertAttributesIntoItems`, true);
|
||||||
|
};
|
||||||
|
};
|
||||||
// #endregion Lifecycle
|
// #endregion Lifecycle
|
||||||
|
|
||||||
// #region Token Attributes
|
// #region Token Attributes
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
|
import { checkMigrations } from "../migrations/checkMigrations.mjs";
|
||||||
|
|
||||||
Hooks.on(`ready`, () => {
|
Hooks.on(`ready`, () => {
|
||||||
// Remove with issue: Foundry/taf#52
|
// Remove with issue: Foundry/taf#52
|
||||||
if (game.release.generation < 14 && globalThis._loc == null) {
|
if (game.release.generation < 14 && globalThis._loc == null) {
|
||||||
globalThis._loc = game.i18n.format.bind(game.i18n);
|
globalThis._loc = game.i18n.format.bind(game.i18n);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
checkMigrations();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
24
module/migrations/checkMigrations.mjs
Normal file
24
module/migrations/checkMigrations.mjs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { __ID__ } from "../consts.mjs";
|
||||||
|
import { Logger } from "../utils/Logger.mjs";
|
||||||
|
import { migrateTo3_0_0 } from "./v3.0.0.mjs";
|
||||||
|
|
||||||
|
const { isNewerVersion } = foundry.utils;
|
||||||
|
|
||||||
|
export async function checkMigrations() {
|
||||||
|
if (!game.user.isActiveGM) {
|
||||||
|
Logger.debug(`User not active GM, skipping data migrations`);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
const migrationVersion = game.settings.get(__ID__, `migrationVersion`);
|
||||||
|
let updateVersion = !migrationVersion;
|
||||||
|
|
||||||
|
if (isNewerVersion("3.0.0", migrationVersion)) {
|
||||||
|
await migrateTo3_0_0();
|
||||||
|
updateVersion = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (updateVersion) {
|
||||||
|
game.settings.set(__ID__, `migrationVersion`, game.system.version);
|
||||||
|
};
|
||||||
|
};
|
||||||
79
module/migrations/utils.mjs
Normal file
79
module/migrations/utils.mjs
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { __ID__ } from "../consts.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate the documents within a collection based on what
|
||||||
|
*
|
||||||
|
* This function was originally reproduced from [Draw Steel's codebase](https://github.com/MetaMorphic-Digital/draw-steel/blob/82a0a050da7c0d6d28c0cd283cf3b6915f47ee2a/src/module/data/migrations.mjs#L206-L226),
|
||||||
|
* with modifications to it to work better without
|
||||||
|
*
|
||||||
|
* @param collection The Collection of documents to update.
|
||||||
|
* @param flag The flag name to reference for if the document should be migrated.
|
||||||
|
* @param convertor The function that takes the document and performs the.
|
||||||
|
* transformations to get the required update data.
|
||||||
|
* @param options Options to configure how the method behaves.
|
||||||
|
* @param options.pack The compendium pack to update.
|
||||||
|
* @param options.parent Parent of the collection for embedded collections.
|
||||||
|
* @param options.update Whether or not this method should perform the update, or pass back the array of DB operations.
|
||||||
|
* @returns An array of batch operations to perform.
|
||||||
|
*/
|
||||||
|
export async function migrateCollection(
|
||||||
|
collection,
|
||||||
|
flag,
|
||||||
|
convertor,
|
||||||
|
options = {}
|
||||||
|
) {
|
||||||
|
const toMigrate = collection
|
||||||
|
.filter(doc => {
|
||||||
|
console.log(`toMigrate.filter doc`, doc);
|
||||||
|
return doc.getFlag(__ID__, flag)
|
||||||
|
})
|
||||||
|
.map(doc => {
|
||||||
|
const update = convertor(doc) ?? {};
|
||||||
|
update[`_id`] = doc._id;
|
||||||
|
|
||||||
|
// v13/v14+ compatibility shim
|
||||||
|
if (game.release.generation > 13) {
|
||||||
|
update[`flags.${__ID__}.${flag}`] = _del;
|
||||||
|
} else {
|
||||||
|
update[`flags.${__ID__}.-=${flag}`] = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
return update;
|
||||||
|
})
|
||||||
|
.filter(data => !!data);
|
||||||
|
// update in increments of 100
|
||||||
|
// TODO: optionally return an array of DB operations for modifyBatch
|
||||||
|
const batches = Math.ceil(toMigrate.length / 100);
|
||||||
|
for (let i = 0; i < batches; i++) {
|
||||||
|
const updateData = toMigrate.slice(i * 100, (i + 1) * 100);
|
||||||
|
await collection.documentClass.updateDocuments(
|
||||||
|
updateData,
|
||||||
|
{
|
||||||
|
pack: options.pack,
|
||||||
|
parent: options.parent,
|
||||||
|
diff: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a compendium pack should be migrated during `migrateWorld`.
|
||||||
|
*
|
||||||
|
* This function was reproduced from [Draw Steel's codebase](https://github.com/MetaMorphic-Digital/draw-steel/blob/82a0a050da7c0d6d28c0cd283cf3b6915f47ee2a/src/module/data/migrations.mjs#L287-L302)
|
||||||
|
*
|
||||||
|
* @param pack The CompendiumPack document
|
||||||
|
* @returns {boolean} Whether or not the pack should be migrated
|
||||||
|
*/
|
||||||
|
export function shouldMigrateCompendium(pack) {
|
||||||
|
// We only care about actor and item migrations
|
||||||
|
if (!["Actor", "Item"].includes(pack.documentName)) return false;
|
||||||
|
|
||||||
|
// World compendiums should all be migrated, system ones should never by migrated
|
||||||
|
if (pack.metadata.packageType === "world") return true;
|
||||||
|
if (pack.metadata.packageType === "system") return false;
|
||||||
|
|
||||||
|
// Module compendiums should only be migrated if they don't have a download or manifest URL
|
||||||
|
const module = game.modules.get(pack.metadata.packageName);
|
||||||
|
return !module.download && !module.manifest;
|
||||||
|
}
|
||||||
72
module/migrations/v3.0.0.mjs
Normal file
72
module/migrations/v3.0.0.mjs
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { Logger } from "../utils/Logger.mjs";
|
||||||
|
import { migrateCollection, shouldMigrateCompendium } from "./utils.mjs";
|
||||||
|
|
||||||
|
const flag = `convertAttributesIntoItems`;
|
||||||
|
const operations = [];
|
||||||
|
|
||||||
|
export async function migrateTo3_0_0() {
|
||||||
|
Logger.debug(`Starting v3.0.0 data migration`);
|
||||||
|
|
||||||
|
operations.push(
|
||||||
|
...await migrateCollection(
|
||||||
|
game.actors,
|
||||||
|
flag,
|
||||||
|
handleMigratingActor,
|
||||||
|
{ update: false, },
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// for (const pack of game.packs) {
|
||||||
|
// if (
|
||||||
|
// pack.metadata.type !== "Actor"
|
||||||
|
// || !shouldMigrateCompendium(pack)
|
||||||
|
// ) {
|
||||||
|
// continue;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// await pack.getDocuments();
|
||||||
|
|
||||||
|
// // TODO: unlock compendium if required then re-lock after finishing
|
||||||
|
// await migrateCollection(
|
||||||
|
// pack,
|
||||||
|
// flag,
|
||||||
|
// handleMigratingActor,
|
||||||
|
// { pack },
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// TODO: create the item documents (batch them if possible)
|
||||||
|
Logger.debug(`Finished v3.0.0 migration, resulting operations:`);
|
||||||
|
console.log(operations);
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleMigratingActor(actor) {
|
||||||
|
console.log(actor);
|
||||||
|
|
||||||
|
const operation = {
|
||||||
|
action: `create`,
|
||||||
|
documentName: `Item`,
|
||||||
|
parent: actor,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const attrs = actor.system.attr;
|
||||||
|
for (const [ key, attr ] of Object.entries(attrs)) {
|
||||||
|
operation.data.push(convertToItem(key, attr));
|
||||||
|
};
|
||||||
|
operations.push(operation);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function convertToItem(key, attr) {
|
||||||
|
return {
|
||||||
|
name: attr.name,
|
||||||
|
type: "attribute",
|
||||||
|
system: {
|
||||||
|
key,
|
||||||
|
value: attr.value,
|
||||||
|
max: attr.isRange ? attr.max : null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -74,4 +74,10 @@ export function registerWorldSettings() {
|
||||||
type: Object,
|
type: Object,
|
||||||
scope: `world`,
|
scope: `world`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.settings.register(__ID__, `migrationVersion`, {
|
||||||
|
config: false,
|
||||||
|
type: String,
|
||||||
|
scope: `world`,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue