Implement creating and joining rooms

This commit is contained in:
Michael Zhang 2020-11-27 01:16:15 -06:00
parent 50f359c1c3
commit 4ba0f326bd
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
7 changed files with 127 additions and 17 deletions

View file

@ -2,7 +2,7 @@ import { Mongo } from "meteor/mongo";
let Players = new Mongo.Collection("players");
// let collection = Players.rawCollection();
// collection.ensureIndex({ joinCode: 1 }, { unique: true });
let collection = Players.rawCollection();
collection.ensureIndex({ name: 1, roomId: 1, }, { unique: true });
export default Players;

View file

@ -1 +1,2 @@
import "./newGame";
import "./joinGame";

View file

@ -0,0 +1,38 @@
import { Meteor } from "meteor/meteor";
import { Random } from "meteor/random";
import { check } from "meteor/check";
import Rooms from "../collections/Rooms.js";
import Players from "../collections/Players.js";
Meteor.methods({
"joinGame": async ({ code, name }) => {
check(code, String);
check(name, String);
name = name.trim();
let room = Rooms.findOne({ joinCode: code });
if (room === undefined) {
throw new Meteor.Error("room-not-found");
}
if (room.state !== "waitingRoom") {
throw new Meteor.Error("room-already-playing");
}
let roomId = room._id;
try {
let playerId = Players.insert({ roomId, name });
} catch (e) {
if (e.code === 11000) {
throw new Meteor.Error("name-collision");
}
}
let joinCode = room.joinCode;
let players = {};
Players.find({ roomId }).forEach((doc) => {
players[doc._id] = doc.name;
});
return { joinCode, players, roomId };
}
});

View file

@ -7,6 +7,8 @@ import Players from "../collections/Players.js";
Meteor.methods({
"newGame": async ({ name }) => {
check(name, String);
name = name.trim();
let roomId = null;
let state = "waitingRoom";
@ -25,16 +27,21 @@ Meteor.methods({
// BulkWriteError
if (e.code === 11000) {
remainingAttempts -= 1;
} else {
console.log("UNCAUGHT", e);
}
}
}
let playerId = Players.insert({ roomId, name });
Rooms.update(roomId, { $set: { owner: playerId } });
if (remainingAttempts == 0 && roomId === null) {
return "failed";
throw new Meteor.Error("no-more-rooms");
}
return { playerId, roomId, joinCode };
let players = {};
players[playerId] = name;
return { players, roomId, joinCode };
},
});

View file

@ -1,15 +1,22 @@
<template>
<div>
<component v-bind:is="whatScreen"></component>
<component
v-bind:is="whatScreen"
v-bind="currentRoom"
v-on:newGame="newGame"
v-on:joinGame="joinGame"
></component>
</div>
</template>
<script>
import Lobby from './components/Lobby.vue'
import WaitingRoom from './components/WaitingRoom.vue'
export default {
components: {
Lobby,
WaitingRoom,
},
data() {
@ -18,6 +25,18 @@ export default {
whatScreen: Lobby,
};
},
methods: {
newGame: function(args) {
this.currentRoom = args;
this.whatScreen = WaitingRoom;
},
joinGame: function(args) {
this.currentRoom = args;
this.whatScreen = WaitingRoom;
},
}
}
</script>

View file

@ -2,6 +2,8 @@
<div>
<h1>LOBBY</h1>
<div id="error">{{ errorMessage }}</div>
<form v-on:submit.prevent="newGame">
<input
type="text"
@ -11,16 +13,30 @@
v-model="newGameName"
:disabled="loading"
/>
<button type="submit">new game</button>
<button type="submit" :disabled="loading">new game</button>
</form>
<p>or</p>
<div>
<input type="text" autocomplete="off" name="name" placeholder="what's your name?" />
<input type="text" autocomplete="off" name="code" placeholder="join code" />
<button id="joingame-btn">join game</button>
</div>
<form v-on:submit.prevent="joinGame">
<input
type="text"
autocomplete="off"
required
placeholder="join code"
v-model="joinGameCode"
:disabled="loading"
/>
<input
type="text"
autocomplete="off"
required
placeholder="what's your name?"
v-model="joinGameName"
:disabled="loading"
/>
<button type="submit" :disabled="loading">join game</button>
</form>
</div>
</template>
@ -32,20 +48,45 @@ export default {
return {
loading: false,
newGameName: "",
joinGameName: "",
joinGameCode: "",
errorMessage: "",
};
},
methods: {
newGame: function(evt) {
loading = true;
this.loading = true;
let name = this.newGameName;
Meteor.call("newGame", { name }, (err, res) => {
console.log(err, res);
});
if (err !== undefined) {
this.errorMessage = err.message;
this.loading = false;
return;
}
this.$emit("newGame", res);
});
},
joinGame: function(evt) {
this.loading = true;
let name = this.joinGameName;
let code = this.joinGameCode;
Meteor.call("joinGame", { code, name }, (err, res) => {
if (err !== undefined) {
this.errorMessage = err.message;
this.loading = false;
return;
}
this.$emit("joinGame", res);
});
},
}
}
</script>
<style scoped>
#error {
color: red;
}
</style>

View file

@ -1,10 +1,14 @@
<template>
<div>
<h1>Waiting for players...</h1>
<p>Join code: {{ joinCode.toUpperCase() }}</p>
<p>Players: {{ players }}</p>
</div>
</template>
<script>
export default {
props: ["joinCode", "players"],
}
</script>