Add support for downloading an entire pack as a zipped C2G

This commit is contained in:
Eevee (Evelyn Woods) 2021-01-01 14:44:48 -07:00
parent 83793603d3
commit 044c08c3fc

View File

@ -1,3 +1,5 @@
import * as fflate from 'https://unpkg.com/fflate/esm/index.mjs';
import { DIRECTIONS, TICS_PER_SECOND } from './defs.js'; import { DIRECTIONS, TICS_PER_SECOND } from './defs.js';
import { TILES_WITH_PROPS } from './editor-tile-overlays.js'; import { TILES_WITH_PROPS } from './editor-tile-overlays.js';
import * as format_base from './format-base.js'; import * as format_base from './format-base.js';
@ -2549,7 +2551,7 @@ export class Editor extends PrimaryView {
if (this.stored_level) { if (this.stored_level) {
this.save_button.disabled = ! this.conductor.stored_game.editor_metadata; this.save_button.disabled = ! this.conductor.stored_game.editor_metadata;
} }
_make_button("Download", ev => { _make_button("Download level as C2M", ev => {
// TODO also allow download as CCL // TODO also allow download as CCL
// TODO support getting warnings + errors out of synthesis // TODO support getting warnings + errors out of synthesis
let buf = c2g.synthesize_level(this.stored_level); let buf = c2g.synthesize_level(this.stored_level);
@ -2568,6 +2570,66 @@ export class Editor extends PrimaryView {
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
}, 60 * 1000); }, 60 * 1000);
}); });
_make_button("Download pack", ev => {
let stored_pack = this.conductor.stored_game;
// This is pretty heckin' best-effort for now; TODO move into format-c2g?
let lines = [];
let safe_title = (stored_pack.title || "untitled").replace(/[""]/g, "'").replace(/[\x00-\x1f]+/g, "_");
lines.push(`game "${safe_title}"`);
let files = {};
let count = stored_pack.level_metadata.length;
let levelnumlen = String(count).length;
for (let [i, meta] of stored_pack.level_metadata.entries()) {
let c2m;
if (i === this.conductor.level_index) {
// Use the current state of the current level even if it's not been saved
c2m = new Uint8Array(c2g.synthesize_level(this.stored_level));
}
else if (meta.key) {
// This is already in localStorage as a c2m
c2m = fflate.strToU8(localStorage.getItem(meta.key), true);
}
else {
let stored_level = stored_pack.load_level(i);
c2m = new Uint8Array(c2g.synthesize_level(stored_level));
}
let safe_title = meta.title.replace(/[\x00-\x1f<>:""\/\\|?*]+/g, '_');
let dirchunk = i - i % 50;
let dirname = (
String(dirchunk + 1).padStart(levelnumlen, '0') + '-' +
String(Math.min(count, dirchunk + 50)).padStart(levelnumlen, '0'));
let filename = `${dirname}/${i + 1} - ${safe_title}.c2m`;
files[filename] = c2m;
lines.push(`map "${filename}"`);
}
// TODO utf8 encode this
safe_title = safe_title.replace(/[\x00-\x1f<>:""\/\\|?*]+/g, '_');
lines.push("");
files[safe_title + '.c2g'] = fflate.strToU8(lines.join("\n"));
let u8array = fflate.zipSync(files);
// TODO also allow download as CCL
// TODO support getting warnings + errors out of synthesis
let blob = new Blob([u8array]);
let url = URL.createObjectURL(blob);
// To download a file, um, make an <a> and click it. Not kidding
let a = mk('a', {
href: url,
download: (stored_pack.title || 'untitled') + '.zip',
});
document.body.append(a);
a.click();
// Absolutely no idea when I'm allowed to revoke this, but surely a minute is safe
window.setTimeout(() => {
a.remove();
URL.revokeObjectURL(url);
}, 60 * 1000);
});
_make_button("Share", ev => { _make_button("Share", ev => {
let data = util.b64encode(c2g.synthesize_level(this.stored_level)); let data = util.b64encode(c2g.synthesize_level(this.stored_level));
let url = new URL(location); let url = new URL(location);