Skip to content

Commit

Permalink
v2.6.7
Browse files Browse the repository at this point in the history
- Fixed the "Adventure Converter" to correctly handle compendium pack paths presented by Foundry Core during the suggested `module.json` file changes.
- Updated the "Bulk Pack Scenes" macro to correctly handle differences in folder data structure for nested folders in V10.
- Improved the folder creation process when utilising structures exported by the Compendium Folders module.
- Improved the handling of scene note icons in v10.
  • Loading branch information
sneat authored Oct 14, 2022
1 parent 0b4a11d commit ca637d3
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 31 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v2.6.7

- Fixed the "Adventure Converter" to correctly handle compendium pack paths presented by Foundry Core during the suggested `module.json` file changes.
- Updated the "Bulk Pack Scenes" macro to correctly handle differences in folder data structure for nested folders in V10.
- Improved the folder creation process when utilising structures exported by the Compendium Folders module.
- Improved the handling of scene note icons in v10.

## v2.6.6

- Migrate items as well for D&D5e system updates.
Expand Down
4 changes: 2 additions & 2 deletions languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -504,13 +504,13 @@
"manifest-upgrade-detail-2": "Added an <code>Adventure</code> pack.",
"manifest-upgrade-detail-3": "Changed the <code>compatibility</code> to be a minimum of V10.",
"manifest-upgrade-detail-4": "The conversion process done by the Core Foundry VTT platform will have output warnings to the Console (F12). Consider reviewing these warnings for additional context on the changes other than the two above.",
"manifest-upgrade-next-steps": "You will need to perform the following steps manually before your adventure module can be converted (take a note of them in case you close this dialog):",
"manifest-upgrade-next-steps": "You will need to perform the following steps manually before your adventure module can be converted (take a note or screenshot of them as you will close this dialog before completing all of the steps):",
"manifest-upgrade-next-steps-1": "Open the <code>{module}</code> file in your text editor.",
"manifest-upgrade-next-steps-2": "Replace the file with the contents below and review the changes. Make any additional changes that you feel are appropriate. If you have any queries, please join the Discord server for assistance.",
"manifest-upgrade-next-steps-3": "Save the file.",
"manifest-upgrade-next-steps-4": "Exit this world, returning to the setup screen (this reloads the module details).",
"manifest-upgrade-next-steps-5": "Load the world again and return to the Adventure Converter. Select the module you just updated and proceed with the conversion.",
"manifest-upgrade-automated-steps": "The following file has been created automatically to store the Adventure compendium database. If you have chosen to use a format that is different than the suggested <code>module.json</code> changes above, then you may need to create your own compendium database file.",
"manifest-upgrade-automated-steps": "The following file path has been chosen automatically to store the Adventure compendium database. If you have chosen to use a format that is different than the suggested <code>module.json</code> changes above, then you may need to manually adjust the pack paths.",
"manifest-upgrade-ok": "I've followed the steps above.",
"manifest-upgrade-error": "Error generating recommended changes to module.json. Please check the console (F12) for more information.",
"manifest-upgrade-module-not-found": "Module \"{name}\" does not exist within the world.",
Expand Down
2 changes: 1 addition & 1 deletion module.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "scene-packer",
"title": "Library: Scene Packer",
"description": "A module to assist with Scene and Adventure packing and unpacking.",
"version": "2.6.6",
"version": "2.6.7",
"library": "true",
"manifestPlusVersion": "1.2.0",
"minimumCoreVersion": "0.8.6",
Expand Down
2 changes: 1 addition & 1 deletion packs/macros.db
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{"_id":"L2BGaj7HBxJHOSkM","name":"Bulk replace asset references","type":"script","author":"MRUsyvFBYyl6GZtk","img":"icons/svg/lightning.svg","scope":"global","command":"/*\n * Bulk replace asset references\n */\n(async () => {\n Dialog.prompt({\n title: 'Bulk replace asset references',\n content:\n '<p>This tool will search for asset references <strong>within your world</strong> that start with the provided value and replace that portion with the other provided value.</p>' +\n '<p><label>Find (case sensitive): <input type=\"text\" name=\"find\" placeholder=\"some/original/path/\"></label></p>' +\n '<p><label>Replace (case sensitive): <input type=\"text\" name=\"replace\" placeholder=\"your/new/path/\"></label></p>' +\n '<hr><p><label><input type=\"checkbox\"> Save changes?</label></p><p>Leaving this unchecked will operate in a \"dry run\" mode, where changes are only output to the console (F12).</p><hr>',\n label: 'Bulk replace',\n callback: async (html) => {\n const find = html.find('input[name=\"find\"]').val();\n const replace = html.find('input[name=\"replace\"]').val();\n const dryRun = !html.find('input[type=\"checkbox\"]')[0].checked;\n if (!find || !replace) {\n ui.notifications.warn('Please provide both a find and replace value.', {permanent: true});\n console.warn('Bulk replace asset references: Please provide both a find and replace value.');\n return;\n }\n\n const documentTypes = CONST.COMPENDIUM_DOCUMENT_TYPES || CONST.COMPENDIUM_ENTITY_TYPES || [];\n for (const documentType of documentTypes) {\n const collectionName = CONFIG[documentType]?.documentClass?.collectionName;\n if (!collectionName) {\n console.warn(`Bulk replace asset references: No collection name for ${documentType}`);\n continue;\n }\n\n const collection = game[collectionName];\n if (!collection) {\n continue;\n }\n\n console.groupCollapsed(`Bulk replace asset references: ${collectionName}`);\n for (const document of collection) {\n const original = document.toJSON();\n const replacementData = JSON.stringify(original).replaceAll(`\"${find}`, `\"${replace}`);\n if (original === replacementData) {\n continue;\n }\n\n const diff = diffObject(original, JSON.parse(replacementData));\n if (isObjectEmpty(diff)) {\n continue;\n }\n\n console.log(`Bulk replace asset references: Updating ${documentType} ${document.id} ${document.name}`);\n console.table(diff);\n if (!dryRun) {\n await document.update(diff);\n }\n }\n\n console.groupEnd();\n }\n\n ui.notifications.info('Bulk replace asset references complete. Check the console (F12) for full details.', {permanent: true});\n console.log('Bulk replace asset references complete.');\n },\n });\n})();","folder":null,"sort":0,"permission":{"default":0,"MRUsyvFBYyl6GZtk":3},"flags":{"core":{"sourceId":"Macro.YpZnc0IWBVWtIoJO"},"scene-packer":{"sourceId":"Macro.YpZnc0IWBVWtIoJO"}}}
{"_id":"OUvevMPeaRKzQBVu","name":"Bulk Lock/Unlock compendiums","type":"script","author":"MRUsyvFBYyl6GZtk","img":"icons/svg/door-locked-outline.svg","scope":"global","command":"// This macro allows you to bulk lock or unlock compendiums\n// as a way to save time.\n(() => {\n if (!game.user.isGM) {\n return;\n }\n\n let activeModules = (isNewerVersion(game.version ?? game.data.version, '10') ? game.modules : game.data.modules)\n .filter((m) => m.active && ((m.packs ?? m.data?.packs)?.size || m.packs?.length))\n .map((m) => m.id);\n if (!activeModules.length) {\n ui.notifications.info(\n \"There are no modules with compendium packs in this world.\"\n );\n return;\n }\n let hasWorldCompendiums = !!game.packs.find(p => (p.metadata.packageName || p.metadata.package) === 'world')\n let content = `<p>Bulk Lock/Unlock compendium packs that belong to the following module:</p>`;\n content += '<select id=\"module-name\">';\n activeModules.forEach((m) => {\n content += `<option value=\"${m}\">${m}</option>`;\n });\n if (hasWorldCompendiums) {\n content += `<option value=\"world\">world</option>`;\n }\n content += \"</select>\";\n content += \"<p><hr></p>\";\n let d = new Dialog({\n title: \"Bulk Lock/Unlock compendium packs\",\n content: content,\n buttons: {\n lock: {\n icon: '<i class=\"fas fa-lock\"></i>',\n label: game.i18n.localize(\"Lock\"),\n callback: async (html) => {\n await setState(true, html.find(\"#module-name\")[0].value);\n },\n },\n unlock: {\n icon: '<i class=\"fas fa-unlock\"></i>',\n label: game.i18n.localize(\"Unlock\"),\n callback: async (html) => {\n await setState(false, html.find(\"#module-name\")[0].value);\n },\n },\n cancel: {\n icon: '<i class=\"fas fa-times\"></i>',\n label: game.i18n.localize(\"Cancel\"),\n },\n },\n });\n d.render(true);\n\n async function setState(locked, moduleName) {\n locked = !!locked;\n const compendiums = game.packs.filter(\n (p) => (p.metadata.packageName || p.metadata.package) === moduleName\n );\n const settings = {};\n compendiums.forEach((p) => {\n settings[`${(p.metadata.packageName || p.metadata.package)}.${p.metadata.name}`] = { locked };\n });\n if (Object.keys(settings).length) {\n let key = locked\n ? \"Locking compendiums: {list}\"\n : \"Unlocking compendiums: {list}\";\n ui.notifications.info(\n game.i18n.format(key, {\n list: Object.keys(settings).join(\", \"),\n locked: locked,\n })\n );\n let configSetting =\n Compendium?.CONFIG_SETTING ||\n CompendiumCollection?.CONFIG_SETTING ||\n \"compendiumConfiguration\";\n await game.settings.set(\"core\", configSetting, settings);\n }\n }\n})();","folder":null,"sort":0,"permission":{"default":0},"flags":{"scene-packer":{"hash":"9526d9354098381b75dbb4a47300957cbdf45c4b","sourceId":"Macro.cEYqc2chS1vOpIPo"},"core":{"sourceId":"Macro.cEYqc2chS1vOpIPo"}}}
{"name":"Show Scenes Worth Packing","type":"script","author":"XKmxUPdkcWMuKdfu","img":"icons/svg/eye.svg","scope":"global","command":"// This macro will check your world Scenes to see whether\n// there is any data that would benefit from being Packed.\n\nScenePacker.ShowScenesWorthPacking();","folder":null,"sort":0,"permission":{"default":0,"XKmxUPdkcWMuKdfu":3},"flags":{"core":{"sourceId":"Macro.zo5hb9xMPyiUEqrE"}},"_id":"P3UkVzGKhtwAcpRT"}
{"_id":"YsJZfzxws5UeXYJC","name":"Bulk pack scenes","type":"script","author":"FYKEkGQDWeedzh8v","img":"icons/svg/barrel.svg","scope":"global","command":"// This macro will pack/repack all scenes in the requested scene folder.\nDialog.prompt({\n title: 'Pack all Scenes in a folder',\n content: '<label>Enter folder name (case sensitive): <input type=\"text\" name=\"folder\"><hr></label>',\n label: 'Pack scenes',\n callback: async (html) => {\n let folderName = html.find('input').val();\n if (!folderName) {\n return;\n }\n let process = async (f, instance) => {\n for (const scene of (f.contents ?? f.content)) {\n await instance.ClearPackedData(scene);\n await instance.PackScene(scene);\n }\n for (const child of (f.children || [])) {\n await process(child, instance);\n }\n }\n const folder = game.folders.find(f => f.name === folderName && f.type === 'Scene');\n if (folder) {\n ScenePacker.PromptForInstance().then(async instance => {\n await process(folder, instance);\n ui.notifications.warn('Make sure that you export your packed scenes to your compendium. You should also run \"Relink compendium entries\" one more time after exporting your scenes.', { permanent: true });\n })\n } else {\n console.error(`Could not find a Scene folder with the name \"${folderName}\"`);\n }\n },\n});","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.oYPUPtEzf8Dp90ZS"},"scene-packer":{"sourceId":"Macro.oYPUPtEzf8Dp90ZS"}},"ownership":{"default":0,"FYKEkGQDWeedzh8v":3},"_stats":{"systemId":"dnd5e","systemVersion":"1.6.1","coreVersion":"10.263","createdTime":null,"modifiedTime":1653105956978,"lastModifiedBy":"sH4kZUxETJcGJ0Zj"}}
{"_id":"YsJZfzxws5UeXYJC","name":"Bulk pack scenes","type":"script","author":"FYKEkGQDWeedzh8v","img":"icons/svg/barrel.svg","scope":"global","command":"// This macro will pack/repack all scenes in the requested scene folder.\nDialog.prompt({\n title: 'Pack all Scenes in a folder',\n content: '<label>Enter folder name (case sensitive): <input type=\"text\" name=\"folder\"><hr></label>',\n label: 'Pack scenes',\n callback: async (html) => {\n let folderName = html.find('input').val();\n if (!folderName) {\n return;\n }\n let process = async (f, instance) => {\n const contents = f.documents ?? f.contents ?? f.content;\n for (const scene of (contents)) {\n await instance.ClearPackedData(scene);\n await instance.PackScene(scene);\n }\n for (const child of (f.children || [])) {\n await process(child, instance);\n }\n }\n const folder = game.folders.find(f => f.name === folderName && f.type === 'Scene');\n if (folder) {\n ScenePacker.PromptForInstance().then(async instance => {\n await process(folder, instance);\n ui.notifications.warn('Make sure that you export your packed scenes to your compendium. You should also run \"Relink compendium entries\" one more time after exporting your scenes.', { permanent: true });\n })\n } else {\n console.error(`Could not find a Scene folder with the name \"${folderName}\"`);\n }\n },\n});","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.oYPUPtEzf8Dp90ZS"},"scene-packer":{"sourceId":"Macro.oYPUPtEzf8Dp90ZS"}},"ownership":{"default":0,"FYKEkGQDWeedzh8v":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.0.3","coreVersion":"10.288","createdTime":null,"modifiedTime":1665708678404,"lastModifiedBy":"RuFRN1eHFACTjcgR"}}
{"_id":"Zj82Pme9Bzjd6MPK","name":"Clean up #[CF_tempEntity] entries","type":"script","author":"XbLObTJNibRaLZgl","img":"icons/svg/acid.svg","scope":"global","command":"// Prompt to remove \"#[CF_tempEntity]\" items from the world,\n// in the case where they have been imported when the\n// Compendium Folders module is not active.\n(async () => {\n if (!game.user.isGM) {\n return;\n }\n\n let cfTempEntity = '#[CF_tempEntity]';\n let activeModules = (isNewerVersion(game.version ?? game.data.version, '10') ? game.modules : game.data.modules)\n .filter((m) => m.active && ((m.packs ?? m.data?.packs)?.size || m.packs?.length))\n .map((m) => m.id);\n let content = `<p>Remove #[CF_tempEntity] from the following location:</p>`;\n content += '<select id=\"module-name\">';\n content += `<option value=\"world\" selected>world</option>`;\n activeModules.forEach((m) => {\n content += `<option value=\"${m}\">${m}</option>`;\n });\n content += '</select>';\n content += '<p><hr></p>';\n new Dialog({\n title: 'Remove #[CF_tempEntity]',\n content: content,\n buttons: {\n process: {\n icon: '<i class=\"fas fa-check\"></i>',\n label: game.i18n.localize('Process'),\n callback: async (html) => {\n await process(html.find('#module-name')[0].value);\n },\n },\n cancel: {\n icon: '<i class=\"fas fa-times\"></i>',\n label: game.i18n.localize('Cancel'),\n },\n },\n }).render(true);\n\n async function process(moduleName) {\n let collections = [\n {name: 'scenes', collection: game.scenes},\n {name: 'actors', collection: game.actors},\n {name: 'items', collection: game.items},\n {name: 'journals', collection: game.journal},\n {name: 'macros', collection: game.macros},\n {name: 'playlists', collection: game.playlists},\n {name: 'roll tables', collection: game.tables},\n ];\n let packs = game.packs.filter(p => (p.metadata.packageName || p.metadata.package) === moduleName)\n for (const entity of collections) {\n const found = [];\n if (moduleName === 'world') {\n found.push(...entity.collection.filter(e => e.name === cfTempEntity));\n }\n for (const pack of packs) {\n const packType = pack.documentName || pack.entity;\n if (packType !== entity.collection.documentName) {\n continue;\n }\n pack.configure({locked: false});\n const docs = await pack.getDocuments();\n found.push(...docs.filter(e => e.name === cfTempEntity));\n }\n if (found.length) {\n for (const foundElement of found) {\n console.log(`Deleting ${foundElement.id} from ${entity.name}`);\n await foundElement.delete();\n }\n } else {\n console.log(`No ${entity.name} with the name \"${cfTempEntity}\" found.`);\n }\n }\n }\n})();","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.Vseli28UPwE5waan"},"scene-packer":{"sourceId":"Macro.mYvPx3E5TVzLprkb","hash":"dd9e25978da2a949c96605a1789e171694d2442f"}},"ownership":{"default":0,"XbLObTJNibRaLZgl":3},"_stats":{"systemId":"dnd5e","systemVersion":"1.6.1","coreVersion":"10.263","createdTime":null,"modifiedTime":1653106037269,"lastModifiedBy":"sH4kZUxETJcGJ0Zj"}}
{"name":"Show asset report","type":"script","author":"ajyvWN29UcpExc6d","img":"icons/svg/hazard.svg","scope":"global","command":"// This macro shows an asset report that details the assets\n// in this world and whether they have \"external\" dependencies.\n//\n// Use it to help determine whether your packaged module will\n// result in broken assets (images, sounds etc.).\n\nnew ScenePacker.AssetReport();","folder":null,"sort":0,"permission":{"default":0,"ajyvWN29UcpExc6d":3},"flags":{"core":{"sourceId":"Macro.CIKJ4iAmyMvhtptI"}},"_id":"mkNKay70v790Fu4h"}
{"_id":"qIQ9ehnHD47ekm1l","name":"Reset world Scene Packer prompts","type":"script","author":"Rt2brfVFebtCuVnc","img":"icons/svg/hanging-sign.svg","scope":"global","command":"// This macro will prompt you to select your module and then\n// will reset the settings values to allow retriggering of\n// the prompts when you first install a world.\n//\n// These prompts are the \"Yes import all\", \"Let me choose\" etc.\n\nlet content = '';\nlet instances = Object.keys(ScenePacker.instances);\nif (instances.length) {\n content = '<p>Select the module that you want to reset prompting for:</p>';\n content += '<select id=\"module-name\">';\n instances.forEach(m => {\n content += `<option value=\"${m}\">${m}</option>`;\n });\n content += '</select>';\n content += '<p>Refresh the world after resetting.</p>'\n} else {\n content = '<p>There are no modules registered with Scene Packer currently available.</p>';\n}\nlet d = new Dialog({\n title: 'Select instance',\n content: content,\n buttons: {\n relink: {\n icon: '<i class=\"fas fa-check\"></i>',\n label: 'Reset',\n callback: (html) => {\n let moduleName = html.find('#module-name')[0].value;\n if (!moduleName) {\n return;\n }\n game.settings.set(moduleName, 'imported', '0.0.0');\n game.settings.set(moduleName, 'prompted', '0.0.0');\n game.settings.set(moduleName, 'showWelcomePrompts', true);\n game.settings.set(moduleName, 'migrationSystemVersion', '0.0.0')\n if (canvas?.scene?.getFlag(moduleName, 'imported')) {\n canvas.scene.setFlag(moduleName, 'imported', '0.0.0')\n }\n },\n },\n cancel: {\n icon: '<i class=\"fas fa-times\"></i>',\n label: 'Cancel',\n },\n },\n});\nd.render(true);","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.8Ed2EtweXHL8UrPq"},"scene-packer":{"sourceId":"Macro.8Ed2EtweXHL8UrPq"}},"ownership":{"default":0,"Rt2brfVFebtCuVnc":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.0.2","coreVersion":"10.285","createdTime":null,"modifiedTime":1663143118043,"lastModifiedBy":"rfTqhTOpsOhdbu6t"}}
Expand Down
Loading

0 comments on commit ca637d3

Please sign in to comment.