diff --git a/client/package.json b/client/package.json index fab710f6..4a07d6cb 100755 --- a/client/package.json +++ b/client/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "start": "parcel index.html --port 40080 --no-hmr --no-source-maps", - "build": "rm -rf dist && parcel build index.html", + "build": "rm -rf dist && parcel build --no-source-maps index.html", "lint": "eslint --fix src/", "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/client/src/main.js b/client/src/main.js index cef96aa6..6203789b 100644 --- a/client/src/main.js +++ b/client/src/main.js @@ -7,5 +7,6 @@ const game = renderCryps(); const events = registerEvents(game.registry, game.events); const ws = createSocket(events); events.setWs(ws); +events.setGameList([]); ws.connect(); diff --git a/client/src/scenes/constants.js b/client/src/scenes/constants.js index 48261fb4..727ef7bf 100644 --- a/client/src/scenes/constants.js +++ b/client/src/scenes/constants.js @@ -18,6 +18,7 @@ const gameListWidth = () => Math.floor(window.innerWidth * 0.2); const gameListHeight = () => Math.floor(window.innerHeight / 10); const gameListX = () => crypListWidth(); const gameListY = i => menuHeight() + (gameListHeight() * i); +const gameListRowY = i => menuHeight() + (gameListHeight() * (i + 2)); const statsWidth = () => Math.floor(window.innerWidth - crypListWidth() - gameListWidth()); const statsHeight = () => window.innerHeight - menuHeight(); @@ -82,6 +83,7 @@ module.exports = { y: gameListY, width: gameListWidth, height: gameListHeight, + rowY: gameListRowY, }, }, diff --git a/client/src/scenes/cryp.list.js b/client/src/scenes/cryp.list.js index 951dcd3a..43f1ab17 100644 --- a/client/src/scenes/cryp.list.js +++ b/client/src/scenes/cryp.list.js @@ -15,14 +15,23 @@ class CrypList extends Phaser.Scene { return true; } - updateData(parent, key, data) { - if (key === 'cryps') { - this.renderList(data); + updateData(parent, key) { + const UPDATE_KEYS = ['gameList', 'cryps']; + if (UPDATE_KEYS.includes(key)) { + this.renderList(); + this.renderGameList(); } + + if (key === 'game' && this.scene.isActive()) { + this.scene.switch('Combat'); + } + return true; } - renderList(cryps) { + renderList() { + const cryps = this.registry.get('cryps'); + // your cryps if (this.CrypRows) { this.CrypRows.cleanup(); @@ -35,10 +44,19 @@ class CrypList extends Phaser.Scene { const cryp = cryps.find(c => c.id === this.CrypPage.id); this.displaySkills(cryp); } + } + + renderGameList() { + const ws = this.registry.get('ws'); + const cryps = this.registry.get('cryps'); + const gameList = this.registry.get('gameList'); + if (this.gameList) { + this.gameList.cleanup(); this.gameList.destroy(true); } - this.gameList = new GameList(this, cryps); + + this.gameList = new GameList({ list: this, ws, cryps, gameList }); } displaySkills(cryp) { diff --git a/client/src/scenes/game.list.js b/client/src/scenes/game.list.js index ca7d778c..21462a1b 100644 --- a/client/src/scenes/game.list.js +++ b/client/src/scenes/game.list.js @@ -7,55 +7,65 @@ const { } = require('./constants'); class GameList extends Phaser.GameObjects.Group { - constructor(list, cryps) { + constructor(args) { super(list); - // this.keyboard = list.input.keyboard; - const ws = list.registry.get('ws'); - - const games = [ - 'PVE', - 'PVP', - ]; + const { list, ws, cryps, gameList } = args; const X = GAME_LIST.x(); const WIDTH = GAME_LIST.width(); const HEIGHT = GAME_LIST.height(); + const TEXT_MARGIN = 24; const pvp = list.add .rectangle(X, GAME_LIST.y(0), WIDTH, HEIGHT, 0x440000) .setInteractive() .setOrigin(0); - this - .add(list.add.text(pvp.getCenter().x, pvp.getCenter().y, 'NEW', TEXT.HEADER)); + this.add(list.add.text(pvp.getCenter().x, pvp.getCenter().y, 'NEW', TEXT.HEADER)); const pve = list.add .rectangle(X, GAME_LIST.y(1), Math.floor(WIDTH / 2), HEIGHT, 0x004400) .setInteractive() .setOrigin(0); - this - .add(list.add.text(pve.getCenter().x, pve.getCenter().y, 'PVE', TEXT.HEADER)); + this.add(list.add.text(pve.getCenter().x, pve.getCenter().y, 'PVE', TEXT.HEADER)); const refresh = list.add .rectangle(X + Math.floor(WIDTH / 2), GAME_LIST.y(1), Math.floor(WIDTH / 2), HEIGHT, 0x000044) .setInteractive() .setOrigin(0); - this - .add(list.add.text(refresh.getCenter().x, refresh.getCenter().y, 'REFRESH', TEXT.HEADER)); + this.add(list.add.text(refresh.getCenter().x, refresh.getCenter().y, 'REFRESH', TEXT.HEADER)); + const gameRow = (game, i) => { + const GAME_X = GAME_LIST.x(); + const GAME_Y = GAME_LIST.rowY(i); + + const gameBox = list.add + .rectangle(GAME_X, GAME_Y, WIDTH, HEIGHT, 0x111111) + .setInteractive() + .setOrigin(0); + + this.add(list.add.text(GAME_X, GAME_Y, game.id, TEXT.NORMAL)); + this.add(list.add.text(GAME_X, GAME_Y + TEXT_MARGIN, `${game.team_size}v${game.team_size}`, TEXT.NORMAL)); + + gameBox.on('pointerdown', () => { + const team = cryps.filter(c => c.active).map(c => c.id); + ws.sendGameJoin(game.id, team); + }); + }; + + gameList.forEach(gameRow); + pvp.on('pointerdown', () => { const team = cryps.filter(c => c.active).map(c => c.id); - list.scene.switch('Combat'); return ws.sendGamePvp(team); }); pve.on('pointerdown', () => { const team = cryps.filter(c => c.active).map(c => c.id); - list.scene.switch('Combat'); return ws.sendGamePve(team); }); diff --git a/ops/migrations/20181020104420_games.js b/ops/migrations/20181020104420_games.js index 1297bd48..09e8ccf0 100644 --- a/ops/migrations/20181020104420_games.js +++ b/ops/migrations/20181020104420_games.js @@ -5,11 +5,9 @@ exports.up = async knex => { table.timestamps(); table.binary('data').notNullable(); - table.boolean('open') + table.boolean('joinable') .defaultTo(true) .notNullable(); - - // table.boolean('active').notNullable(); }); await knex.schema.createTable('players', table => { diff --git a/server/src/game.rs b/server/src/game.rs index 64fc9e5f..b27412ae 100755 --- a/server/src/game.rs +++ b/server/src/game.rs @@ -98,7 +98,11 @@ impl Game { self } - fn add_team(&mut self, team: Team) -> Result<&mut Game, Error> { + fn already_joined(&self, team_id: Uuid) -> bool { + self.teams.iter().any(|t| t.id == team_id) + } + + fn team_add(&mut self, team: Team) -> Result<&mut Game, Error> { if self.teams.len() == self.team_num { return Err(err_msg("maximum number of teams")); } @@ -154,6 +158,10 @@ impl Game { self } + fn joinable(&self) -> bool { + self.phase == Phase::Start + } + fn can_start(&self) -> bool { self.teams.len() == self.team_num } @@ -497,13 +505,13 @@ pub fn game_new(game: &Game, tx: &mut Transaction) -> Result<(), Error> { let game_bytes = to_vec(&game)?; let query = " - INSERT INTO games (id, data) - VALUES ($1, $2) + INSERT INTO games (id, data, joinable) + VALUES ($1, $2, $3) RETURNING id; "; let result = tx - .query(query, &[&game.id, &game_bytes])?; + .query(query, &[&game.id, &game.joinable(), &game_bytes])?; result.iter().next().ok_or(format_err!("no game written"))?; @@ -568,13 +576,13 @@ pub fn game_update(game: &Game, tx: &mut Transaction) -> Result<(), Error> { let query = " UPDATE games - SET data = $1 - WHERE id = $2 + SET (data = $1, joinable = $2) + WHERE id = $3 RETURNING id, data; "; let result = tx - .query(query, &[&game_bytes, &game.id])?; + .query(query, &[&game_bytes, &game.joinable(), &game.id])?; result.iter().next().ok_or(format_err!("game {:?} could not be written", game))?; @@ -634,8 +642,8 @@ pub fn game_pve(params: GamePveParams, tx: &mut Transaction, account: &Account) .set_cryps(mobs); game - .add_team(plr_team)? - .add_team(mob_team)?; + .team_add(plr_team)? + .team_add(mob_team)?; game.start(); @@ -665,7 +673,7 @@ pub fn game_pvp(params: GamePvpParams, tx: &mut Transaction, account: &Account) let mut team = Team::new(account.id); team.set_cryps(cryps); - game.add_team(team)?; + game.team_add(team)?; // persist game_new(&game, tx)?; @@ -676,6 +684,13 @@ pub fn game_pvp(params: GamePvpParams, tx: &mut Transaction, account: &Account) pub fn game_join(params: GameJoinParams, tx: &mut Transaction, account: &Account) -> Result { let mut game = game_get(tx, params.game_id)?; + + // rejoining a game from the FE list + if game.already_joined(account.id) { + return Ok(game); + } + + // ok actually adding a new team let game_id = game.id; let cryps = params.cryp_ids @@ -689,8 +704,7 @@ pub fn game_join(params: GameJoinParams, tx: &mut Transaction, account: &Account let mut team = Team::new(account.id); team.set_cryps(cryps); - - game.add_team(team)?; + game.team_add(team)?; if game.can_start() { game.start(); @@ -706,7 +720,7 @@ pub fn game_joinable_list(tx: &mut Transaction, _account: &Account) -> Result