diff --git a/index.html b/index.html index 2f457d5..886f33c 100644 --- a/index.html +++ b/index.html @@ -14,63 +14,7 @@ src="https://cdn.jsdelivr.net/npm/htmx-ext-ws@2.0.2" crossorigin="anonymous" > - +
@@ -86,98 +30,8 @@
Connecting...
- + + + diff --git a/public/scripts/copy-game-link.js b/public/scripts/copy-game-link.js new file mode 100644 index 0000000..b432bbf --- /dev/null +++ b/public/scripts/copy-game-link.js @@ -0,0 +1,13 @@ +function copyGameLink() { + const gameLinkInput = document.getElementById('game-link'); + if (gameLinkInput) { + navigator.clipboard + .writeText(gameLinkInput.value) + .then(() => { + alert('Game link copied to clipboard!'); + }) + .catch((err) => { + console.error('Failed to copy link: ', err); + }); + } +} \ No newline at end of file diff --git a/public/scripts/display-ws-connection.js b/public/scripts/display-ws-connection.js new file mode 100644 index 0000000..7e3ccf7 --- /dev/null +++ b/public/scripts/display-ws-connection.js @@ -0,0 +1,41 @@ +// Get gameId and playerId from meta tags generated by the server +const gameIdMeta = document.querySelector('meta[name="gameId"]'); +const playerIdMeta = document.querySelector('meta[name="playerId"]'); +if (!gameIdMeta || !playerIdMeta) { + console.error('Game ID or Player ID meta tags not found.'); +} +const gameId = gameIdMeta.content; +const playerId = playerIdMeta.content; + +// Dynamically construct WebSocket URL +const wsUrl = `ws://${window.location.host}/ws?gameId=${gameId}&playerId=${playerId}`; + +// Get the game container element +const gameContainer = document.getElementById('game-container'); + +// Set the ws-connect attribute +gameContainer.setAttribute('ws-connect', wsUrl); + +// Tell HTMX to connect the WebSocket +htmx.trigger(gameContainer, ' and connect'); + +// Update the game link input +const gameLinkInput = document.getElementById('game-link'); +if (!gameLinkInput) { + console.error('Missing game-link element.') +} +gameLinkInput.value = + window.location.origin + + window.location.pathname + + `?gameId=${gameId}`; + +// Update the WebSocket status indicator +const wsStatusDiv = document.getElementById('ws-status'); + +gameContainer.addEventListener('htmx:wsClose', function () { + if (wsStatusDiv) wsStatusDiv.textContent = 'Disconnected'; +}); + +gameContainer.addEventListener('htmx:wsError', function () { + if (wsStatusDiv) wsStatusDiv.textContent = 'Connection Error'; +}); diff --git a/public/scripts/send-ws-messages.js b/public/scripts/send-ws-messages.js new file mode 100644 index 0000000..a03fcd4 --- /dev/null +++ b/public/scripts/send-ws-messages.js @@ -0,0 +1,13 @@ +document.addEventListener('htmx:wsConfigSend', function(e) { + if (e.target.classList.contains('board-cell')) { + const row = parseInt(e.target.dataset.row); + const col = parseInt(e.target.dataset.col); + + // Set the custom JSON data + e.detail.parameters = { + type: "make_move", + row: row, + col: col + }; + } +}); \ No newline at end of file diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..7ecfb04 --- /dev/null +++ b/public/style.css @@ -0,0 +1,55 @@ +body { + font-family: Arial, sans-serif; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100vh; + margin: 0; + background-color: #f0f0f0; +} +#game-container { + background-color: white; + padding: 20px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + text-align: center; +} +.game-board-grid { + display: grid; + grid-template-columns: repeat(15, 1fr); + width: 450px; /* 15 * 30px */ + height: 450px; /* 15 * 30px */ + border: 1px solid black; + margin-top: 20px; +} +.board-cell { + width: 30px; + height: 30px; + border: 1px solid #ccc; + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; +} +.board-cell:hover { + background-color: #e0e0e0; +} +.board-cell > div { + width: 24px; + height: 24px; + border-radius: 50%; + border: 1px solid #333; +} +.last-move { + box-shadow: 0 0 5px 3px rgba(255, 255, 0, 0.7); /* Yellow glow */ +} +#messages { + margin-top: 10px; + font-size: 0.9em; + color: #555; +} +#player-info { + margin-top: 10px; + font-weight: bold; +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index b3b7fc8..bdc0ff4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,20 +22,15 @@ const app = new Elysia() }), open(ws) { const { gameId, playerId } = ws.data.query; - if (!gameId || !playerId) { console.error( 'WebSocket connection missing gameId or playerId in query params.', ); - ws.send( - JSON.stringify({ - type: 'error', - error: 'Missing gameId or playerId.', - }), - ); + ws.send('Error: missing gameId or playerId.'); ws.close(); return; } + wsHandler.handleConnection(ws, gameId, playerId); const game = wsHandler.getGame(gameId); @@ -47,7 +42,7 @@ const app = new Elysia() } else if (game.getPlayerCount() === 1 && game.status === 'waiting') { message = `You are ${playerId}. Waiting for another player to join.`; } - wsHandler.sendMessage(game.id, 'message', message, ws); + wsHandler.sendMessage(game.id, message, ws); } else { ws.send( JSON.stringify({