Files
Werewolf/client/src/modules/game_state/states/Lobby.js
2022-12-17 15:18:05 -05:00

187 lines
7.6 KiB
JavaScript

import { QRCode } from '../../third_party/qrcode.js';
import { toast } from '../../front_end_components/Toast.js';
import { globals } from '../../../config/globals.js';
import { HTMLFragments } from '../../front_end_components/HTMLFragments.js';
import { Confirmation } from '../../front_end_components/Confirmation.js';
export class Lobby {
constructor (containerId, stateBucket, socket) {
this.stateBucket = stateBucket;
this.socket = socket;
this.container = document.getElementById(containerId);
this.container.innerHTML = HTMLFragments.LOBBY;
this.startGameHandler = (e) => {
e.preventDefault();
Confirmation('Start game and deal roles?', () => {
socket.emit(
globals.SOCKET_EVENTS.IN_GAME_MESSAGE,
globals.EVENT_IDS.START_GAME,
stateBucket.currentGameState.accessCode,
null,
() => {
this.removeStartGameFunctionalityIfPresent();
}
);
});
};
}
populateHeader () {
const timeString = getTimeString(this.stateBucket.currentGameState);
const time = this.container.querySelector('#game-time');
time.innerText = timeString;
const linkContainer = this.container.querySelector('#game-link');
linkContainer.innerHTML = '<img src=\'../images/copy.svg\' alt=\'copy\'/>';
const link = window.location.protocol + '//' + window.location.host +
'/join/' + this.stateBucket.currentGameState.accessCode +
'?playerCount=' + this.stateBucket.currentGameState.gameSize +
'&timer=' + encodeURIComponent(timeString);
const linkDiv = document.createElement('div');
linkDiv.innerText = link;
linkContainer.prepend(linkDiv);
activateLink(linkContainer, link);
const playerCount = this.container.querySelector('#game-player-count');
playerCount.innerText = this.stateBucket.currentGameState.gameSize + ' Players';
const gameCode = this.container.querySelector('#game-code');
gameCode.innerHTML = 'Or enter this code on the homepage: <span>' +
this.stateBucket.currentGameState.accessCode + '</span>';
QRCode.toCanvas(document.getElementById('canvas'), link, { scale: 2 }, function (error) {
if (error) console.error(error);
});
}
populatePlayers () {
document.querySelectorAll('.lobby-player').forEach((el) => el.remove());
const lobbyPlayersContainer = this.container.querySelector('#lobby-players');
if (this.stateBucket.currentGameState.moderator.userType === globals.USER_TYPES.MODERATOR) {
lobbyPlayersContainer.appendChild(
renderLobbyPerson(
this.stateBucket.currentGameState.moderator.name,
this.stateBucket.currentGameState.moderator.userType
)
);
}
for (const person of this.stateBucket.currentGameState.people) {
lobbyPlayersContainer.appendChild(renderLobbyPerson(person.name, person.userType));
}
const playerCount = this.stateBucket.currentGameState.people.length;
document.querySelector("label[for='lobby-players']").innerText =
'Participants (' + playerCount + '/' + this.stateBucket.currentGameState.gameSize + ' Players)';
}
setSocketHandlers () {
this.socket.on(globals.EVENT_IDS.PLAYER_JOINED, (player, gameIsFull) => {
toast(player.name + ' joined!', 'success', true, true, 'short');
this.stateBucket.currentGameState.people.push(player);
this.stateBucket.currentGameState.isFull = gameIsFull;
this.populatePlayers();
if ((
this.stateBucket.currentGameState.client.userType === globals.USER_TYPES.MODERATOR
|| this.stateBucket.currentGameState.client.userType === globals.USER_TYPES.TEMPORARY_MODERATOR
)
) {
this.displayStartGamePromptForModerators();
}
});
this.socket.on(globals.EVENT_IDS.NEW_SPECTATOR, (spectator) => {
this.stateBucket.currentGameState.spectators.push(spectator);
});
// this.socket.on(globals.EVENT_IDS.PLAYER_LEFT, (player) => {
// removeStartGameFunctionalityIfPresent(this.stateBucket.currentGameState, this.startGameHandler);
// toast(player.name + ' has left!', 'error', false, true, 'short');
// const index = this.stateBucket.currentGameState.people.findIndex(person => person.id === player.id);
// if (index >= 0) {
// this.stateBucket.currentGameState.people.splice(
// index,
// 1
// );
// this.populatePlayers();
// }
// });
}
displayStartGamePromptForModerators () {
const existingPrompt = document.getElementById('start-game-prompt');
if (existingPrompt) {
enableOrDisableStartButton(this.stateBucket.currentGameState, existingPrompt, this.startGameHandler);
} else {
const newPrompt = document.createElement('div');
newPrompt.setAttribute('id', 'start-game-prompt');
newPrompt.innerHTML = HTMLFragments.START_GAME_PROMPT;
document.body.appendChild(newPrompt);
enableOrDisableStartButton(this.stateBucket.currentGameState, newPrompt, this.startGameHandler);
}
}
removeStartGameFunctionalityIfPresent () {
document.querySelector('#start-game-prompt')?.removeEventListener('click', this.startGameHandler);
document.querySelector('#start-game-prompt')?.remove();
}
}
function enableOrDisableStartButton (gameState, buttonContainer, handler) {
if (gameState.isFull) {
buttonContainer.querySelector('#start-game-button').addEventListener('click', handler);
buttonContainer.querySelector('#start-game-button').classList.remove('disabled');
} else {
buttonContainer.querySelector('#start-game-button').removeEventListener('click', handler);
buttonContainer.querySelector('#start-game-button').classList.add('disabled');
}
}
function activateLink (linkContainer, link) {
const linkCopyHandler = (e) => {
if (e.type === 'click' || e.code === 'Enter') {
navigator.clipboard.writeText(link)
.then(() => {
toast('Link copied!', 'success', true);
});
}
};
linkContainer.addEventListener('click', linkCopyHandler);
linkContainer.addEventListener('keyup', linkCopyHandler);
}
function getTimeString (gameState) {
let timeString = '';
if (gameState.timerParams) {
const hours = gameState.timerParams.hours;
const minutes = gameState.timerParams.minutes;
if (hours) {
timeString += hours > 1
? hours + ' hours '
: hours + ' hour ';
}
if (minutes) {
timeString += minutes > 1
? minutes + ' minutes '
: minutes + ' minute ';
}
return timeString;
} else {
return 'untimed';
}
}
function renderLobbyPerson (name, userType) {
const el = document.createElement('div');
const personNameEl = document.createElement('div');
const personTypeEl = document.createElement('div');
personNameEl.innerText = name;
personTypeEl.innerText = userType + globals.USER_TYPE_ICONS[userType];
el.classList.add('lobby-player');
el.appendChild(personNameEl);
el.appendChild(personTypeEl);
return el;
}