diff --git a/client/src/App.js b/client/src/App.js index 6e4a2a1..839b692 100755 --- a/client/src/App.js +++ b/client/src/App.js @@ -178,6 +178,7 @@ const Table = () => { break; } }; + const sendUpdate = (update) => { ws.send(JSON.stringify(update)); }; @@ -366,7 +367,7 @@ const Table = () => { audioEffects.volcano.hasPlayed = false; } } - }, [state]); + }, [state, volume]); useEffect(() => { if (turn && turn.color === color) { diff --git a/server/ai/app.js b/server/ai/app.js new file mode 100644 index 0000000..da5bbff --- /dev/null +++ b/server/ai/app.js @@ -0,0 +1,141 @@ +const fetch = require('node-fetch'); +const WebSocket = require('ws'); + +const version = '0.0.1'; + +if (process.argv.length < 5) { + console.error(` +usage: npm start SERVER GAME-ID USER + +For example: + + npm start https://nuc.ketrenos.com:3000/ketr.ketran robot-wars ai-1 + +`); + process.exit(-1); +} + +const server = process.argv[2]; +const gameId = process.argv[3]; +let session = undefined; +const user = process.argv[4]; + +const game = {}; + +process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; + +const error = (e) => { + console.log(`ws - error`, e); +} + +const connect = async () => { + let loc = new URL(server), new_uri; + const res = await fetch(`${server}/api/v1/games`, { + method: 'GET', + cache: 'no-cache', + credentials: 'same-origin', /* include cookies */ + headers: { + 'Content-Type': 'application/json' + } + }); + if (!res) { + throw new Error(`Unable to connect to ${server}`); + } + + const { player } = JSON.parse(await res.text()); + console.log(`Connecting to ${server} as ${player}`); + + if (loc.protocol === "https:") { + new_uri = "wss"; + } else { + new_uri = "ws"; + } + new_uri = `${new_uri}://${loc.host}/ketr.ketran/api/v1/games/ws/${gameId}`; + const ws = new WebSocket(new_uri, + [], + { + 'headers': { + 'Cookie': `player=${player}` + } + }); + return new Promise((resolve, reject) => { + const headers = (e) => { + console.log(`ws - headers`); + }; + + const open = (e) => { + console.log(`ws - open`); + resolve(ws); + }; + + const close = (e) => { + console.log(`ws - close`); + }; + + ws.on('open', open); + ws.on('headers', headers); + ws.on('close', close); + ws.on('error', error); + ws.on('message', (data) => { message(ws, data) }); + }); +}; + +const message = (ws, data) => { + data = JSON.parse(data); + switch (data.type) { + case 'game-update': + Object.assign(game, data.update); + if (game.name === '') { + ws.send(JSON.stringify({ type: 'player-name', name: user })); + } + if (game.state === 'lobby' && game.unselected.indexOf(user) !== -1) { + const slots = []; + for (let color in game.players) { + if (game.players[color].status === 'Not active') { + slots.push(color); + } + } + if (slots.length !== 0) { + const index = Math.floor(Math.random() * slots.length); + console.log(`Requesting to play as ${slots[index]}.`); + game.unselected = game.unselected.filter( + color => color === slots[index]); + ws.send(JSON.stringify({ + type: 'set', + field: 'color', + value: slots[index] + })); + ws.send(JSON.stringify({ + type: 'chat', + message: `Woohoo! Robot AI ${version} is alive!` + })); + } + } + break; + + case 'ping': + break; + + default: + console.log(data); + break; + } +} + +const ai = async (ws) => { + ws.send(JSON.stringify({ + type: 'game-update' + })); +} + +connect().then((ws) => { + ai(ws).then(() => { + }) + .catch((error) => { + console.error(error); + ws.close(); + }); +}) +.catch((error) => { + console.error(error); +}); diff --git a/server/ai/package.json b/server/ai/package.json new file mode 100644 index 0000000..2fe57e9 --- /dev/null +++ b/server/ai/package.json @@ -0,0 +1,27 @@ +{ + "name": "peddlers-of-ketran-ai-bot", + "version": "1.0.0", + "main": "app.js", + "scripts": { + "start": "export $(cat ../../.env | xargs) && node app.js" + }, + "author": "James Ketrenos ", + "license": "MIT", + "private": true, + "dependencies": { + "bluebird": "^3.5.5", + "body-parser": "^1.19.2", + "config": "^3.1.0", + "cookie-parser": "^1.4.6", + "core-js": "^3.21.1", + "fast-deep-equal": "^3.1.3", + "moment": "^2.24.0", + "node-fetch": "^2.6.0", + "node-gzip": "^1.1.2", + "ws": "^8.5.0" + }, + "repository": { + "type": "git", + "url": "git@git.ketrenos.com:jketreno/peddlers-of-ketran" + } +} diff --git a/server/routes/games.js b/server/routes/games.js index 18c1b17..8ec7834 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -3843,7 +3843,7 @@ const gotoLobby = (game, session) => { router.ws("/ws/:id", async (ws, req) => { if (!req.cookies || !req.cookies.player) { - ws.send({ type: 'error', error: `Unable to find session cookie` }); + ws.send(JSON.stringify({ type: 'error', error: `Unable to find session cookie` })); return; }