Skip to content

Commit

Permalink
WIP: Add player presence tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
ThunderDev1 committed Dec 4, 2019
1 parent defb60d commit 102a9f8
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 131 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
11 changes: 11 additions & 0 deletions client/src/components/PlayerBox/PlayerBox.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import 'styles/variables';

$background-color: rgb(37, 153, 138);

.PlayerBox {
border: 2px solid black;
background-color: $background-color;
color: white;
padding: 1rem;
min-width: 10rem;
}
23 changes: 23 additions & 0 deletions client/src/components/PlayerBox/PlayerBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { FC } from 'react'

import './PlayerBox.scss'

export interface PlayerProps {
name: string
isHost: boolean
isSelf: boolean
}

const Player: FC<PlayerProps> = (props: PlayerProps) => {
return (
<div className='PlayerBox'>
<div>
<h3>{props.name}</h3>
</div>
{props.isHost && <h4>Host</h4>}
{props.isSelf && '(this is you)'}
</div>
)
}

export default Player
2 changes: 2 additions & 0 deletions client/src/components/PlayerBox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './PlayerBox'
export { default } from './PlayerBox'
87 changes: 22 additions & 65 deletions client/src/pages/Lobby/Lobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,107 +4,64 @@ import { RouteComponentProps } from '@reach/router'
import { Game } from '../../types/Game'
import * as moment from 'moment'

import connectToHub from '../../utils/signalrConnector'
import connectToGameHub from '../../utils/signalrConnector'

import './Lobby.scss'
import { HubConnection } from '@microsoft/signalr'
import Button from '../../components/Button'
import { Player } from '../../types/Player'
import PlayerBox from '../../components/PlayerBox'

export interface LobbyProps extends RouteComponentProps {
id?: string
}

