feat: add signalr hub and github workflow
This commit is contained in:
39
.github/workflows/tetriscloneapp.yml
vendored
Normal file
39
.github/workflows/tetriscloneapp.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Build and deploy .NET Core application to Web App tetriscloneapp
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
env:
|
||||
AZURE_WEBAPP_NAME: tetriscloneapp
|
||||
AZURE_WEBAPP_PACKAGE_PATH: TetrisClone.WebApi/publish
|
||||
CONFIGURATION: Release
|
||||
DOTNET_CORE_VERSION: 6.0.x
|
||||
WORKING_DIRECTORY: TetrisClone.WebApi
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-dotnet@v1.8.0
|
||||
with:
|
||||
include-prerelease: True
|
||||
dotnet-version: ${{ env.DOTNET_CORE_VERSION }}
|
||||
- name: Restore
|
||||
run: dotnet restore "${{ env.WORKING_DIRECTORY }}"
|
||||
- name: Build
|
||||
run: dotnet build "${{ env.WORKING_DIRECTORY }}" --configuration ${{ env.CONFIGURATION }} --no-restore
|
||||
- name: Test
|
||||
run: dotnet test "${{ env.WORKING_DIRECTORY }}" --no-build
|
||||
- name: Publish
|
||||
run: dotnet publish "${{ env.WORKING_DIRECTORY }}" --configuration ${{ env.CONFIGURATION }} --no-build --output "${{ env.AZURE_WEBAPP_PACKAGE_PATH }}"
|
||||
- name: Deploy to Azure WebApp
|
||||
uses: azure/webapps-deploy@v2
|
||||
with:
|
||||
app-name: ${{ env.AZURE_WEBAPP_NAME }}
|
||||
publish-profile: ${{ secrets.TETRISCLONEAPP_FFFF }}
|
||||
package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
|
||||
- name: Publish Artifacts
|
||||
uses: actions/upload-artifact@v1.0.0
|
||||
with:
|
||||
name: webapp
|
||||
path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
|
||||
27
TetrisClone.WebApi/Controllers/TetrisController.cs
Normal file
27
TetrisClone.WebApi/Controllers/TetrisController.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TetrisClone.WebApi.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class TetrisController : ControllerBase
|
||||
{
|
||||
private readonly ILogger<TetrisController> _logger;
|
||||
|
||||
public TetrisController(ILogger<TetrisController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult Get()
|
||||
{
|
||||
return new EmptyResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
46
TetrisClone.WebApi/Hubs/PlayerHub.cs
Normal file
46
TetrisClone.WebApi/Hubs/PlayerHub.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using TetrisClone.WebApi.Model;
|
||||
|
||||
namespace TetrisClone.WebApi.Hubs
|
||||
{
|
||||
public class PlayerHub : Hub
|
||||
{
|
||||
public ConcurrentDictionary<string, List<string>> Games { get; set; }
|
||||
|
||||
private const int PLAYERS_PER_GAME = 2;
|
||||
|
||||
/*
|
||||
TODO: Fix assumption that there will only ever be two players connecting using same uniqueString
|
||||
*/
|
||||
public async Task EnterGame(string gameId)
|
||||
{
|
||||
if (Games.Keys.Any(x => x == gameId))
|
||||
Games[gameId].Add(Context.ConnectionId);
|
||||
else
|
||||
Games[gameId] = new List<string> { Context.ConnectionId };
|
||||
|
||||
if (Games[gameId].Count != PLAYERS_PER_GAME)
|
||||
await Clients
|
||||
.Clients(Games[gameId])
|
||||
.SendAsync("StartGame");
|
||||
|
||||
await Clients
|
||||
.Clients(Games[gameId])
|
||||
.SendAsync("WaitForOpponent");
|
||||
}
|
||||
|
||||
public async Task SendCurrentPiece(string gameId, Piece piece)
|
||||
{
|
||||
if (Games.Keys.All(x => x != gameId))
|
||||
return;
|
||||
|
||||
await Clients
|
||||
.Clients(Games[gameId].First(x => x != Context.ConnectionId))
|
||||
.SendAsync("GetOpponentPiece");
|
||||
}
|
||||
}
|
||||
}
|
||||
14
TetrisClone.WebApi/Model/Piece.cs
Normal file
14
TetrisClone.WebApi/Model/Piece.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TetrisClone.WebApi.Model
|
||||
{
|
||||
public class Piece
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public PieceType Type { get; set; }
|
||||
}
|
||||
}
|
||||
18
TetrisClone.WebApi/Model/PieceType.cs
Normal file
18
TetrisClone.WebApi/Model/PieceType.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TetrisClone.WebApi.Model
|
||||
{
|
||||
public enum PieceType
|
||||
{
|
||||
I,
|
||||
J,
|
||||
L,
|
||||
O,
|
||||
S,
|
||||
T,
|
||||
Z
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"metadata": {
|
||||
"_dependencyType": "appService.linux"
|
||||
},
|
||||
"parameters": {
|
||||
"resourceGroupName": {
|
||||
"type": "string",
|
||||
"defaultValue": "development",
|
||||
"metadata": {
|
||||
"description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking."
|
||||
}
|
||||
},
|
||||
"resourceGroupLocation": {
|
||||
"type": "string",
|
||||
"defaultValue": "eastus",
|
||||
"metadata": {
|
||||
"description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support."
|
||||
}
|
||||
},
|
||||
"resourceName": {
|
||||
"type": "string",
|
||||
"defaultValue": "tetriscloneapp",
|
||||
"metadata": {
|
||||
"description": "Name of the main resource to be created by this template."
|
||||
}
|
||||
},
|
||||
"resourceLocation": {
|
||||
"type": "string",
|
||||
"defaultValue": "[parameters('resourceGroupLocation')]",
|
||||
"metadata": {
|
||||
"description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there."
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]",
|
||||
"appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Resources/resourceGroups",
|
||||
"name": "[parameters('resourceGroupName')]",
|
||||
"location": "[parameters('resourceGroupLocation')]",
|
||||
"apiVersion": "2019-10-01"
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Resources/deployments",
|
||||
"name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]",
|
||||
"resourceGroup": "[parameters('resourceGroupName')]",
|
||||
"apiVersion": "2019-10-01",
|
||||
"dependsOn": [
|
||||
"[parameters('resourceGroupName')]"
|
||||
],
|
||||
"properties": {
|
||||
"mode": "Incremental",
|
||||
"template": {
|
||||
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"resources": [
|
||||
{
|
||||
"location": "[parameters('resourceLocation')]",
|
||||
"name": "[parameters('resourceName')]",
|
||||
"type": "Microsoft.Web/sites",
|
||||
"apiVersion": "2015-08-01",
|
||||
"tags": {
|
||||
"[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[variables('appServicePlan_ResourceId')]"
|
||||
],
|
||||
"kind": "app",
|
||||
"properties": {
|
||||
"name": "[parameters('resourceName')]",
|
||||
"kind": "app",
|
||||
"httpsOnly": true,
|
||||
"reserved": false,
|
||||
"serverFarmId": "[variables('appServicePlan_ResourceId')]",
|
||||
"siteConfig": {
|
||||
"linuxFxVersion": "DOTNETCORE|2.1"
|
||||
}
|
||||
},
|
||||
"identity": {
|
||||
"type": "SystemAssigned"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"name": "appsettings",
|
||||
"type": "config",
|
||||
"apiVersion": "2015-08-01",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.Web/Sites/', parameters('resourceName'))]"
|
||||
],
|
||||
"properties": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"location": "[parameters('resourceLocation')]",
|
||||
"name": "[variables('appServicePlan_name')]",
|
||||
"type": "Microsoft.Web/serverFarms",
|
||||
"apiVersion": "2015-02-01",
|
||||
"kind": "linux",
|
||||
"properties": {
|
||||
"name": "[variables('appServicePlan_name')]",
|
||||
"sku": "Standard",
|
||||
"workerSizeId": "0",
|
||||
"reserved": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -11,6 +11,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using TetrisClone.WebApi.Hubs;
|
||||
|
||||
namespace TetrisClone.WebApi
|
||||
{
|
||||
@@ -26,8 +27,8 @@ namespace TetrisClone.WebApi
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
|
||||
services.AddControllers();
|
||||
services.AddSignalR();
|
||||
services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "TetrisClone.WebApi", Version = "v1" });
|
||||
@@ -53,6 +54,7 @@ namespace TetrisClone.WebApi
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
endpoints.MapHub<PlayerHub>("/player");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user