import logger from "../logger"; export async function migrate(): Promise { await migrateItems(); await migrateActors(); await migrateScenes(); await migrateCompendiums(); } async function migrateItems() { for (const item of game.items?.entities ?? []) { try { const updateData = getItemUpdateData(item._data); if (updateData) { logger.info(`Migrating Item entity ${item.name} (${item.id})`); await item.update(updateData), { enforceTypes: false }; } } catch (err) { err.message = `Error during migration of Item entity ${item.name} (${item.id}), continuing anyways.`; logger.error(err); } } } function getItemUpdateData(itemData: DeepPartial) { if (!["loot"].includes(itemData.type ?? "")) return undefined; return { data: { "-=equipped": null, }, }; } async function migrateActors() { for (const actor of game.actors?.entities ?? []) { try { const updateData = getActorUpdateData(actor._data); if (updateData) { logger.info(`Migrating Actor entity ${actor.name} (${actor.id})`); await actor.update(updateData, { enforceTypes: false }); } } catch (err) { err.message = `Error during migration of Actor entity ${actor.name} (${actor.id}), continuing anyways.`; logger.error(err); } } } function getActorUpdateData(actorData: DeepPartial) { let hasItemUpdates = false; const items = actorData.items?.map((itemData) => { const update = itemData ? getItemUpdateData(itemData) : undefined; if (update) { hasItemUpdates = true; return mergeObject(itemData, update, { enforceTypes: false, inplace: false }); } else { return itemData; } }); return hasItemUpdates ? { items } : undefined; } async function migrateScenes() { for (const scene of game.scenes?.entities ?? []) { try { const updateData = getSceneUpdateData(scene._data); if (updateData) { logger.info(`Migrating Scene entity ${scene.name} (${scene.id})`); await scene.update(updateData, { enforceTypes: false }); } } catch (err) { err.message = `Error during migration of Scene entity ${scene.name} (${scene.id}), continuing anyways.`; logger.error(err); } } } function getSceneUpdateData(sceneData: Scene.Data) { let hasTokenUpdates = false; const tokens = sceneData.tokens.map((tokenData) => { if (!tokenData.actorId || tokenData.actorLink || tokenData.actorData.data) { tokenData.actorData = {}; hasTokenUpdates = true; return tokenData; } const token = new Token(tokenData); if (!token.actor) { tokenData.actorId = null as unknown as string; tokenData.actorData = {}; hasTokenUpdates = true; } else if (!tokenData.actorLink) { const actorUpdateData = getActorUpdateData(token.data.actorData); tokenData.actorData = mergeObject(token.data.actorData, actorUpdateData); hasTokenUpdates = true; } return tokenData; }); if (!hasTokenUpdates) return undefined; return hasTokenUpdates ? { tokens } : undefined; } async function migrateCompendiums() { for (const compendium of game.packs ?? []) { if (compendium.metadata.package !== "world") continue; if (!["Actor", "Item", "Scene"].includes(compendium.metadata.entity)) continue; await migrateCompendium(compendium); } } async function migrateCompendium(compendium: Compendium) { const entityName = compendium.metadata.entity; if (!["Actor", "Item", "Scene"].includes(entityName)) return; const wasLocked = compendium.locked; await compendium.configure({ locked: false }); const content = await compendium.getContent(); for (const entity of content) { try { const getUpdateData = (entity: Entity) => { switch (entityName) { case "Item": return getItemUpdateData(entity._data); case "Actor": return getActorUpdateData(entity._data); case "Scene": return getSceneUpdateData(entity._data as Scene.Data); } }; const updateData = getUpdateData(entity); if (updateData) { logger.info(`Migrating entity ${entity.name} (${entity.id}) in compendium ${compendium.collection}`); await compendium.updateEntity({ ...updateData, _id: entity._id }); } } catch (err) { err.message = `Error during migration of entity ${entity.name} (${entity.id}) in compendium ${compendium.collection}, continuing anyways.`; logger.error(err); } } await compendium.migrate({}); await compendium.configure({ locked: wasLocked }); }