This repository has been archived by the owner on Dec 18, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 446
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
246 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.SignalR; | ||
|
||
namespace SocketsSample.Hubs | ||
{ | ||
public class GameLogic | ||
{ | ||
private readonly HashSet<string> _connections = new HashSet<string>(); | ||
private bool _gameRunning; | ||
private readonly IHubContext<Game> _hubContext; | ||
private Task _gameTask; | ||
|
||
public GameLogic(IHubContext<Game> hubContext) | ||
{ | ||
_hubContext = hubContext; | ||
} | ||
|
||
public void RemoveConnection(string connectionId) | ||
{ | ||
lock (_connections) | ||
{ | ||
_connections.Remove(connectionId); | ||
} | ||
} | ||
|
||
public void AddConnection(string connectionId) | ||
{ | ||
lock (_connections) | ||
{ | ||
_connections.Add(connectionId); | ||
|
||
if (_connections.Count == 2 && !_gameRunning) | ||
{ | ||
_gameTask = RunGame(); | ||
} | ||
} | ||
} | ||
|
||
private async Task RunGame() | ||
{ | ||
_gameRunning = true; | ||
|
||
// Start the game on all clients | ||
var winner = await Task.WhenAny(InvokeOnAll("Ask")); | ||
|
||
var result = await winner; | ||
|
||
var ignore = _hubContext.Clients.Client(result.ConnectionId).InvokeAsync("Send", "You win :)"); | ||
|
||
foreach (var item in _connections) | ||
{ | ||
if (item == result.ConnectionId) | ||
{ | ||
continue; | ||
} | ||
|
||
ignore = _hubContext.Clients.Client(item).InvokeAsync("Send", "You lose :("); | ||
} | ||
} | ||
|
||
private Task<Result>[] InvokeOnAll(string method, params object[] args) | ||
{ | ||
Task<Result>[] tasks; | ||
lock (_connections) | ||
{ | ||
tasks = new Task<Result>[_connections.Count]; | ||
|
||
int i = 0; | ||
foreach (var id in _connections) | ||
{ | ||
tasks[i++] = Invoke(id, method, args); | ||
} | ||
} | ||
|
||
return tasks; | ||
} | ||
|
||
private async Task<Result> Invoke(string id, string method, object[] args) | ||
{ | ||
|
||
return new Result | ||
{ | ||
Value = await _hubContext.Clients.Client(id).InvokeAsync(method, args), | ||
ConnectionId = id | ||
}; | ||
} | ||
|
||
private class Result | ||
{ | ||
public object Value { get; set; } | ||
public string ConnectionId { get; set; } | ||
} | ||
} | ||
|
||
public class Game : Hub | ||
{ | ||
private readonly GameLogic _gameLogic; | ||
|
||
public Game(GameLogic gameLogic) | ||
{ | ||
_gameLogic = gameLogic; | ||
} | ||
|
||
public override Task OnConnectedAsync() | ||
{ | ||
_gameLogic.AddConnection(Context.ConnectionId); | ||
return base.OnConnectedAsync(); | ||
} | ||
|
||
public override Task OnDisconnectedAsync(Exception exception) | ||
{ | ||
_gameLogic.RemoveConnection(Context.ConnectionId); | ||
return base.OnDisconnectedAsync(exception); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<title></title> | ||
</head> | ||
<body> | ||
<h1 id="head1"></h1> | ||
|
||
<input type="button" id="game" value="Click me!" disabled="disabled" /> | ||
|
||
<ul id="messages"></ul> | ||
</body> | ||
</html> | ||
<script src="lib/signalr-client/signalr-client.js"></script> | ||
<script> | ||
var isConnected = false; | ||
function getParameterByName(name, url) { | ||
if (!url) { | ||
url = window.location.href; | ||
} | ||
name = name.replace(/[\[\]]/g, "\\$&"); | ||
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), | ||
results = regex.exec(url); | ||
if (!results) return null; | ||
if (!results[2]) return ''; | ||
return decodeURIComponent(results[2].replace(/\+/g, " ")); | ||
} | ||
|
||
function click(id, callback) { | ||
document.getElementById(id).addEventListener('click', event => { | ||
callback(event); | ||
event.preventDefault(); | ||
}); | ||
} | ||
|
||
function addLine(line, color) { | ||
var child = document.createElement('li'); | ||
if (color) { | ||
child.style.color = color; | ||
} | ||
child.innerText = line; | ||
document.getElementById('messages').appendChild(child); | ||
} | ||
|
||
function invoke(connection, method, ...args) { | ||
if (!isConnected) { | ||
return; | ||
} | ||
var argsArray = Array.prototype.slice.call(arguments); | ||
connection.invoke.apply(connection, argsArray.slice(1)) | ||
.then(result => { | ||
console.log("invocation completed successfully: " + (result === null ? '(null)' : result)); | ||
|
||
if (result) { | ||
addLine(result); | ||
} | ||
}) | ||
.catch(err => { | ||
addLine(err, 'red'); | ||
}); | ||
} | ||
|
||
let transport = getParameterByName('transport') || 'webSockets'; | ||
|
||
document.getElementById('head1').innerHTML = transport; | ||
|
||
let connection = new signalR.HubConnection(`http://${document.location.host}/game`, 'formatType=json&format=text'); | ||
|
||
var currentQuestion = { | ||
resolve: function () { }, | ||
reject: function() { } | ||
}; | ||
|
||
connection.on('Ask', (a, b) => { | ||
document.getElementById('game').removeAttribute('disabled'); | ||
return new Promise(function (resolve, reject) { | ||
currentQuestion.resolve = resolve; | ||
currentQuestion.reject = reject; | ||
}); | ||
}); | ||
|
||
connection.on('Send', data => { | ||
alert(data); | ||
}); | ||
|
||
|
||
connection.connectionClosed = e => { | ||
if (e) { | ||
addLine('Connection closed with error: ' + e, 'red'); | ||
} | ||
else { | ||
addLine('Disconnected', 'green'); | ||
} | ||
} | ||
|
||
click('game', event => { | ||
currentQuestion.resolve(); | ||
}); | ||
|
||
connection.start(transport); | ||
|
||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Turns out we should've used a "type guard" here: https://www.typescriptlang.org/docs/handbook/advanced-types.html