Finally support "uploading" your own levels
This commit is contained in:
parent
dea7a7b754
commit
6f6f0fab48
@ -35,12 +35,13 @@
|
|||||||
<ul id="level-pack-list">
|
<ul id="level-pack-list">
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!--
|
|
||||||
<h2>Commercial and other levels</h2>
|
<h2>Commercial and other levels</h2>
|
||||||
<p>You can play the original levels, or any you've downloaded from the web!</p>
|
<p>You can play the original levels, or any you've downloaded from the web!</p>
|
||||||
-->
|
<!-- TODO explain how to find chips.dat or steam folder -->
|
||||||
|
<!-- TODO drag and drop? -->
|
||||||
|
<p><input id="splash-upload" type="file"></p>
|
||||||
|
|
||||||
<h2>Make your own</h2>
|
<h2>Make your own (WIP lol)</h2>
|
||||||
<p><button type="button" id="splash-create-level">Create a level</button></p>
|
<p><button type="button" id="splash-create-level">Create a level</button></p>
|
||||||
</main>
|
</main>
|
||||||
<main id="player" hidden>
|
<main id="player" hidden>
|
||||||
|
|||||||
56
js/main.js
56
js/main.js
@ -1462,7 +1462,19 @@ class Editor extends PrimaryView {
|
|||||||
// Tile palette
|
// Tile palette
|
||||||
let palette_el = this.root.querySelector('.palette');
|
let palette_el = this.root.querySelector('.palette');
|
||||||
this.palette = {}; // name => element
|
this.palette = {}; // name => element
|
||||||
for (let name of ['floor', 'wall']) {
|
for (let name of [
|
||||||
|
// Terrain
|
||||||
|
'floor', 'wall', 'hint', 'socket', 'exit',
|
||||||
|
'popwall',
|
||||||
|
'fake_floor', 'fake_wall',
|
||||||
|
'water', 'fire', 'ice', 'force_floor_all',
|
||||||
|
// TODO ice curves
|
||||||
|
// Items
|
||||||
|
'chip', // 'chip_extra', -- XXX doesn't exist in TW tileset!
|
||||||
|
'key_blue', 'key_red', 'key_yellow', 'key_green',
|
||||||
|
// Creatures
|
||||||
|
])
|
||||||
|
{
|
||||||
let entry = mk('canvas.palette-entry', {
|
let entry = mk('canvas.palette-entry', {
|
||||||
width: this.conductor.tileset.size_x,
|
width: this.conductor.tileset.size_x,
|
||||||
height: this.conductor.tileset.size_y,
|
height: this.conductor.tileset.size_y,
|
||||||
@ -1553,6 +1565,19 @@ class Splash extends PrimaryView {
|
|||||||
pack_list.append(li);
|
pack_list.append(li);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind to file upload control
|
||||||
|
let upload_el = this.root.querySelector('#splash-upload');
|
||||||
|
// Clear it out in case of refresh
|
||||||
|
upload_el.value = '';
|
||||||
|
upload_el.addEventListener('change', async ev => {
|
||||||
|
let file = ev.target.files[0];
|
||||||
|
let buf = await file.arrayBuffer();
|
||||||
|
this.load_file(buf);
|
||||||
|
// TODO get title out of C2G when it's supported
|
||||||
|
this.conductor.level_pack_name_el.textContent = file.name;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bind to "create level" button
|
||||||
this.root.querySelector('#splash-create-level').addEventListener('click', ev => {
|
this.root.querySelector('#splash-create-level').addEventListener('click', ev => {
|
||||||
let stored_level = new format_util.StoredLevel;
|
let stored_level = new format_util.StoredLevel;
|
||||||
stored_level.size_x = 32;
|
stored_level.size_x = 32;
|
||||||
@ -1578,18 +1603,27 @@ class Splash extends PrimaryView {
|
|||||||
// TODO cancel a download if we start another one?
|
// TODO cancel a download if we start another one?
|
||||||
let data = await fetch(path);
|
let data = await fetch(path);
|
||||||
let stored_game;
|
let stored_game;
|
||||||
// TODO check magic numbers, not extensions
|
this.load_file(buf);
|
||||||
// TODO also support tile world's DAC when reading from local??
|
|
||||||
// TODO ah, there's more metadata in CCX, crapola
|
|
||||||
if (path.match(/\.(?:dat|ccl)$/i)) {
|
|
||||||
stored_game = dat.parse_game(data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stored_game = new format_util.StoredGame;
|
|
||||||
stored_game.levels.push(c2m.parse_level(data));
|
|
||||||
}
|
|
||||||
// TODO get title out of C2G when it's supported
|
// TODO get title out of C2G when it's supported
|
||||||
this.conductor.level_pack_name_el.textContent = title || path;
|
this.conductor.level_pack_name_el.textContent = title || path;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_file(buf) {
|
||||||
|
// TODO also support tile world's DAC when reading from local??
|
||||||
|
// TODO ah, there's more metadata in CCX, crapola
|
||||||
|
let magic = String.fromCharCode.apply(null, new Uint8Array(buf.slice(0, 4)));
|
||||||
|
let stored_game;
|
||||||
|
console.log(magic);
|
||||||
|
if (magic === 'CC2M' || magic === 'CCS ') {
|
||||||
|
stored_game = new format_util.StoredGame;
|
||||||
|
stored_game.levels.push(c2m.parse_level(buf));
|
||||||
|
}
|
||||||
|
else if (magic === '\xac\x2a\x02\x00' || magic == '\xac\x2a\x02\x01') {
|
||||||
|
stored_game = dat.parse_game(buf);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("Unrecognized file format");
|
||||||
|
}
|
||||||
this.conductor.load_game(stored_game);
|
this.conductor.load_game(stored_game);
|
||||||
this.conductor.switch_to_player();
|
this.conductor.switch_to_player();
|
||||||
}
|
}
|
||||||
|
|||||||
17
style.css
17
style.css
@ -3,7 +3,7 @@ html {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
min-height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -180,11 +180,19 @@ body[data-mode=splash] #header-level {
|
|||||||
/* Splash (intro part) */
|
/* Splash (intro part) */
|
||||||
|
|
||||||
#splash {
|
#splash {
|
||||||
flex: 0;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#splash h2 {
|
||||||
|
border-bottom: 1px solid #404040;
|
||||||
|
color: #909090;
|
||||||
|
text-shadow: 0 1px #0004;
|
||||||
|
}
|
||||||
|
#splash * + h2 {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
#level-pack-list {
|
#level-pack-list {
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
@ -428,14 +436,15 @@ main.--has-demo .demo-controls {
|
|||||||
/* Editor */
|
/* Editor */
|
||||||
|
|
||||||
#editor {
|
#editor {
|
||||||
|
flex: 1 1 auto;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid:
|
grid:
|
||||||
"level palette"
|
"level palette"
|
||||||
;
|
;
|
||||||
|
|
||||||
max-width: 95%;
|
min-height: 0;
|
||||||
max-height: 95%;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#editor .level {
|
#editor .level {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user