AnthorNet / SC-InteractiveMap

Satisfactory-Calculator Interactive Map
154 stars 34 forks source link

[Feature proposal] Save game screenshot #219

Closed DeviateFish closed 1 month ago

DeviateFish commented 2 years ago

Let me preface this by saying that I really enjoy the work you've done here, and think you've built a wonderful tool for the Satisfactory community. I use the interactive map almost every time I play, to figure out where to build, to sanity check the inputs/outputs of factories. I haven't yet dabbled in any of the more advanced features, like editing save files, but it looks like quite the suite of features.

Using this tool has given me an idea. I have a proposal for a new feature, one that I'd like to implement if I get your approval.

I would like to be able to provide the tool (or a new tool) with a whole list of save games, and have it generate a timelapse of the whole map across all those saves. I think this would be a really cool way to look back on the history of a particular Satisfactory playthrough, to see how factories and setups evolve over time. The quality of the timelapse would obvious depend heavily on the saves themselves, but I think it could produce some really cool results, especially for people who regularly produce Satisfactory content.

This is a huge feature. So far, from browsing through the codebase, looking at the save file parsing, and looking at the supporting libraries, some big concerns arise:

Given all the above, this seems like a pretty big project, but I do think it can be broken down into a set of smaller projects that each are more tractable:

Some other questions/concerns:

Thoughts? Questions? I'd really like to make this a reality. I also know that this is your project, and I don't want to intrude or impose in any way. I think what you've built is pretty incredible, which is why I would love to use it as a starting point for this particular project. I could in theory build all the requisite pieces from scratch, drawing on your work for inspiration, but I think in many ways that would be a disservice to the work you've done here. You've also made it pretty clear that this is your code, and that it's not to be used for any external purposes. I would like to respect that.

AnthorNet commented 2 years ago

Lot to think of :D If you have Discord it would be easier to discuss all that. Not against PR, but some times they take more time for me to handle than keeping things in order.

DeviateFish commented 2 years ago

Yeah, I can definitely pop into Discord in the near future. It'll probably be in a couple days or so, since I'm currently away from home. What's your timezone, and when do you think you'd be most available to chat?

I did a little more digging and it doesn't seem like there's really a good pure-JS option for creating a timelapse from individual frames, especially if you want to do something fancy like have variable input framerates. I think variable framerates is probably a must, since I think it would make the most sense to have the playback be x seconds per hour of playtime or something like that. Since there's no good guarantee that each save in a set of files will be created at a regular interval (like every hour or something), it would probably be best to accommodate for uneven intervals from the start. Most examples of creating videos from frames in js seem to just delegate to ffmpeg to get the job done, which is... probably the right call, honestly. This does limit them to being server-side only, which introduces its own set of complications.

The "good news" is that this means any changes here could be limited to those needed to support the generation of a single static image per save game (and maybe some JSON metadata for timing purposes?), and whatever scaffolding is required to make that friendly to automation. I've done automated frame capture in the browser before (aside: I see we both like FileSaver.js 😄) with decent results (see below), but it's kind of janky, and would still require some changes to where the lines of abstraction currently lie.

Given a list of images generated from a list of save games and some information about how much playtime had elapsed for each snapshot, the process of creating the timelapse can be entirely independent and happen in any environment.

DeviateFish commented 2 years ago

So after sleeping on this, I realized that the most basic MVP would essentially just be the ability to export a screenshot of the map after loading a save file. Technically, everything else that needs to be done to create the timelapse can be done outside the tool, even if it requires a bunch of manual work. Some of it probably has to happen outside the tool, especially if things like ffmpeg are requried.

My preference would still be to automate it, or be able to use parts of your codebase as a library to do so, but from the perspective of introducing a minimal set of changes to the thing you've built, I think just exporting a screenshot would be sufficient.

It looks like several options exist as Leaflet plugins to do this, so it might be pretty straightforward. Some of them look like they have some caveats (some kinds of markers aren't supported since they're html and not drawn directly in the canvas element, etc), but for at least my purposes, that's an acceptable limitation.

If none of those plugins work, I think it would be possible to do manually by:

  1. Getting a reference the Leaflet's canvas
  2. Using something like this code to export the canvas as a PNG and save it

Obviously being able to automate the above and manipulate the canvas itself (setting zoom and canvas size, for example) for multiple save games would be more ideal, but I'd definitely be able to accomplish what I want with just the above and some additional scripts (either Tampermonkey or cli) to extract the header information from each save to get the playtime information.

I'll edit the title of the issue to better reflect this, and we can still chat on Discord about this tomorrow, but I wanted to get this down in writing so I don't forget 😄

SignpostMarv commented 2 years ago

@DeviateFish

Is this possible to even do in the browser?

past experience says yes

"list of frames for a timelapse" (or video/gif)

see #35

Most examples of creating videos from frames in js seem to just delegate to ffmpeg to get the job done

see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/captureStream and https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder

DeviateFish commented 2 years ago

see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/captureStream and https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder

Oh that's pretty nifty. Also, thanks for linking the old issue, it seems I'm definitely not the only one who has had this idea.

I'm still not entirely sure the browser is indeed the right place to do this, though. My biggest concern is the memory limitations, since it looks like the save files can get pretty big, and that's in a compressed format. I also didn't really think of doing timelapses for specific areas of the map (as opposed to just the entire map over time), so I can see that being a slightly different use-case. One is just a superset of the other, so it definitely could be built to do so. Being able to easily control the viewpoint is certainly a point in favor of doing it natively in the browser, however.

I'll take a peek at the linked APIs and see if I can cobble something together.

Fair warning though: I have no intention of doing anything here that could compete with anything @AnthorNet has built, so whether or not any of the stuff I end up building makes it into main is entirely up to them. I'll certainly be sharing my results with them, but I won't be releasing anything publicly without express consent 😄

SignpostMarv commented 2 years ago

@DeviateFish it may be more practical to knock up a standalone CLI tool that uses https://github.com/puppeteer/puppeteer

DeviateFish commented 2 years ago

@DeviateFish it may be more practical to knock up a standalone CLI tool that uses https://github.com/puppeteer/puppeteer

I had considered that, but I really hate puppeteer. It might be the least worst option out of all the browser orchestration tools, but it's still bad. Using a headless browser is probably going to be my last resort, rather than first 😄

AnthorNet commented 2 years ago

https://webrtc.github.io/samples/src/content/capture/canvas-record/

SignpostMarv commented 2 years ago

@AnthorNet 🤔 I just had a terrible idea