const Lobby: FC<LobbyProps> = (props: LobbyProps) => {
const [game, setGame] = useState<Game>()
const [hubConnection, setHubConnection] = useState<HubConnection>()
const [gameHost, setGameHost] = useState<Player>()
const [currentPlayer, setCurrentPlayer] = useState<Player>()
const [currentPlayerId, setCurrentPlayerId] = useState<string>()

useEffect(() => {
const onLoad = async () => {
const loadGame = async () => {
const getGameResponse: AxiosResponse<Game> = await axios.get(
`/games/${props.id}`
)
const game = getGameResponse.data
return game
}
const onLoad = async () => {
var game = await loadGame()
setGame(game)

if (game.status === 'PENDING_START') {
// consider player in the game if playerId is found in storage
// could be either game host or player refreshing window
let playerId = localStorage.getItem(`poule-poule-${game.id}`)
let newPlayer = null
if (!playerId) {
// first visit, join the game
const { data: player } = await axios.post(
`/games/${props.id}/players`
)

localStorage.setItem(`poule-poule-${game.id}`, player.id)
playerId = player.id
newPlayer = player
}

// connect to hub
if (playerId) {
const hubConnection = connectToHub('gameHub', playerId)

hubConnection.on('playerJoined', (player: Player) => {
const updatedGame = {
...game,
players: game.players.concat(player)
}
setGame(updatedGame)
})
setHubConnection(hubConnection)
const gameHost = game.players.find(
player => player.id === game.hostId
)
setGameHost(gameHost)

setCurrentPlayer(
newPlayer || game.players.find(player => player.id === playerId)
)
}
const hubConnection = connectToGameHub(game.id)
hubConnection.start().then(() => {
hubConnection.connectionId &&
setCurrentPlayerId(hubConnection.connectionId)
})
hubConnection.on('refreshGame', () => {
loadGame().then(game => setGame(game))
})
}
}

onLoad()
}, [props.id])

const getSubtitle = (game: Game) => {
let creator = ''
if (currentPlayer && gameHost && currentPlayer.id === gameHost.id)
creator = 'vous'
else creator = (gameHost && gameHost.name) || ''
return `Créé par ${creator} ${moment.utc(game.creationDate).fromNow()}`
}

return (
<div className='Lobby'>
{game && (
<>
<h1>Details de la partie ({game.id})</h1>
<h2>{getSubtitle(game)}</h2>
<h2>{`Créé ${moment.utc(game.creationDate).fromNow()}`}</h2>
<h3>Statut {game.status}</h3>
<br></br>
<h4>Joueurs</h4>
<div className='Players'>
{game.players.map(player => (
<div className='Player' title={player.id} key={player.id}>
{player.name} - {game.hostId === player.id ? '(host)' : ''} -
{currentPlayer && currentPlayer.id === player.id ? '(you)' : ''}
</div>
<PlayerBox
name={player.name}
isSelf={currentPlayerId === player.id || false}
isHost={game.hostId === player.id}
/>
))}
</div>
{hubConnection &&
currentPlayer &&
currentPlayer.id === game.hostId &&
game.status === 'PENDING_START' && (
<Button primary onClick={() => hubConnection.invoke('StartGame')}>
Commencer la partie
</Button>
)}
</>
)}
</div>
Expand Down
17 changes: 8 additions & 9 deletions client/src/utils/signalrConnector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,22 @@ import { HubConnection } from '@microsoft/signalr'

const API_URL: string = 'https://localhost:5001'

const connectToHub = (
hubName: string,
playerId: string,
const connectToGameHub = (
gameId: number,
onStart: any = null
): HubConnection => {
const connection = new SignalR.HubConnectionBuilder()
.withUrl(`${API_URL}/${hubName}?playerId=${playerId}`)
.withUrl(`${API_URL}/gameHub?gameId=${gameId}`)
.withAutomaticReconnect()
.configureLogging(SignalR.LogLevel.Debug)
.build()

connection
.start()
.then(() => onStart && onStart())
.catch(err => console.log(err))
// connection
// .start()
// .then(() => onStart && onStart())
// .catch(err => console.log(err))

return connection
}

export default connectToHub
export default connectToGameHub
1 change: 0 additions & 1 deletion server/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*.user
*.userosscache
*.sln.docstates
.vscode

# Build results
[Dd]ebug/
Expand Down
50 changes: 0 additions & 50 deletions server/Data/random-names.txt

This file was deleted.

50 changes: 50 additions & 0 deletions server/Data/video-game-characters.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
Ryu Hayabusa
Dirk The Daring
Donkey Kong
The Horned Reaper
Vault Boy
Marcus Fenix
Leon Kennedy
HK-47
Sam & Max
Pyramid Head
Dr Fred Eddison
Mr. X
Dante
Pac Man
Big Daddy
Prince of Persia
Alucard
The Announcer
Miner Willy
Kane
Manny Cavalera
Garrett
Harman Smith
Ryu
Samus Aran
Arthas Menethil
Sabre Man
Bowser
Nathan Drake
Agent 47
Duke Nukem
Solid Snake
American McGee's Alice
Illidan Stormrage
Brucie
Kratos
Sonic
Cloud Strife
GLaDOS
Minsc & Boo
Sephiroth
The Lemmings
Master Chief
Guybrush Threepwood
Link
Lara Croft
The Nameless One
Shodan
Mario
Gordon Freeman
36 changes: 36 additions & 0 deletions server/Hubs/GameHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,45 @@ public GameHub(IGameService gameService)
_gameService = gameService;
}

private string GetPlayerId()
{
return Context.ConnectionId;
}

private int GetGameId()
{
int gameId = 0;
if (!int.TryParse(Context.GetHttpContext().Request.Query["gameId"], out gameId))
throw new InvalidOperationException("Game id is missing from query string");

return gameId;
}

public override Task OnConnectedAsync()
{
string playerId = GetPlayerId();
int gameId = GetGameId();
string groupName = "game-" + gameId;

_gameService.AddPlayer(gameId, playerId);

Groups.AddToGroupAsync(Context.ConnectionId, groupName);
Clients.Group(groupName).SendAsync("refreshGame");

return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
string playerId = GetPlayerId();
int gameId = GetGameId();
string groupName = "game-" + gameId;

Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
_gameService.RemovePlayer(playerId);

Clients.Group(groupName).SendAsync("refreshGame");

return base.OnDisconnectedAsync(exception);
}
}
}
Loading

0 comments on commit 102a9f8

Please sign in to comment.