Attribute Item Subtype #76
6 changed files with 192 additions and 1 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { __ID__ } from "../consts.mjs";
|
||||
|
||||
const { Actor } = foundry.documents;
|
||||
const { hasProperty } = foundry.utils;
|
||||
const { hasProperty, setProperty } = foundry.utils;
|
||||
|
||||
export class TAFActor extends Actor {
|
||||
|
||||
|
|
@ -33,6 +33,12 @@ export class TAFActor extends Actor {
|
|||
super._onEmbeddedDocumentChange(...args);
|
||||
this.#sortedTypes = null;
|
||||
};
|
||||
|
||||
static migrateData(data, ...args) {
|
||||
if (Object.keys(data.system?.attr ?? {}).length > 0) {
|
||||
setProperty(data, `flags.${__ID__}.convertAttributesIntoItems`, true);
|
||||
};
|
||||
};
|
||||
// #endregion Lifecycle
|
||||
|
||||
// #region Token Attributes
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import { checkMigrations } from "../migrations/checkMigrations.mjs";
|
||||
|
||||
Hooks.on(`ready`, () => {
|
||||
// Remove with issue: Foundry/taf#52
|
||||
if (game.release.generation < 14 && globalThis._loc == null) {
|
||||
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,
|
||||
scope: `world`,
|
||||
});
|
||||
|
||||
game.settings.register(__ID__, `migrationVersion`, {
|
||||
config: false,
|
||||
type: String,
|
||||
scope: `world`,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue