Add... error handling... sort of... for levels at least

This commit is contained in:
Eevee (Evelyn Woods) 2020-10-21 21:07:50 -06:00
parent edbe32c148
commit 8073604271
3 changed files with 54 additions and 12 deletions

View File

@ -860,7 +860,7 @@ export function parse_level(buf, number = 1) {
if (! spec) if (! spec)
throw new util.LLError(`Invalid tile type 0x${tile_byte.toString(16)}`); throw new util.LLError(`Invalid tile type 0x${tile_byte.toString(16)}`);
if (spec.error) if (spec.error)
throw spec.error; throw new util.LLError(spec.error);
return spec; return spec;
} }

View File

@ -3,7 +3,7 @@
import { DIRECTIONS, TICS_PER_SECOND } from './defs.js'; import { DIRECTIONS, TICS_PER_SECOND } from './defs.js';
import * as c2g from './format-c2g.js'; import * as c2g from './format-c2g.js';
import * as dat from './format-dat.js'; import * as dat from './format-dat.js';
import * as format_util from './format-base.js'; import * as format_base from './format-base.js';
import { Level } from './game.js'; import { Level } from './game.js';
import { PrimaryView, Overlay, DialogOverlay, ConfirmOverlay } from './main-base.js'; import { PrimaryView, Overlay, DialogOverlay, ConfirmOverlay } from './main-base.js';
import { Editor } from './main-editor.js'; import { Editor } from './main-editor.js';
@ -1312,18 +1312,18 @@ class Splash extends PrimaryView {
// Bind to "create level" button // 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_base.StoredLevel;
stored_level.size_x = 32; stored_level.size_x = 32;
stored_level.size_y = 32; stored_level.size_y = 32;
for (let i = 0; i < 1024; i++) { for (let i = 0; i < 1024; i++) {
let cell = new format_util.StoredCell; let cell = new format_base.StoredCell;
cell.push({type: TILE_TYPES['floor']}); cell.push({type: TILE_TYPES['floor']});
stored_level.linear_cells.push(cell); stored_level.linear_cells.push(cell);
} }
stored_level.linear_cells[0].push({type: TILE_TYPES['player']}); stored_level.linear_cells[0].push({type: TILE_TYPES['player']});
// FIXME definitely gonna need a name here chief // FIXME definitely gonna need a name here chief
let stored_game = new format_util.StoredGame(null); let stored_game = new format_base.StoredGame(null);
stored_game.level_metadata.push({ stored_game.level_metadata.push({
stored_level: stored_level, stored_level: stored_level,
}); });
@ -1363,6 +1363,30 @@ class Splash extends PrimaryView {
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
// Central controller, thingy // Central controller, thingy
// Report an error when a level fails to load
class LevelErrorOverlay extends DialogOverlay {
constructor(conductor, error) {
super(conductor);
this.set_title("bummer");
this.main.append(
mk('p', "Whoopsadoodle! I seem to be having some trouble loading this level. I got this error, which may or may not be useful:"),
mk('pre.error', error.toString()),
mk('p',
"It's probably entirely my fault, and I'm very sorry. ",
"Unless you're doing something weird and it's actually your fault, I guess. ",
"This is just a prerecorded message, so it's hard for me to tell! ",
"But if it's my fault and you're feeling up to it, you can let me know by ",
mk('a', {href: 'https://github.com/eevee/lexys-labyrinth/issues'}, "filing an issue on GitHub"),
" or finding me on Discord or Twitter or whatever.",
),
mk('p', "In the more immediate future, you can see if any other levels work by jumping around manually with the 'level select' button. Unless this was the first level of a set, in which case you're completely out of luck."),
);
this.add_button("welp, you get what you pay for", ev => {
this.close();
});
}
}
// About dialog // About dialog
const ABOUT_HTML = ` const ABOUT_HTML = `
<p>Welcome to Lexy's Labyrinth, an exciting old-school tile-based puzzle adventure that is compatible with — but legally distinct from! — <a href="https://store.steampowered.com/app/346850/Chips_Challenge_1/">Chip's Challenge</a> and its long-awaited sequel <a href="https://store.steampowered.com/app/348300/Chips_Challenge_2/">Chip's Challenge 2</a>.</p> <p>Welcome to Lexy's Labyrinth, an exciting old-school tile-based puzzle adventure that is compatible with — but legally distinct from! — <a href="https://store.steampowered.com/app/346850/Chips_Challenge_1/">Chip's Challenge</a> and its long-awaited sequel <a href="https://store.steampowered.com/app/348300/Chips_Challenge_2/">Chip's Challenge 2</a>.</p>
@ -1625,8 +1649,9 @@ class LevelBrowserOverlay extends DialogOverlay {
return; return;
let index = parseInt(tr.getAttribute('data-index'), 10); let index = parseInt(tr.getAttribute('data-index'), 10);
this.conductor.change_level(index); if (this.conductor.change_level(index)) {
this.close(); this.close();
}
}); });
this.add_button("nevermind", ev => { this.add_button("nevermind", ev => {
@ -1767,13 +1792,20 @@ class Conductor {
this.player.load_game(stored_game); this.player.load_game(stored_game);
this.editor.load_game(stored_game); this.editor.load_game(stored_game);
this.change_level(0); return this.change_level(0);
} }
change_level(level_index) { change_level(level_index) {
this.level_index = level_index;
// FIXME handle errors here // FIXME handle errors here
try {
this.stored_level = this.stored_game.load_level(level_index); this.stored_level = this.stored_game.load_level(level_index);
}
catch (e) {
new LevelErrorOverlay(this, e).open();
return false;
}
this.level_index = level_index;
// FIXME do better // FIXME do better
this.level_name_el.textContent = `Level ${level_index + 1}${this.stored_level.title}`; this.level_name_el.textContent = `Level ${level_index + 1}${this.stored_level.title}`;
@ -1783,6 +1815,7 @@ class Conductor {
this.player.load_level(this.stored_level); this.player.load_level(this.stored_level);
this.editor.load_level(this.stored_level); this.editor.load_level(this.stored_level);
return true;
} }
update_nav_buttons() { update_nav_buttons() {
@ -1871,9 +1904,10 @@ class Conductor {
else { else {
throw new Error("Unrecognized file format"); throw new Error("Unrecognized file format");
} }
this.load_game(stored_game, identifier); if (this.load_game(stored_game, identifier)) {
this.switch_to_player(); this.switch_to_player();
} }
}
} }

View File

@ -82,6 +82,9 @@ p:first-child {
p:last-child { p:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
pre {
white-space: pre-wrap;
}
code { code {
color: #c0c0e0; color: #c0c0e0;
} }
@ -157,6 +160,11 @@ a:active {
overflow: auto; overflow: auto;
padding: 1em; padding: 1em;
} }
.dialog pre.error {
color: #400000;
background: #f0d0d0;
padding: 0.5em 1em;
}
/* Individual overlays */ /* Individual overlays */
table.level-browser { table.level-browser {