Implement creating and joining rooms
This commit is contained in:
parent
50f359c1c3
commit
4ba0f326bd
7 changed files with 127 additions and 17 deletions
|
@ -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;
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
import "./newGame";
|
||||
import "./joinGame";
|
||||
|
|
38
imports/api/methods/joinGame.js
Normal file
38
imports/api/methods/joinGame.js
Normal 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 };
|
||||
}
|
||||
});
|
|
@ -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 };
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
newGame: function(evt) {
|
||||
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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
Loading…
Reference in a new issue