Add support for downloading an entire pack as a zipped C2G
This commit is contained in:
parent
83793603d3
commit
044c08c3fc
@ -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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user