diff --git a/html/js/network/smirkAuth.js b/html/js/network/smirkAuth.js
index 5e6de09..d9dbde6 100644
--- a/html/js/network/smirkAuth.js
+++ b/html/js/network/smirkAuth.js
@@ -170,7 +170,9 @@ const SmirkAuth = {
try {
keys = await window.smirk.connect();
} catch (smirkError) {
- throw new Error('Failed to connect to Smirk wallet: ' + (smirkError.message || 'Unknown error'));
+ const e = new Error('Failed to connect to Smirk wallet: ' + (smirkError.message || 'Unknown error'));
+ e.code = smirkError && smirkError.code; // preserve SmirkRpcError code ('LOCKED', 'USER_REJECTED', …)
+ throw e;
}
if (!keys || !keys.wow) {
@@ -182,7 +184,9 @@ const SmirkAuth = {
try {
signResult = await window.smirk.signMessage(challenge);
} catch (signError) {
- throw new Error('Failed to sign challenge: ' + (signError.message || 'Unknown error'));
+ const e = new Error('Failed to sign challenge: ' + (signError.message || 'Unknown error'));
+ e.code = signError && signError.code; // preserve 'LOCKED' etc.
+ throw e;
}
// Find WOW signature
@@ -317,11 +321,20 @@ const SmirkAuth = {
} catch (err) {
console.error('Smirk login failed:', err);
- this._updateButton(btn, 'error');
+ this._updateButton(btn, 'error'); // button label becomes "Retry Smirk Connect"
- // Show error message
- const errorMsg = 'Smirk login failed: ' + err.message;
- $('#messages').append($('
').text(errorMsg));
+ // A locked wallet is an action, not a red error. Current Smirk builds auto-open the
+ // unlock popup on connect()/signNostrEvent(); older builds throw LOCKED — so guide the
+ // user to unlock and retry (the Retry button re-invokes connect(), which pops the
+ // unlock screen on the updated build).
+ const locked = (err && err.code === 'LOCKED') || /is locked/i.test((err && err.message) || '');
+ if (locked) {
+ $('#messages').append($('').text(
+ '🔒 Your Smirk wallet is locked. Open the Smirk extension, unlock it, then click "Retry Smirk Connect".'
+ ));
+ } else {
+ $('#messages').append($('').text('Smirk login failed: ' + err.message));
+ }
throw err;
}
diff --git a/html/js/render/assetPacks.js b/html/js/render/assetPacks.js
index d4bf965..8fc4ce3 100644
--- a/html/js/render/assetPacks.js
+++ b/html/js/render/assetPacks.js
@@ -112,16 +112,15 @@
tileset: { url: 'assets/kenney/roguelikeSheet.png', tile: 16, spacing: 1 },
// Default tile picks from the sheet metadata ( roguelikeSheet_meta.json).
// The tile-picker overlay can override these per-user via localStorage.
- // floor/wall are ARRAYS of [col,row] variants (sheet cols = 57): TileRenderer
- // picks one deterministically per cell so a wall of stone doesn't read as a
- // single flat texture. Single-pair kinds (bar/table/features) draw as-is.
+ // Each kind maps to a single [col,row] on the sheet (cols = 57). Per-cell "variant"
+ // arrays were tried but mixing wood/stone/plank tiles per cell read as noise, so we
+ // keep one coherent tile per kind. (TileRenderer still accepts an array here if a
+ // future theme wants subtle, same-material variation.)
tiles: {
- // floor: sheet 119/120 (wood/stone) + 982-984 (planks)
- floor: [[5, 2], [6, 2], [13, 17], [14, 17], [15, 17]],
- floor2: [[6, 2], [13, 17], [15, 17]],
- // wall: sheet 697-701 + 868/869/871-874 (stone masonry)
- wall: [[13, 12], [14, 12], [15, 12], [16, 12], [17, 12],
- [13, 15], [14, 15], [16, 15], [17, 15], [18, 15], [19, 15]],
+ floor: [5, 2], // tile 119 — wood floor (uniform)
+ floor2: [6, 2], // tile 120 — stone floor (accent)
+ wall: [13, 12], // tile 697 — stone masonry
+
bar: [28, 0], // tile 28 — counter
table: [20, 3], // tile 191 — table
// Dungeon features drawn as real tiles instead of monospace glyphs.
diff --git a/html/js/ui/ui.js b/html/js/ui/ui.js
index 30fcdc0..53b9af3 100644
--- a/html/js/ui/ui.js
+++ b/html/js/ui/ui.js
@@ -19,7 +19,10 @@ const UI = {
var chatInput = $('#chatInput');
if (document.activeElement === gameDisplay[0]) {
- gameDisplay.css('outline', '2px solid yellow');
+ // Inset the outline (offset -2px) so it is drawn INSIDE the box — the play area is
+ // flush to the viewport's right edge and the container clips an outward outline there,
+ // which hid the border on the right side.
+ gameDisplay.css({ 'outline': '2px solid yellow', 'outline-offset': '-2px' });
chatInput.css('outline', 'none');
} else if (document.activeElement === chatInput[0]) {
chatInput.css('outline', '2px solid cyan');