Skip to content
This repository has been archived by the owner on Aug 19, 2021. It is now read-only.

Commit

Permalink
Allow players to rejoin an in-progress game
Browse files Browse the repository at this point in the history
  • Loading branch information
kcgidw committed Apr 20, 2020
1 parent 1be6908 commit aa77d0e
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 39 deletions.
16 changes: 9 additions & 7 deletions src/public/js/faq-view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@
</div>
<div class="align-left">
<div class="qa">
<h3>I found a bug!</h3>
<p>
Bug reports are greatly appreciated! Contact me at
<em>fakeartistonline@gmail.com</em>, or post an issue on Github.
</p>
<h3>
I accidentally quit my browser. Can I rejoin an in-progress game?
I accidentally quit my browser. How do I rejoin an in-progress game?
</h3>
<p>This is on the to-do list!</p>
<p>Join the room again with your username exactly as it was.</p>
</div>
<div class="qa">
<h3>The website connection is spotty!</h3>
<p>FAO's currently on Heroku's free hosting service.</p>
<p>(I would like to get a proper server and domain at some point!)</p>
</div>
<div class="qa">
<h3>I found a bug!</h3>
<p>
Bug reports are greatly appreciated! Contact me at
<em>fakeartistonline@gmail.com</em>, or post an issue on Github.
</p>
</div>
<div class="qa">
<h3>Will you implement ___?</h3>
<p>
Expand Down
64 changes: 36 additions & 28 deletions src/public/js/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,37 @@ const Store = {
this.state.view = view;
},
setGameState(newGameState) {
if(newGameState === undefined) {
if (newGameState === undefined) {
this.state.gameState = undefined;
this.setGameConnection(CONNECTION_STATE.DISCONNECT);
this.setView(VIEW.HOME);
return;
}
this.setGameConnection(CONNECTION_STATE.CONNECT);

if(this.state.gameState === undefined) {
if (this.state.gameState === undefined) {
this.state.gameState = generateClientGameState();
}
this.state.gameState.adoptJson(newGameState);

if(this.state.gameState.phase === GAME_PHASE.SETUP) {
if (this.state.gameState.phase === GAME_PHASE.SETUP) {
this.setView(VIEW.SETUP);
} else if(this.state.gameState.phase === GAME_PHASE.PLAY || this.state.gameState.phase === GAME_PHASE.VOTE) {
} else if (
this.state.gameState.phase === GAME_PHASE.PLAY ||
this.state.gameState.phase === GAME_PHASE.VOTE
) {
this.setView(VIEW.GAME);
}
},
setGameConnection(cs) {
this.state.gameConnection = cs;
},
myTurn() {
return this.state.gameState
&& this.state.gameState.whoseTurn === this.state.username
&& this.state.gameState.phase === GAME_PHASE.PLAY;
return (
this.state.gameState &&
this.state.gameState.whoseTurn === this.state.username &&
this.state.gameState.phase === GAME_PHASE.PLAY
);
},
setWarning(warningName, message) {
this.state[warningName] = message;
Expand All @@ -67,36 +72,38 @@ const Store = {

function handleSocket(messageName, handler, errHandler) {
socket.on(messageName, function(data) {
if(data.err) {
if (data.err) {
console.warn(data.err);
if(errHandler) {
if (errHandler) {
errHandler(data.err);
}
return;
}
if(handler) {
if (handler) {
handler(data);
}
if(data.roomState !== undefined) {
if (data.roomState !== undefined) {
Store.setGameState(data.roomState);
}
});
}
handleSocket(MESSAGE.CREATE_ROOM,
handleSocket(
MESSAGE.CREATE_ROOM,
function(data) {
Store.setUsername(data.username);
},
function(errMsg) {
Store.setWarning('createWarning', errMsg);
}
);
handleSocket(MESSAGE.JOIN_ROOM,
handleSocket(
MESSAGE.JOIN_ROOM,
function(data) {
if(data.username !== Store.state.username) {
if (data.username !== Store.state.username) {
return;
}
Store.setWarning('joinWarning', undefined);
if(data.rejoin === true) {
if (data.rejoin === true) {
console.log('Game reconnect success');
}
},
Expand All @@ -113,10 +120,11 @@ handleSocket(MESSAGE.START_GAME);
handleSocket(MESSAGE.NEW_TURN);
handleSocket(MESSAGE.RETURN_TO_SETUP);

const usernameWarning = 'Username must be 1-20 characters long, and can only contain alphanumerics and spaces';
const usernameWarning =
'Username must be 1-20 characters long, and can only contain alphanumerics and spaces';
function submitCreateGame(username) {
username = username.trim();
if(validateUsername(username)) {
if (validateUsername(username)) {
this.setWarning('createWarning', undefined);
socket.emit(MESSAGE.CREATE_ROOM, {
username: username,
Expand All @@ -129,7 +137,7 @@ function submitCreateGame(username) {
}
function submitJoinGame(roomCode, username) {
username = username.trim();
if(validateUsername(username)) {
if (validateUsername(username)) {
this.setWarning('joinWarning', undefined);
socket.emit(MESSAGE.JOIN_ROOM, {
roomCode: roomCode,
Expand Down Expand Up @@ -162,17 +170,17 @@ function submitReturnToSetup() {
socket.on('disconnect', function() {
Store.state.gameConnection = CONNECTION_STATE.DISCONNECT;
let existingGameState = Store.state.gameState;
if(existingGameState) {
switch(existingGameState.phase) {
if (existingGameState) {
let me = existingGameState.findUser(Store.state.username);
switch (existingGameState.phase) {
case GAME_PHASE.SETUP:
// if user was in room setup, just forget about the gamestate altogether
// No need to handle reconnection, user should just join the room normally again
Store.setGameState(undefined);
break;
case GAME_PHASE.PLAY:
case GAME_PHASE.VOTE:
let me = existingGameState.findUser(Store.state.username);
if(me) {
if (me) {
me.connected = false;
}
break;
Expand All @@ -187,26 +195,26 @@ socket.on('reconnect', reconnectToGame);
function reconnectToGame() {
let existingGameState = Store.state.gameState;
let username = Store.state.username;
if(existingGameState && username && Store.state.gameConnection === CONNECTION_STATE.DISCONNECT) {
if (
existingGameState &&
username &&
Store.state.gameConnection === CONNECTION_STATE.DISCONNECT
) {
Store.state.gameConnection = CONNECTION_STATE.RECONNECT;
console.log('Attempting game rejoin.');
socket.emit(MESSAGE.JOIN_ROOM, {
roomCode: existingGameState.roomCode,
username: username,
rejoin: true,
});
}
}
window.faodbg = {
dcon() {
socket.disconnect();
},
recon() {
reconnectToGame();
},
con() {
socket.connect();
},
};

export default Store;
export default Store;
3 changes: 0 additions & 3 deletions src/server/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ SCHEMA[MESSAGE.JOIN_ROOM] = {
type: ['string', 'number'],
minLength: 1,
},
rejoin: {
type: 'boolean',
},
},
required: ['username', 'roomCode'],
};
Expand Down
13 changes: 12 additions & 1 deletion src/server/socket-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,16 @@ const MessageHandlers = {
GamePrecond.roomExists(data.roomCode);

let user;
const nameExistsInRoom = roomToJoin.findUser(data.username) !== undefined;

if (data.rejoin) {
if (nameExistsInRoom) {
// rejoin
GamePrecond.nameIsTakenInRoom(data.username, roomToJoin);
GamePrecond.gameInProgress(roomToJoin);
user = login(sock, data.username, roomToJoin);
joinRoom(user, roomToJoin, true, false);
} else {
// join for first time
GamePrecond.roomIsNotFull(roomToJoin);
GamePrecond.gameNotInProgress(roomToJoin);
GamePrecond.nameIsNotTakenInRoom(data.username, roomToJoin);
Expand Down Expand Up @@ -259,6 +262,14 @@ const GamePrecond = {
);
}
},
userIsDisconnected(username, room) {
if (!room.findUser(username).connected) {
throw new GameError(
`Username ${username} connected to ${room.roomCode}`,
'This username is taken in this room'
);
}
},
};

// send roomstate update to all users, accounting for different roles (i.e., faker vs artist)
Expand Down

0 comments on commit aa77d0e

Please sign in to comment.