using System.Security.AccessControl; using Microsoft.AspNetCore.SignalR; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Collections.Concurrent; using Sledgemapper.Shared.Entities; using Sledgemapper.Clients; using MediatR; using System; using Sledgemapper.Api.Data; using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.AspNetCore.Authorization; using Sledgemapper.Api.Models; using Sledgemapper.Helpers; namespace SignalRChat.Hubs { [Authorize] public class SledgemapperHub : Hub { private static readonly ConcurrentDictionary UserColors = new ConcurrentDictionary(); private readonly MyDbContext _dbContext; private readonly DataContext _datacontext; public SledgemapperHub(MyDbContext dbContext, DataContext datacontext) { _dbContext = dbContext; _datacontext = datacontext; } // other colors // #cca300, #20f200, #004011, #00e6d6, #005c73, #0057d9, #d900ca, #660029, #d9003a // private static Dictionary _sessions = new Dictionary(); public List Colors = new List{ "#e6194B", "#f58231", "#3cb44b", "#000075", "#911eb4", "#800000", "#808000", "#469990"}; public async Task NewTile(string sessionName, Tile tile) { // var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); // var existingTile = _sessions[sessionName].Map.TryGetValue(tile.ToString(), out var t); // if (existingTile) // { // _sessions[sessionName].Map.TryRemove(t.ToString(), out var rtile); // } // _sessions[sessionName].Map.TryAdd(tile.ToString(), tile); // var jsonString = JsonSerializer.Serialize(tile); // _dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog // { // Operation = "N", // SessionName = sessionName, // Type = "T", // Timestamp = timestamp, // Object = jsonString // }); // await _dbcontext.SaveChangesAsync(); await Clients.Group(sessionName).NewTile(tile); } public async Task NewWall(string sessionName, Wall tile) { // var existingTile = _sessions[sessionName].Walls.TryGetValue(tile.ToString(), out var t); // if (existingTile) // { // _sessions[sessionName].Walls.TryRemove(t.ToString(), out var rtile); // } // _sessions[sessionName].Walls.TryAdd(tile.ToString(), tile); await Clients.Group(sessionName).NewWall(tile); } public async Task NewOverlay(string sessionName, Overlay tile) { // var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); // var existingTile = _sessions[sessionName].Overlays.TryGetValue(tile.ToString(), out var t); // if (existingTile) // { // _sessions[sessionName].Overlays.TryRemove(t.ToString(), out var rtile); // } // _sessions[sessionName].Overlays.TryAdd(tile.ToString(), tile); // var jsonString = JsonSerializer.Serialize(tile); // _dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog // { // Operation = "N", // SessionName = sessionName, // Type = "O", // Timestamp = timestamp, // Object = jsonString // }); // await _dbcontext.SaveChangesAsync(); await Clients.Group(sessionName).NewOverlay(tile); } public async Task DeleteTile(string sessionName, Tile tile) { // _sessions[sessionName].Map.TryRemove(tile.ToString(), out var rtile); await Clients.Group(sessionName).DeleteTile(tile); } public async Task DeleteWall(string sessionName, Wall tile) { //_sessions[sessionName].Walls.TryRemove(tile.ToString(), out var rtile); await Clients.Group(sessionName).DeleteWall(tile); } public async Task DeleteOverlay(string sessionName, Overlay tile) { //_sessions[sessionName].Overlays.TryRemove(tile.ToString(), out var rtile); await Clients.Group(sessionName).DeleteOverlay(tile); } // public async Task NewSession(string sessionName, string initials) // { // var userId = int.Parse(Context.User.Identity.Name); // // var user = this.Context.GetHttpContext().; // var session = new Session(); // session.Colors = new List(Colors); // session.Colors.Shuffle(); // var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[0], Initials = initials }; // session.Players.Add(player); // _sessions.Add(sessionName, session); // await Groups.AddToGroupAsync(Context.ConnectionId, sessionName); // return session; // } public async Task JoinSession(string sessionName) { var session = _dbContext.Sessions.FirstOrDefault(s => s.SessionName == sessionName); var userId = int.Parse(Context.User.Identity.Name); if (session != null) { var userSession = new SessionUser { SessionId = session.SessionId, UserId = userId }; _dbContext.SessionUsers.Add(userSession); await _dbContext.SaveChangesAsync(); await Groups.AddToGroupAsync(Context.ConnectionId, session.SessionName); var user = _datacontext.Users.First(u => u.Id == userId); var player = new Player { UserId = userId, Initials = user.Initials, Position = new Tile { X = 0, Y = 0 }, Color = UserColors[userId] }; await Clients.Group(session.SessionName).NewPlayer(player); await Clients.Group(session.SessionName).RefreshPlayers(); var newSession = new Sledgemapper.Shared.Entities.Session { SessionName = session.SessionName, SessionId = session.SessionId }; return newSession; } else { return null; } // if (_sessions.ContainsKey(sessionName)) // { // var session = _sessions[sessionName]; // var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[session.Players.Count], Initials = initials }; // session.Players.Add(player); // await Clients.Group(sessionName).NewPlayer(player); // return session; // } // else // { // return null; // } } public async Task UpdatePosition(string sessionName, int sessionId, Tile tile) { var userId = int.Parse(Context.User.Identity.Name); //var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionName == sessionName); var SessionUsers = _dbContext.SessionUsers.Where(m => m.SessionId == sessionId).OrderBy(m => m.UserId).ToList(); var user = _datacontext.Users.First(u => u.Id == userId); var player = new Player { UserId = userId, Initials = user.Initials, Position = tile, Color = Colors[SessionUsers.IndexOf(SessionUsers.FirstOrDefault(m => m.UserId == userId))] }; await Clients.Group(sessionName).PlayerUpdate(player); } // public async Task Refresh(string sessionName) // { // return _sessions[sessionName]; // } // public async Task Sync(string sessionName, Session map) // { // _sessions[sessionName].Map = map.Map; // _sessions[sessionName].Overlays = map.Overlays; // _sessions[sessionName].Walls = map.Walls; // await Clients.Group(sessionName).UpdateMap(_sessions[sessionName]); // } public override async Task OnConnectedAsync() { var userId = int.Parse(Context.User.Identity.Name); //var result = _connectedPlayers.AddOrUpdate(Context.ConnectionId, userId,(key, oldValue) => userId); var userConnection = new UserConnection { ConnectionId = Context.ConnectionId, UserId = userId }; _dbContext.UserConnections.Add(userConnection); await _dbContext.SaveChangesAsync(); var availableColor = Colors.Where(m => !UserColors.Values.Contains(m)).First(); UserColors.AddOrUpdate(userId, availableColor, (key, oldValue) => availableColor); await base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception exception) { var userConnection = _dbContext.UserConnections.FirstOrDefault(m => m.ConnectionId == Context.ConnectionId); if (userConnection != null) { _dbContext.UserConnections.Remove(userConnection); } var userSessions = _dbContext.SessionUsers.Where(m => m.UserId == userConnection.UserId).ToList(); { foreach (var userSession in userSessions) { var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionId == userSession.SessionId); await Clients.Group(session.SessionName).PlayerUpdate(null); //send remove player _dbContext.SessionUsers.Remove(userSession); } } await _dbContext.SaveChangesAsync(); await base.OnDisconnectedAsync(exception); } } }