#Path replacement
1 messages ยท Page 1 of 1 (latest)
i will do so, yes.
i'm just downloading the s3 assets atm
that's just the worlds folder in the Data folder, right? or should I back up the whole Data folder?
guess it won't hurt.
to do the latter
just world would do, but a whole backup every so often wont go amis
gimme a shout when you've got the backup
ok. gonna be a few more minutes. I just did the whole folder.
thanks!
probably about 20 more minutes
Hey, i just fucked up the fstab on my pi. In emergency mode. This will take a while.
Sorry for the delay
np
Ugh. Finally got back my install. Had to rebuild the whole environment.
Nothing like wiping a pi and rebuilding from scratch.
Got the backup and reinstall is good.
NOTE this is made for v8 and has not been updated for v9
so... ```js
let actorUpdates = [];
for (let actor of game.actors) {
let files;
let skip = false;
let newimg = actor.data.token.img.replace("X", "Y")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == true) continue
if (CheckFiles(files, newimg)) {
actorUpdates.push({ _id: actor.id, "token.img": newimg });
console.log("Actor Token", actor, "updated");
}
}
if (actorUpdates.length != 0) await Actor.update(actorUpdates);
//Replace Avatars
let actorUpdatesAvatar = [];
for (let actor of game.actors) {
let files;
let skip = false;
let newimg = actor.data.img.replace("X", "Y")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == true) continue
if (CheckFiles(files, newimg)) {
actorUpdatesAvatar.push({ _id: actor.id, "img": newimg });
console.log("Actor Avatar", actor, "updated");
}
}
if (actorUpdatesAvatar.length != 0) await Actor.update(actorUpdatesAvatar);
function CheckFiles(files, webPath) {
for (let file of files.files) {
if (file === webPath) return true;
}
}
this will update the actor images and prototype token images for all Actor Directory actors if it can find a replacement file given the name-swap
oh, nice. thank you so much. Is there a way to just change all the s3 paths to a local path? so maps, tokens, etc., all get updated?
I was just doing 1 by one, just incase something went wrong
this should do all tokens```js
for (let scene of game.scenes) {
let tokenUpdates = [];
for (let token of scene.data.tokens) {
let files;
let skip = false;
let newimg = token.data.img.replace("X", "Y")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == true) continue
if (CheckFiles(files, newimg)) {
tokenUpdates.push({ _id: token._id, "img": newimg });
console.log("Token", token, "updated");
}
}
if (tokenUpdates.length != 0) await scene.updateEmbeddedEntity("Token", tokenUpdates);
}
function CheckFiles(files, webPath) {
for (let file of files.files) {
if (file === webPath) return true;
}
}
this for tiles/backgrounds```js
let tileupdates = 0;
let backgoundupdates = 0;
for (let scene of game.scenes) {
let updates = [];
for (let tile of scene.data.tiles) {
let files;
let skip = false;
let newimg = tile.img.replace("X", "Y")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == true) continue
if (CheckFiles(files, newimg)) {
updates.push({ _id: tile._id, img: newimg });
console.log("Tile", tile, "updated");
}
}
console.log("Tiles in Scene ", scene, "updated")
await scene.updateEmbeddedEntity("Tile", updates);
tileupdates += updates.length
//Replace Backgrounds
let skip = false;
let files;
let newimg = scene.data.img?.replace("X", "Y")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == false) {
if (CheckFiles(files, newimg)) {
await scene.update({ img: newimg });
console.log("Background for Scene", scene, "updated");
backgoundupdates++;
}
}
}
function CheckFiles(files, webPath) {
for (let file of files.files) {
if (file === webPath) return true;
}
}
oh wait woops, 1 sec fixed now
thanks so much. this is very helpful. I'll try playing arond with it.
@rapid cargo try this
Aha. This looks great. Thanks.
Thank you very much! If I'm purely a macro-user that takes macros from you smarter people and uses them will I get this? I don't write or understand macros but I assume the above is pretty straight forward like most of the great work ya'll do?
so in the let newImage = ....replace() you need to fill in your 2 different paths
in your case I think your paths would be somethiing like imageA and then characters/imageA right ?
Yes because currently they're all under the plain Data folder (before I knew how i'd organize FVTT)
I may make
Player Characters, NPCs, Hostiles
Or something
do you recommend just one folder maybe?
I personaly organize by creature type for NPC.s then PCs in one folder
I was thinking the same but that would mean doing the macro multiple times? Like what would the steps be?
if you wanted to mass move a load of images yes
Got it, thank you so much. Iโll give this a shot as soon as I can!
@neat knoll
Thanks, I'll read over this thread to see if I can understand / apply it. Cheers.
And that macro code up there doesn't worry about case sensitivity in file names?
it has to match exactly
๐
@vast tangle @wicked crow might be interested in some of this
Thanks for the ping. Looks really useful
@low kettle
Thanks so much! Looks comprehensive. Will give it a go, once my neighborhood regains power. ๐คช๐
@pastel mango ๐
oh
just a thought, maybe add this if (!actor.data.token.img.includes("old path")) continue;
I am testing the macros in my loval v9 environment, it does not like scene.updateEmbeddedEntity("Token", tokenUpdates);, needs scene.updateEmbeddedDocuments("Token", tokenUpdates); and tokenUpdates.push({ _id: token._id, "img": newimg }); needs to be updated to tokenUpdates.push({ _id: token.id, "img": newimg });
and the FilePicker.browse was causing it to not catch all images for some reason
This was made in v8 and not tested for v9
just noting it for future. The script works in v8 with those changes as well
@glossy jackal this is a rough jist
So, mostly have no idea what I'm doing. I think I can update my paths for file replacement just fine (hopefully), but not sure what to change for the above to work for Items in a compendium rather than actors or tiles
Actually, looking closer now, a lot of the icons have entirely different file names. Not sure how feasible this would be
@compact pelican try this
I'm very much a newbie with this sort of thing. For switching extension name for my tokens, notes, maps, etc. from png and jpeg to webp, do I need to make any edits to the code above or is it essentially finding the most similar files to replace to?
no no, you will have to make edits
actually, there should be an easier macro for you if you're just replacing png=> webp
Yup, all I need to do is replace png and jpeg to webp because I used a converter to replace all my images in the data file using the same location.
i now cant find the macro I wrote for this ๐
oh no wait, this is it im just dumb
all you need to do is change any replace(X, Y) with replace("png", "webp") and that should work
but make sure you make a backup first
Replace to that within this?
thats for actors, but yes. Copy/paste that macro into a foundry script macro, make those changes and hit Execute (after making a backup)
Should I have made any changes besides were replace("X", "Y") was? When I run the macro with those changes, I'm not seeing anything updating. Here's what I put looks like:
let actorUpdates = [];
for (let actor of game.actors) {
let files;
let skip = false;
let newimg = actor.data.token.img.replace("png", "webp")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == true) continue
if (CheckFiles(files, newimg)) {
actorUpdates.push({ _id: actor.id, "token.img": newimg });
console.log("Actor Token", actor, "updated");
}
}
if (actorUpdates.length != 0) await Actor.update(actorUpdates);
//Replace Avatars
let actorUpdatesAvatar = [];
for (let actor of game.actors) {
let files;
let skip = false;
let newimg = actor.data.img.replace("png", "webp")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == true) continue
if (CheckFiles(files, newimg)) {
actorUpdatesAvatar.push({ _id: actor.id, "img": newimg });
console.log("Actor Avatar", actor, "updated");
}
}
if (actorUpdatesAvatar.length != 0) await Actor.update(actorUpdatesAvatar);
function CheckFiles(files, webPath) {
for (let file of files.files) {
if (file === webPath) return true;
}
}
With this error:
After making further adjustments to the code, I am receiving this error:
foundry.js:10090 Uncaught (in promise) Error: You must provide an _id for every object in the update data Array.
[No packages detected]
at ClientDatabaseBackend._preUpdateDocumentArray (foundry.js:10090)
at ClientDatabaseBackend._updateEmbeddedDocuments (foundry.js:10057)
at ClientDatabaseBackend.update (backend.mjs:153)
at async Function.updateDocuments (document.mjs:373)
@plucky glade ๐
thank you, didnt see this in Pins and didnt check Threads @abstract lance
Hello ! Is there a way to use this macro in V9 ? I uptaded all my PNG to Webp, but still searching if there is a way to win time for compendium token link. :'D
I'm after how to use this for a compendium as well in v9. Its probably something like changing the game.actors to game.packs("your-compendium-name") where "your-compendium-name" is what you've named your actor compendium, but NO idea if that is even remotely close and there's probably other changes that need.
Nope, I tried doing this but got an error message:
TypeError: game.packs is not a function or its return value is not iterable
so I think there's something on the
let newimg = actor.data.token.img.replace("png", "webp")``` that is wrong as well.
Is there any way to change 2 things at the same time? Like image path AND from jpeg to webp?
Just change the parameters of the replace function
replace("data/image/a.png", "data/tokens/a.webp")
That would only work on 1 actor at a time right? Any way to get it to loop through all using variables? And I've not been able to get the image swap to work on a Compendium. Is game.packs.getName correct or is there something else?
Game.packs.get(key)
Thanks. Using that in the following macro gives me this error:
Error: The key gIoDL4auFDFPTknd does not exist in the Actors Collection
The macro is as follows:
let actorUpdates = [];
for (let actor of game.packs.get("SharedData.DDBMonsters")) {
let files;
let skip = false;
let newimg = actor.data.token.img.replace("ddb-images/other/", "assets/tokens/monsters/")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == true) continue
if (CheckFiles(files, newimg)) {
actorUpdates.push({ _id: actor.id, "token.img": newimg });
console.log("Actor Token", actor, "updated");
}
}
if (actorUpdates.length != 0) await Actor.updateDocuments(actorUpdates);
//Replace Avatars
let actorUpdatesAvatar = [];
for (let actor of game.packs.get("SharedData.DDBMonsters")) {
let files;
let skip = false;
let newimg = actor.data.img.replace("ddb-images/other/", "assets/tokens/monsters/")
try {
files = await FilePicker.browse('user', newimg)
}
catch {
skip = true
}
if (skip == true) continue
if (CheckFiles(files, newimg)) {
actorUpdatesAvatar.push({ _id: actor.id, "img": newimg });
console.log("Actor Avatar", actor, "updated");
}
}
if (actorUpdatesAvatar.length != 0) await Actor.updateDocuments(actorUpdatesAvatar);
function CheckFiles(files, webPath) {
for (let file of files.files) {
if (file === webPath) return true;
}
}```
So I'm guessing there are a couple of issues, probably around the
```js
let newimg = actor.data.token.img.replace("ddb-images/other/", "assets/tokens/monsters/")
and the
actorUpdatesAvatar.push({ _id: actor.id, "img": newimg });
``` line
Rather than trying to update both path and jpeg to webp at the same time, I've just created 2 macros and copied the original source images for avatar and token to the target to try and get the new location set, then I'll set the jpeg to webp macro to work after. But, the first location change isn't running due to the initial error I posted above.
The database key is correct
And it appears that this error message relates to the Aarakocra entry in the SharedData.DDBMonsters compendium
I would guess there's something broken with that actor then
Sorry for the late response. Its happening with different actors at different times. I've tried running the migrate compendium macro from the DDB Importer server to see if that helps / triggers the actor reference in the macro (although I was pretty sure I'd done that previously). I'll keep trying, thanks for your help.
And what's strange is that in the console, I can see that the actor in question (in this case a freshly munched 'Acolyte' is processed as the first munched monster and is marked as 'updated' but is then referenced in the following error message:
Strange, and I genuinely have no idea what the issue is.
Its trying to update in the wrong place