From 7e3e645fc9fcc940cd818814f5aba6e334b6f8b1 Mon Sep 17 00:00:00 2001 From: Michele Scandura Date: Tue, 21 Sep 2021 11:09:26 +0100 Subject: [PATCH] fixes and cleanup --- .../Commands/DeleteNoteCommand.cs | 3 +- .../Commands/DeleteOverlayCommand.cs | 5 +- .../Commands/DeleteWallCommand.cs | 3 +- .../Controllers/AuthManagementController.cs | 2 +- .../Controllers/CampaignController.cs | 8 +- Sledgemapper.Api/Controllers/MapController.cs | 58 +- Sledgemapper.Api/Core/Entities/MapLog.cs | 4 +- Sledgemapper.Api/Core/Entities/Session.cs | 4 +- Sledgemapper.Api/Core/Entities/SessionUser.cs | 2 +- Sledgemapper.Api/Core/Entities/Snapshot.cs | 2 +- Sledgemapper.Api/Core/Entities/User.cs | 6 +- .../Core/Entities/UserConnection.cs | 4 +- .../Handlers/BaseCommandHandler.cs | 24 +- .../Handlers/GetMapSnapshotCommandHandler.cs | 21 +- .../Handlers/NewLineCommandHandler.cs | 2 +- .../Handlers/NewSnapshotCommandHandler.cs | 20 +- .../Handlers/NewTileCommandHandler.cs | 6 +- .../Handlers/NewWallCommandHandler.cs | 2 +- .../Handlers/PingCommandHandler.cs | 28 - .../Handlers/SendDeleteNoteMessage.cs | 2 +- .../Handlers/SendDeleteOverlayMessage.cs | 2 +- .../Handlers/SendDeleteTileMessage.cs | 2 +- .../Handlers/SendDeleteWallMessage.cs | 2 +- Sledgemapper.Api/Handlers/SendPingMessage.cs | 23 - .../Handlers/StartNewSessionHandler.cs | 5 +- Sledgemapper.Api/Helpers/AppException.cs | 6 +- Sledgemapper.Api/Helpers/AutoMapperProfile.cs | 2 +- Sledgemapper.Api/Hubs/SledgemapperHub.cs | 36 +- Sledgemapper.Api/Models/AuthResult.cs | 2 +- Sledgemapper.Api/Models/AuthenticateModel.cs | 2 +- Sledgemapper.Api/Models/RegisterModel.cs | 2 +- .../Models/RegistrationResponse.cs | 4 +- Sledgemapper.Api/Models/UserLoginRequest.cs | 2 +- .../Clients/ISledgemapperClient.cs | 3 +- Sledgemapper.Shared/ExtensionMethods.cs | 4 +- .../ObservableConcurrentDictionary.cs | 4 +- Sledgemapper.sln.DotSettings | 2 + Sledgemapper/CommunicationManager.cs | 260 +- Sledgemapper/IMapApi.cs | 16 +- Sledgemapper/Settings.cs | 2 +- Sledgemapper/Sledgemapper.cs | 2468 +++++++++-------- Sledgemapper/State.cs | 2 +- Sledgemapper/UI/CampaignWindow.Custom.cs | 1 - Sledgemapper/UI/MainWidget.Custom.cs | 1 - Sledgemapper/UI/MapList.Custom.cs | 1 - Sledgemapper/UI/MapWindow.cs | 3 - Sledgemapper/UI/NoteList.Custom.cs | 3 +- Sledgemapper/UI/PlayerList.Custom.cs | 2 +- 48 files changed, 1530 insertions(+), 1538 deletions(-) delete mode 100644 Sledgemapper.Api/Handlers/PingCommandHandler.cs delete mode 100644 Sledgemapper.Api/Handlers/SendPingMessage.cs create mode 100644 Sledgemapper.sln.DotSettings diff --git a/Sledgemapper.Api/Commands/DeleteNoteCommand.cs b/Sledgemapper.Api/Commands/DeleteNoteCommand.cs index fe8000d..c60bfb0 100644 --- a/Sledgemapper.Api/Commands/DeleteNoteCommand.cs +++ b/Sledgemapper.Api/Commands/DeleteNoteCommand.cs @@ -1,3 +1,4 @@ +using System; using Sledgemapper.Shared.Entities; namespace Sledgemapper.Api.Commands @@ -6,7 +7,7 @@ namespace Sledgemapper.Api.Commands { public Note Note { get; private set; } - public DeleteNoteCommand(string sessionName, Note note, string userId) : base(sessionName, userId) + public DeleteNoteCommand(Guid campaign, Guid mapName, Note note, string userId) : base(campaign, mapName, userId) { Note = note; } diff --git a/Sledgemapper.Api/Commands/DeleteOverlayCommand.cs b/Sledgemapper.Api/Commands/DeleteOverlayCommand.cs index e3cde01..abd504d 100644 --- a/Sledgemapper.Api/Commands/DeleteOverlayCommand.cs +++ b/Sledgemapper.Api/Commands/DeleteOverlayCommand.cs @@ -1,12 +1,13 @@ +using System; using Sledgemapper.Shared.Entities; namespace Sledgemapper.Api.Commands { - public class DeleteOverlayCommand : BaseCommand + public class DeleteOverlayCommand : BaseCommand { public Overlay Overlay { get; private set; } - public DeleteOverlayCommand(string sessionName, Overlay overlay, string userId) : base(sessionName, userId) + public DeleteOverlayCommand(Guid campaign, Guid mapName, Overlay overlay, string userId) : base(campaign, mapName, userId) { Overlay = overlay; } diff --git a/Sledgemapper.Api/Commands/DeleteWallCommand.cs b/Sledgemapper.Api/Commands/DeleteWallCommand.cs index 454af3e..4b38b77 100644 --- a/Sledgemapper.Api/Commands/DeleteWallCommand.cs +++ b/Sledgemapper.Api/Commands/DeleteWallCommand.cs @@ -1,3 +1,4 @@ +using System; using Sledgemapper.Shared.Entities; namespace Sledgemapper.Api.Commands @@ -6,7 +7,7 @@ namespace Sledgemapper.Api.Commands { public Wall Wall { get; private set; } - public DeleteWallCommand(string sessionName, Wall wall, string userId) : base(sessionName, userId) + public DeleteWallCommand(Guid campaign, Guid mapName, Wall wall, string userId) : base(campaign, mapName, userId) { Wall = wall; } diff --git a/Sledgemapper.Api/Controllers/AuthManagementController.cs b/Sledgemapper.Api/Controllers/AuthManagementController.cs index d92a69c..584319a 100644 --- a/Sledgemapper.Api/Controllers/AuthManagementController.cs +++ b/Sledgemapper.Api/Controllers/AuthManagementController.cs @@ -162,7 +162,7 @@ namespace Sledgemapper.Api.Controllers Subject = new ClaimsIdentity(new[] { - new Claim("Id", user.Id.ToString()), + new Claim("Id", user.Id), new Claim(JwtRegisteredClaimNames.Sub, user.Email), new Claim(JwtRegisteredClaimNames.Email, user.Email), // the JTI is used for our refresh token which we will be convering in the next video diff --git a/Sledgemapper.Api/Controllers/CampaignController.cs b/Sledgemapper.Api/Controllers/CampaignController.cs index 44811fd..6c0313f 100644 --- a/Sledgemapper.Api/Controllers/CampaignController.cs +++ b/Sledgemapper.Api/Controllers/CampaignController.cs @@ -24,7 +24,7 @@ namespace Sledgemapper.Api.Controllers [Route("{campaignName}")] public async Task> Post(string campaignName) { - var result = await _mediator.Send(new NewCampaignCommand(campaignName, UserId.ToString())); + var result = await _mediator.Send(new NewCampaignCommand(campaignName, UserId)); if (!result) { return BadRequest(); @@ -51,7 +51,7 @@ namespace Sledgemapper.Api.Controllers [Route("{campaignName}/players/{email}")] public async Task Invite(string campaignName, string email) { - var result = await _mediator.Send(new InvitePlayerToCampaignCommand(campaignName, email, UserId.ToString())); + var result = await _mediator.Send(new InvitePlayerToCampaignCommand(campaignName, email, UserId)); return result; } @@ -59,7 +59,7 @@ namespace Sledgemapper.Api.Controllers [Route("{campaignName}/players")] public async Task> GetPlayers(string campaignName) { - var result = await _mediator.Send(new GetCampaignPlayersCommand(campaignName, UserId.ToString())); + var result = await _mediator.Send(new GetCampaignPlayersCommand(campaignName, UserId)); return result; } @@ -68,7 +68,7 @@ namespace Sledgemapper.Api.Controllers [Route("{campaignName}/maps")] public async Task> GetMaps(Guid campaignName) { - var result = await _mediator.Send(new GetCampaignMapsCommand(campaignName, UserId.ToString())); + var result = await _mediator.Send(new GetCampaignMapsCommand(campaignName, UserId)); return result; } diff --git a/Sledgemapper.Api/Controllers/MapController.cs b/Sledgemapper.Api/Controllers/MapController.cs index e1ab9d3..683f84a 100644 --- a/Sledgemapper.Api/Controllers/MapController.cs +++ b/Sledgemapper.Api/Controllers/MapController.cs @@ -1,11 +1,11 @@ +using System; +using System.Linq; +using System.Threading.Tasks; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Sledgemapper.Api.Commands; using Sledgemapper.Shared.Entities; -using System; -using System.Linq; -using System.Threading.Tasks; namespace Sledgemapper.Api.Controllers { @@ -14,15 +14,30 @@ namespace Sledgemapper.Api.Controllers public class MapController : ControllerBase { private readonly IMediator _mediator; + + public MapController(IMediator mediator) + { + _mediator = mediator; + } + private string UserId => HttpContext.User.Claims.FirstOrDefault(m => m.Type == "Id").Value; - public MapController(IMediator mediator) => _mediator = mediator; - - [HttpPost] - public async Task Post(string campaign, string mapName) + [HttpDelete("overlay")] + public async Task Delete(Guid campaign, Guid mapName, [FromBody] Overlay overlay) { - var result = await _mediator.Send(new NewSessionCommand(campaign, mapName, UserId)); - return result; + await _mediator.Send(new DeleteOverlayCommand(campaign, mapName, overlay, UserId)); + } + + [HttpDelete("wall")] + public async Task Delete(Guid campaign, Guid mapName, [FromBody] Wall wall) + { + await _mediator.Send(new DeleteWallCommand(campaign, mapName, wall, UserId)); + } + + [HttpDelete("note")] + public async Task Delete(Guid campaign, Guid mapName, [FromBody] Note note) + { + await _mediator.Send(new DeleteNoteCommand(campaign, mapName, note, UserId)); } [HttpGet] @@ -32,6 +47,13 @@ namespace Sledgemapper.Api.Controllers return result; } + [HttpPost] + public async Task Post(string campaign, string mapName) + { + var result = await _mediator.Send(new NewSessionCommand(campaign, mapName, UserId)); + return result; + } + [HttpPost("snapshot")] public async Task Post(string campaign, string mapName, [FromBody] Session session) { @@ -67,23 +89,5 @@ namespace Sledgemapper.Api.Controllers { await _mediator.Send(new NewLineCommand(campaign, mapName, line, UserId)); } - - [HttpDelete("overlay")] - public async Task Delete(string campaign, string mapName, [FromBody] Overlay overlay) - { - await _mediator.Send(new DeleteOverlayCommand(mapName, overlay, UserId)); - } - - [HttpDelete("wall")] - public async Task Delete(string campaign, string mapName, [FromBody] Wall wall) - { - await _mediator.Send(new DeleteWallCommand(mapName, wall, UserId)); - } - - [HttpDelete("note")] - public async Task Delete(string campaign, string mapName, [FromBody] Note note) - { - await _mediator.Send(new DeleteNoteCommand(mapName, note, UserId)); - } } } \ No newline at end of file diff --git a/Sledgemapper.Api/Core/Entities/MapLog.cs b/Sledgemapper.Api/Core/Entities/MapLog.cs index ea70dc1..4d004f6 100644 --- a/Sledgemapper.Api/Core/Entities/MapLog.cs +++ b/Sledgemapper.Api/Core/Entities/MapLog.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace Sledgemapper.Api.Models +namespace Sledgemapper.Api.Core.Entities { public class MapLog @@ -10,7 +10,7 @@ namespace Sledgemapper.Api.Models public int MapLogId { get; set; } [Required] - public string UserId{get;set;} + public string UserId { get; set; } [Required] public Guid SessionId { get; set; } diff --git a/Sledgemapper.Api/Core/Entities/Session.cs b/Sledgemapper.Api/Core/Entities/Session.cs index 98daf68..52029db 100644 --- a/Sledgemapper.Api/Core/Entities/Session.cs +++ b/Sledgemapper.Api/Core/Entities/Session.cs @@ -3,7 +3,7 @@ using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace Sledgemapper.Api.Models +namespace Sledgemapper.Api.Core.Entities { [Index(nameof(CampaignId), nameof(SessionName), IsUnique = true)] public class Session @@ -13,7 +13,7 @@ namespace Sledgemapper.Api.Models public Guid SessionId { get; set; } [Required] - public Guid CampaignId { get; set; } + public Guid CampaignId { get; set; } [Required] public string SessionName { get; set; } diff --git a/Sledgemapper.Api/Core/Entities/SessionUser.cs b/Sledgemapper.Api/Core/Entities/SessionUser.cs index 98860ed..b2136c0 100644 --- a/Sledgemapper.Api/Core/Entities/SessionUser.cs +++ b/Sledgemapper.Api/Core/Entities/SessionUser.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace Sledgemapper.Api.Models +namespace Sledgemapper.Api.Core.Entities { public class SessionUser { diff --git a/Sledgemapper.Api/Core/Entities/Snapshot.cs b/Sledgemapper.Api/Core/Entities/Snapshot.cs index 2f9b797..2a577e2 100644 --- a/Sledgemapper.Api/Core/Entities/Snapshot.cs +++ b/Sledgemapper.Api/Core/Entities/Snapshot.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace Sledgemapper.Api.Models +namespace Sledgemapper.Api.Core.Entities { public class Snapshot diff --git a/Sledgemapper.Api/Core/Entities/User.cs b/Sledgemapper.Api/Core/Entities/User.cs index bd4993f..bc29784 100644 --- a/Sledgemapper.Api/Core/Entities/User.cs +++ b/Sledgemapper.Api/Core/Entities/User.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Identity; -namespace Sledgemapper.Entities +namespace Sledgemapper.Api.Core.Entities { - public class User:IdentityUser + public class User : IdentityUser { // public int Id { get; set; } public string FirstName { get; set; } @@ -13,6 +13,6 @@ namespace Sledgemapper.Entities public string Initials { get; set; } // public byte[] PasswordHash { get; set; } public byte[] PasswordSalt { get; set; } - public ICollection Campaigns {get;set;} + public ICollection Campaigns { get; set; } } } \ No newline at end of file diff --git a/Sledgemapper.Api/Core/Entities/UserConnection.cs b/Sledgemapper.Api/Core/Entities/UserConnection.cs index 74c0ce8..17e34a3 100644 --- a/Sledgemapper.Api/Core/Entities/UserConnection.cs +++ b/Sledgemapper.Api/Core/Entities/UserConnection.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace Sledgemapper.Api.Models +namespace Sledgemapper.Api.Core.Entities { public class UserConnection { @@ -11,6 +11,6 @@ namespace Sledgemapper.Api.Models public Guid UserId { get; set; } [Required] - public string ConnectionId{get;set;} + public string ConnectionId { get; set; } } } diff --git a/Sledgemapper.Api/Handlers/BaseCommandHandler.cs b/Sledgemapper.Api/Handlers/BaseCommandHandler.cs index 4723308..f9a8dea 100644 --- a/Sledgemapper.Api/Handlers/BaseCommandHandler.cs +++ b/Sledgemapper.Api/Handlers/BaseCommandHandler.cs @@ -7,31 +7,29 @@ using System.Threading.Tasks; using System; using Microsoft.EntityFrameworkCore; using Sledgemapper.Api.Models; -using System.Collections.Generic; using Sledgemapper.Api.Core.Entities; namespace Sledgemapper.Api.Handlers { public abstract class BaseCommandHandler : IRequestHandler where TRequest : BaseCommand { - protected SledgemapperDbContext Dbcontext { get; } + protected SledgemapperDbContext DbContext { get; } protected IMediator Mediator { get; } - public abstract Task Handle(TRequest request, CancellationToken cancellationToken); - public BaseCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) + protected BaseCommandHandler(IMediator mediator, SledgemapperDbContext dbContext) { - Dbcontext = dbcontext; + DbContext = dbContext; Mediator = mediator; } protected async Task CheckAuthorization(TRequest command) { - var user = await Dbcontext.Users.FindAsync(command.UserId); - Dbcontext.Attach(user); + var user = await DbContext.Users.FindAsync(command.UserId); + DbContext.Attach(user); var campaign = await GetCampaignForUser(command); @@ -46,9 +44,9 @@ namespace Sledgemapper.Api.Handlers protected async Task GetCampaignForUser(TRequest command) { - var user = await Dbcontext.Users.FindAsync(command.UserId); - Dbcontext.Attach(user); - var campaign = await Dbcontext + var user = await DbContext.Users.FindAsync(command.UserId); + DbContext.Attach(user); + var campaign = await DbContext .Campaigns .Where(campaign => campaign.CampaignId == command.Campaign) .Include(c => c.InvitedUsers) @@ -60,8 +58,8 @@ namespace Sledgemapper.Api.Handlers protected async Task SaveLog(TRequest command, string operation, string type, string data, CancellationToken cancellationToken) { - var session = Dbcontext.Sessions.First(m => m.SessionId == command.SessionId); - Dbcontext.MapLogs.Add(new Models.MapLog + var session = DbContext.Sessions.First(m => m.SessionId == command.SessionId); + DbContext.MapLogs.Add(new MapLog { Operation = operation, SessionId = session.SessionId, @@ -70,7 +68,7 @@ namespace Sledgemapper.Api.Handlers Object = data, UserId = command.UserId, }); - await Dbcontext.SaveChangesAsync(cancellationToken); + await DbContext.SaveChangesAsync(cancellationToken); return session; } diff --git a/Sledgemapper.Api/Handlers/GetMapSnapshotCommandHandler.cs b/Sledgemapper.Api/Handlers/GetMapSnapshotCommandHandler.cs index 56973c1..887635d 100644 --- a/Sledgemapper.Api/Handlers/GetMapSnapshotCommandHandler.cs +++ b/Sledgemapper.Api/Handlers/GetMapSnapshotCommandHandler.cs @@ -6,31 +6,32 @@ using System.Threading; using System.Threading.Tasks; using System.Linq; using Sledgemapper.Api.Models; +using Sledgemapper.Api.Commands; -namespace Sledgemapper.Api.Commands +namespace Sledgemapper.Api.Handlers { - public class GetMapSnapshotCommandHandler : IRequestHandler + public class GetMapSnapshotCommandHandler : IRequestHandler { private readonly SledgemapperDbContext _dbcontext; public GetMapSnapshotCommandHandler(SledgemapperDbContext dbcontext) { _dbcontext = dbcontext; } - public async Task Handle(GetMapSnapshotCommand notification, CancellationToken cancellationToken) + public async Task Handle(GetMapSnapshotCommand notification, CancellationToken cancellationToken) { Snapshot snapshot; double timestamp; - Shared.Entities.Session mapSession; + Session mapSession; var session = _dbcontext.Sessions.First(m => m.SessionId == notification.MapId); snapshot = _dbcontext.Snapshots.OrderByDescending(s => s.Timestamp).FirstOrDefault(m => m.SessionId == session.SessionId); if (snapshot is null) { timestamp = 0; - mapSession = new Shared.Entities.Session(); + mapSession = new Session(); } else { - mapSession = JsonSerializer.Deserialize(snapshot.Object); + mapSession = JsonSerializer.Deserialize(snapshot.Object); timestamp = snapshot.Timestamp; } @@ -57,7 +58,7 @@ namespace Sledgemapper.Api.Commands var note = JsonSerializer.Deserialize(mapUpdate.Object); mapSession.NewNote(note); break; - case "L": + case "L": var line = JsonSerializer.Deserialize(mapUpdate.Object); mapSession.NewLine(line); break; @@ -65,9 +66,9 @@ namespace Sledgemapper.Api.Commands var room = JsonSerializer.Deserialize(mapUpdate.Object); mapSession.NewRoom(room); break; - - - + + + } diff --git a/Sledgemapper.Api/Handlers/NewLineCommandHandler.cs b/Sledgemapper.Api/Handlers/NewLineCommandHandler.cs index 58140dc..c499145 100644 --- a/Sledgemapper.Api/Handlers/NewLineCommandHandler.cs +++ b/Sledgemapper.Api/Handlers/NewLineCommandHandler.cs @@ -10,7 +10,7 @@ namespace Sledgemapper.Api.Handlers { public class NewLineCommandHandler : BaseCommandHandler { - public NewLineCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) : base(mediator, dbcontext) + public NewLineCommandHandler(IMediator mediator, SledgemapperDbContext dbContext) : base(mediator, dbContext) { } diff --git a/Sledgemapper.Api/Handlers/NewSnapshotCommandHandler.cs b/Sledgemapper.Api/Handlers/NewSnapshotCommandHandler.cs index 30f53cb..a264f00 100644 --- a/Sledgemapper.Api/Handlers/NewSnapshotCommandHandler.cs +++ b/Sledgemapper.Api/Handlers/NewSnapshotCommandHandler.cs @@ -5,8 +5,9 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Linq; +using Sledgemapper.Api.Commands; -namespace Sledgemapper.Api.Commands +namespace Sledgemapper.Api.Handlers { public class NewSnapshotCommandHandler : IRequestHandler { @@ -17,18 +18,19 @@ namespace Sledgemapper.Api.Commands public async Task Handle(NewSnapshotCommand notification, CancellationToken cancellationToken) { - + var session = _dbcontext.Sessions.First(m => m.SessionName == notification.SessionName); - var newSnapshot = new Models.Snapshot{ - SessionId=session.SessionId, - Timestamp=notification.Timestamp, - Object = JsonSerializer.Serialize(notification.Session) + var newSnapshot = new Models.Snapshot + { + SessionId = session.SessionId, + Timestamp = notification.Timestamp, + Object = JsonSerializer.Serialize(notification.Session) -}; -await _dbcontext.Snapshots.AddAsync(newSnapshot); + }; + await _dbcontext.Snapshots.AddAsync(newSnapshot); await _dbcontext.SaveChangesAsync(); - + return true; } diff --git a/Sledgemapper.Api/Handlers/NewTileCommandHandler.cs b/Sledgemapper.Api/Handlers/NewTileCommandHandler.cs index 6ab63b8..5db3d32 100644 --- a/Sledgemapper.Api/Handlers/NewTileCommandHandler.cs +++ b/Sledgemapper.Api/Handlers/NewTileCommandHandler.cs @@ -4,13 +4,13 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Sledgemapper.Api.Notifications; -using Sledgemapper.Api.Handlers; +using Sledgemapper.Api.Commands; -namespace Sledgemapper.Api.Commands +namespace Sledgemapper.Api.Handlers { public class NewTileCommandHandler : BaseCommandHandler { - public NewTileCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) : base(mediator, dbcontext) + public NewTileCommandHandler(IMediator mediator, SledgemapperDbContext dbContext) : base(mediator, dbContext) { } diff --git a/Sledgemapper.Api/Handlers/NewWallCommandHandler.cs b/Sledgemapper.Api/Handlers/NewWallCommandHandler.cs index 6e306de..c2c480d 100644 --- a/Sledgemapper.Api/Handlers/NewWallCommandHandler.cs +++ b/Sledgemapper.Api/Handlers/NewWallCommandHandler.cs @@ -10,7 +10,7 @@ namespace Sledgemapper.Api.Handlers { public class NewWallCommandHandler : BaseCommandHandler { - public NewWallCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) : base(mediator, dbcontext) + public NewWallCommandHandler(IMediator mediator, SledgemapperDbContext dbContext) : base(mediator, dbContext) { } diff --git a/Sledgemapper.Api/Handlers/PingCommandHandler.cs b/Sledgemapper.Api/Handlers/PingCommandHandler.cs deleted file mode 100644 index 9d3c53a..0000000 --- a/Sledgemapper.Api/Handlers/PingCommandHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -// using MediatR; -// using Sledgemapper.Api.Infrastructure.Data; -// using System.Threading; -// using System.Threading.Tasks; -// using Sledgemapper.Api.Notifications; -// using System.Linq; - -// namespace Sledgemapper.Api.Commands -// { -// public class PingCommandHandler : IRequestHandler -// { -// private readonly SledgemapperDbContext _dbcontext; -// private readonly IMediator _mediator; - -// public PingCommandHandler(IMediator mediator, SledgemapperDbContext dbcontext) { _dbcontext = dbcontext; _mediator = mediator; } - -// public async Task Handle(PingCommand notification, CancellationToken cancellationToken) -// { -// var session = _dbcontext.Sessions.First(m => m.SessionName == notification.SessionName); - - -// await _mediator.Publish(new PingNotification(session, notification.Location, notification.UserId)); -// return true; -// } - - -// } -// } diff --git a/Sledgemapper.Api/Handlers/SendDeleteNoteMessage.cs b/Sledgemapper.Api/Handlers/SendDeleteNoteMessage.cs index 1f6a112..b55e7a0 100644 --- a/Sledgemapper.Api/Handlers/SendDeleteNoteMessage.cs +++ b/Sledgemapper.Api/Handlers/SendDeleteNoteMessage.cs @@ -16,7 +16,7 @@ namespace Sledgemapper.Api.Handlers public async Task Handle(DeleteNoteNotification notification, CancellationToken cancellationToken) { - await _hub.Clients.Groups(notification.Session.SessionName).DeleteNote(notification.Note); + await _hub.Clients.Groups(notification.Session.SessionId.ToString()).DeleteNote(notification.Note); } } } diff --git a/Sledgemapper.Api/Handlers/SendDeleteOverlayMessage.cs b/Sledgemapper.Api/Handlers/SendDeleteOverlayMessage.cs index cb0b922..ab492c4 100644 --- a/Sledgemapper.Api/Handlers/SendDeleteOverlayMessage.cs +++ b/Sledgemapper.Api/Handlers/SendDeleteOverlayMessage.cs @@ -16,7 +16,7 @@ namespace Sledgemapper.Api.Handlers public async Task Handle(DeleteOverlayNotification notification, CancellationToken cancellationToken) { - await _hub.Clients.Groups(notification.Session.SessionName).DeleteOverlay(notification.Overlay); + await _hub.Clients.Groups(notification.Session.SessionId.ToString()).DeleteOverlay(notification.Overlay); } } } diff --git a/Sledgemapper.Api/Handlers/SendDeleteTileMessage.cs b/Sledgemapper.Api/Handlers/SendDeleteTileMessage.cs index 75c0c03..215f830 100644 --- a/Sledgemapper.Api/Handlers/SendDeleteTileMessage.cs +++ b/Sledgemapper.Api/Handlers/SendDeleteTileMessage.cs @@ -16,7 +16,7 @@ namespace Sledgemapper.Api.Handlers public async Task Handle(DeleteTileNotification notification, CancellationToken cancellationToken) { - await _hub.Clients.Groups(notification.Session.SessionName).DeleteTile(notification.Tile); + await _hub.Clients.Groups(notification.Session.SessionId.ToString()).DeleteTile(notification.Tile); } } } diff --git a/Sledgemapper.Api/Handlers/SendDeleteWallMessage.cs b/Sledgemapper.Api/Handlers/SendDeleteWallMessage.cs index e853012..853a0bc 100644 --- a/Sledgemapper.Api/Handlers/SendDeleteWallMessage.cs +++ b/Sledgemapper.Api/Handlers/SendDeleteWallMessage.cs @@ -16,7 +16,7 @@ namespace Sledgemapper.Api.Handlers public async Task Handle(DeleteWallNotification notification, CancellationToken cancellationToken) { - await _hub.Clients.Groups(notification.Session.SessionName).DeleteWall(notification.Wall); + await _hub.Clients.Groups(notification.Session.SessionId.ToString()).DeleteWall(notification.Wall); } } } diff --git a/Sledgemapper.Api/Handlers/SendPingMessage.cs b/Sledgemapper.Api/Handlers/SendPingMessage.cs deleted file mode 100644 index 9b7f0d9..0000000 --- a/Sledgemapper.Api/Handlers/SendPingMessage.cs +++ /dev/null @@ -1,23 +0,0 @@ -// using MediatR; -// using Microsoft.AspNetCore.SignalR; -// using Sledgemapper.Api.Notifications; -// using Sledgemapper.Clients; -// using System.Threading; -// using System.Threading.Tasks; -// using Sledgemapper.Api.Hubs; - -// namespace Sledgemapper.Api.Handlers -// { -// public class SendPingMessage : INotificationHandler -// { -// private readonly IHubContext _hub; - -// public SendPingMessage(IHubContext hub) => _hub = hub; - -// public async Task Handle(PingNotification notification, CancellationToken cancellationToken) -// { - -// await _hub.Clients.Groups(notification.Session.SessionName).Ping(notification.Location, notification.UserId); -// } -// } -// } diff --git a/Sledgemapper.Api/Handlers/StartNewSessionHandler.cs b/Sledgemapper.Api/Handlers/StartNewSessionHandler.cs index 6281275..e84ba3e 100644 --- a/Sledgemapper.Api/Handlers/StartNewSessionHandler.cs +++ b/Sledgemapper.Api/Handlers/StartNewSessionHandler.cs @@ -3,7 +3,6 @@ using Sledgemapper.Api.Commands; using Sledgemapper.Api.Infrastructure.Data; using Sledgemapper.Api.Models; using System; -using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -29,8 +28,8 @@ namespace Sledgemapper.Api.Handlers CampaignId = campaign.CampaignId }; - Dbcontext.Sessions.Add(session); - await Dbcontext.SaveChangesAsync(); + DbContext.Sessions.Add(session); + await DbContext.SaveChangesAsync(cancellationToken); return session.SessionId; } } diff --git a/Sledgemapper.Api/Helpers/AppException.cs b/Sledgemapper.Api/Helpers/AppException.cs index c9601e5..957826f 100644 --- a/Sledgemapper.Api/Helpers/AppException.cs +++ b/Sledgemapper.Api/Helpers/AppException.cs @@ -1,17 +1,17 @@ using System; using System.Globalization; -namespace Sledgemapper.Helpers +namespace Sledgemapper.Api.Helpers { // Custom exception class for throwing application specific exceptions (e.g. for validation) // that can be caught and handled within the application public class AppException : Exception { - public AppException() : base() {} + public AppException() : base() { } public AppException(string message) : base(message) { } - public AppException(string message, params object[] args) + public AppException(string message, params object[] args) : base(string.Format(CultureInfo.CurrentCulture, message, args)) { } diff --git a/Sledgemapper.Api/Helpers/AutoMapperProfile.cs b/Sledgemapper.Api/Helpers/AutoMapperProfile.cs index e9fd4aa..e6fd486 100644 --- a/Sledgemapper.Api/Helpers/AutoMapperProfile.cs +++ b/Sledgemapper.Api/Helpers/AutoMapperProfile.cs @@ -2,7 +2,7 @@ using AutoMapper; using Sledgemapper.Entities; using Sledgemapper.Models.Users; -namespace Sledgemapper.Helpers +namespace Sledgemapper.Api.Helpers { public class AutoMapperProfile : Profile { diff --git a/Sledgemapper.Api/Hubs/SledgemapperHub.cs b/Sledgemapper.Api/Hubs/SledgemapperHub.cs index 8141746..b41343f 100644 --- a/Sledgemapper.Api/Hubs/SledgemapperHub.cs +++ b/Sledgemapper.Api/Hubs/SledgemapperHub.cs @@ -17,12 +17,10 @@ namespace Sledgemapper.Api.Hubs { private static readonly ConcurrentDictionary UserColors = new(); private readonly SledgemapperDbContext _dbContext; - // private readonly DataContext _datacontext; public SledgemapperHub(SledgemapperDbContext dbContext/*, DataContext datacontext*/) { _dbContext = dbContext; - // _datacontext = datacontext; } // other colors @@ -87,12 +85,12 @@ namespace Sledgemapper.Api.Hubs public async Task Ping(string sessionName, Tile location) { - var userId = new Guid( Context.User.Claims.FirstOrDefault(m => m.Type == "Id").Value); + var userId = new Guid(Context.User.Claims.FirstOrDefault(m => m.Type == "Id").Value); var user = _dbContext.Users.First(u => u.Id == userId.ToString()); var player = new Player { UserId = userId, Initials = user.Initials, Position = new Tile { X = 0, Y = 0 }, Color = UserColors[userId] }; - await Clients.Group(sessionName).Ping(new Ping{X=location.X, Y=location.Y, Player=player}); + await Clients.Group(sessionName).Ping(new Ping { X = location.X, Y = location.Y, Player = player }); } public async Task JoinSession(Guid mapId) @@ -114,7 +112,7 @@ namespace Sledgemapper.Api.Hubs await Clients.Group(session.SessionId.ToString()).NewPlayer(player); await Clients.Group(session.SessionId.ToString()).RefreshPlayers(); - + return true; } @@ -136,7 +134,7 @@ namespace Sledgemapper.Api.Hubs public async Task UpdatePosition(string sessionName, Guid sessionId, Tile tile) { var userId = new Guid(Context.User.Claims.FirstOrDefault(m => m.Type == "Id").Value); - var SessionUsers = _dbContext.SessionUsers.Where(m => m.SessionId == sessionId).OrderBy(m => m.UserId).ToList(); + var sessionUsers = _dbContext.SessionUsers.Where(m => m.SessionId == sessionId).OrderBy(m => m.UserId).ToList(); var user = _dbContext.Users.First(u => u.Id == userId.ToString()); var player = new Player { UserId = userId, Initials = user.Initials, Position = tile, Color = UserColors[userId] }; await Clients.Group(sessionId.ToString()).PlayerUpdate(player); @@ -148,7 +146,7 @@ namespace Sledgemapper.Api.Hubs 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(); + var availableColor = Colors.First(m => !UserColors.Values.Contains(m)); UserColors.AddOrUpdate(userId, availableColor, (key, oldValue) => availableColor); await base.OnConnectedAsync(); } @@ -156,26 +154,26 @@ namespace Sledgemapper.Api.Hubs public override async Task OnDisconnectedAsync(Exception exception) { var userConnection = _dbContext.UserConnections.FirstOrDefault(m => m.ConnectionId == Context.ConnectionId); - var userId = userConnection.UserId; if (userConnection != null) { + var userId = userConnection.UserId; + _dbContext.UserConnections.Remove(userConnection); - } - var userSessions = _dbContext.SessionUsers.Where(m => m.UserId == userId).ToList(); - { - foreach (var userSession in userSessions) + var userSessions = _dbContext.SessionUsers.Where(m => m.UserId == userId).ToList(); { - var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionId == userSession.SessionId); + foreach (var userSession in userSessions) + { + var session = _dbContext.Sessions.FirstOrDefault(m => m.SessionId == userSession.SessionId); - await Clients.Group(session.SessionName).RemovePlayer(new Player { UserId = userId }); //send remove player - _dbContext.SessionUsers.Remove(userSession); + await Clients.Group(session.SessionName).RemovePlayer(new Player { UserId = userId }); //send remove player + _dbContext.SessionUsers.Remove(userSession); + } } + await _dbContext.SaveChangesAsync(); + + await base.OnDisconnectedAsync(exception); } - await _dbContext.SaveChangesAsync(); - - await base.OnDisconnectedAsync(exception); - } } } \ No newline at end of file diff --git a/Sledgemapper.Api/Models/AuthResult.cs b/Sledgemapper.Api/Models/AuthResult.cs index ec22a2c..cf42c6a 100644 --- a/Sledgemapper.Api/Models/AuthResult.cs +++ b/Sledgemapper.Api/Models/AuthResult.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Sledgemapper.Models.Users +namespace Sledgemapper.Api.Models { public class AuthResult { diff --git a/Sledgemapper.Api/Models/AuthenticateModel.cs b/Sledgemapper.Api/Models/AuthenticateModel.cs index f164138..48e743f 100644 --- a/Sledgemapper.Api/Models/AuthenticateModel.cs +++ b/Sledgemapper.Api/Models/AuthenticateModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Sledgemapper.Models.Users +namespace Sledgemapper.Api.Models { public class AuthenticateModel { diff --git a/Sledgemapper.Api/Models/RegisterModel.cs b/Sledgemapper.Api/Models/RegisterModel.cs index de274f0..646a3f3 100644 --- a/Sledgemapper.Api/Models/RegisterModel.cs +++ b/Sledgemapper.Api/Models/RegisterModel.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Sledgemapper.Models.Users +namespace Sledgemapper.Api.Models { public class RegisterModel { diff --git a/Sledgemapper.Api/Models/RegistrationResponse.cs b/Sledgemapper.Api/Models/RegistrationResponse.cs index f3dae6e..88b6b69 100644 --- a/Sledgemapper.Api/Models/RegistrationResponse.cs +++ b/Sledgemapper.Api/Models/RegistrationResponse.cs @@ -1,4 +1,6 @@ -namespace Sledgemapper.Models.Users +using Sledgemapper.Models.Users; + +namespace Sledgemapper.Api.Models { public class RegistrationResponse : AuthResult { diff --git a/Sledgemapper.Api/Models/UserLoginRequest.cs b/Sledgemapper.Api/Models/UserLoginRequest.cs index 4e5fa99..3a2a152 100644 --- a/Sledgemapper.Api/Models/UserLoginRequest.cs +++ b/Sledgemapper.Api/Models/UserLoginRequest.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Sledgemapper.Models.Users +namespace Sledgemapper.Api.Models { public class UserLoginRequest { diff --git a/Sledgemapper.Shared/Clients/ISledgemapperClient.cs b/Sledgemapper.Shared/Clients/ISledgemapperClient.cs index 1158824..7a4ab09 100644 --- a/Sledgemapper.Shared/Clients/ISledgemapperClient.cs +++ b/Sledgemapper.Shared/Clients/ISledgemapperClient.cs @@ -1,8 +1,7 @@ using Sledgemapper.Shared.Entities; -using System.Collections.Generic; using System.Threading.Tasks; -namespace Sledgemapper.Clients +namespace Sledgemapper.Shared.Clients { public interface ISledgemapperClient { diff --git a/Sledgemapper.Shared/ExtensionMethods.cs b/Sledgemapper.Shared/ExtensionMethods.cs index f96159c..e0448d5 100644 --- a/Sledgemapper.Shared/ExtensionMethods.cs +++ b/Sledgemapper.Shared/ExtensionMethods.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Sledgemapper.Api.Hubs +namespace Sledgemapper.Shared { public static class ExtensionMethods { @@ -20,6 +20,6 @@ namespace Sledgemapper.Api.Hubs } } - + } } \ No newline at end of file diff --git a/Sledgemapper.Shared/ObservableConcurrentDictionary.cs b/Sledgemapper.Shared/ObservableConcurrentDictionary.cs index 7173e08..6bf7b4b 100644 --- a/Sledgemapper.Shared/ObservableConcurrentDictionary.cs +++ b/Sledgemapper.Shared/ObservableConcurrentDictionary.cs @@ -8,8 +8,10 @@ using System.Collections.Specialized; using System.ComponentModel; using System.Threading; using System.Diagnostics; +using System.Collections; +using System.Collections.Concurrent; -namespace System.Collections.Concurrent +namespace Sledgemapper.Shared { /// /// Provides a thread-safe dictionary for use with data binding. diff --git a/Sledgemapper.sln.DotSettings b/Sledgemapper.sln.DotSettings new file mode 100644 index 0000000..b22b302 --- /dev/null +++ b/Sledgemapper.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Sledgemapper/CommunicationManager.cs b/Sledgemapper/CommunicationManager.cs index e5874b0..e139545 100644 --- a/Sledgemapper/CommunicationManager.cs +++ b/Sledgemapper/CommunicationManager.cs @@ -1,7 +1,3 @@ -using Microsoft.AspNetCore.SignalR.Client; -using Polly; -using Refit; -using Sledgemapper.Shared.Entities; using System; using System.Collections.Generic; using System.Linq; @@ -10,20 +6,21 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR.Client; +using Polly; +using Refit; +using Sledgemapper.Shared.Entities; namespace Sledgemapper { public class CommunicationManager { - public IMapApi Api { get; private set; } - public HubConnection Connection { get; private set; } + private readonly ChannelsQueue _queue = new(); public readonly Session SessionData; - private readonly ChannelsQueue Queue = new(); private AuthenticateResponse _authenticateResponse; public CommunicationManager(Session sessionData) { - #if DEBUG var baseAddress = "http://localhost:5000"; #else @@ -32,115 +29,93 @@ namespace Sledgemapper SessionData = sessionData; Connection = new HubConnectionBuilder() - .WithAutomaticReconnect() - - .WithUrl($"{baseAddress}/SledgemapperHub", options => - { - options.AccessTokenProvider = () => Task.FromResult(_authenticateResponse.Token); - }) - .Build(); + .WithAutomaticReconnect() + .WithUrl($"{baseAddress}/SledgemapperHub", + options => { options.AccessTokenProvider = () => Task.FromResult(_authenticateResponse.Token); }) + .Build(); Api = RestService.For( - new HttpClient(new AuthenticatedHttpClientHandler(GetToken)) - { - BaseAddress = new Uri(baseAddress) - } - ); + new HttpClient(new AuthenticatedHttpClientHandler(GetToken)) + { + BaseAddress = new Uri(baseAddress) + } + ); - Connection.On("UpdateMap", (map) => + Connection.On("UpdateMap", map => { SessionData.Map = map.Map; SessionData.Walls = map.Walls; SessionData.Overlays = map.Overlays; }); - Connection.On("PlayerUpdate", (player) => + Connection.On("PlayerUpdate", player => { var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); if (p != null) - { p.Position = player.Position; - } else - { SessionData.Players.Add(player); - } }); - Connection.On("DeleteTile", (tile) => + Connection.On("DeleteTile", tile => { SessionData.Map.Remove(tile.ToString(), out var _); }); + + Connection.On("DeleteWall", tile => { SessionData.Walls.Remove(tile.ToString(), out var _); }); + + Connection.On("DeleteNote", tile => { SessionData.Notes.Remove(tile.ToString(), out var _); }); + + Connection.On("DeleteOverlay", + tile => { SessionData.Overlays.Remove(tile.ToString(), out var _); }); + + Connection.On("NewTile", tile => { SessionData.Map.Remove(tile.ToString(), out var _); + SessionData.Map.TryAdd(tile.ToString(), tile); }); - Connection.On("DeleteWall", (tile) => - { - SessionData.Walls.Remove(tile.ToString(), out var _); - }); + Connection.On("NewRoom", room => + { + SessionData.Rooms.Remove(room.ToString(), out var _); + SessionData.Rooms.TryAdd(room.ToString(), room); + }); - Connection.On("DeleteNote", (tile) => - { - SessionData.Notes.Remove(tile.ToString(), out var _); - }); - - Connection.On("DeleteOverlay", (tile) => - { - SessionData.Overlays.Remove(tile.ToString(), out var _); - }); - - Connection.On("NewTile", (tile) => - { - SessionData.Map.Remove(tile.ToString(), out var _); - SessionData.Map.TryAdd(tile.ToString(), tile); - }); - - Connection.On("NewRoom", (room) => - { - SessionData.Rooms.Remove(room.ToString(), out var _); - SessionData.Rooms.TryAdd(room.ToString(), room); - }); - - Connection.On("NewLine", (line) => - { - SessionData.Lines.Remove(line.ToString(), out var _); - SessionData.Lines.TryAdd(line.ToString(), line); - }); + Connection.On("NewLine", line => + { + SessionData.Lines.Remove(line.ToString(), out var _); + SessionData.Lines.TryAdd(line.ToString(), line); + }); Connection.On("RefreshPlayers", () => - { - if (!string.IsNullOrWhiteSpace(State.Instance.MapName)) - { - Connection?.SendAsync("UpdatePosition", State.Instance.MapName, State.Instance.MapId, SessionData.Players.First(p => p.UserId == new Guid(_authenticateResponse.Id))); - } - }); + { + if (!string.IsNullOrWhiteSpace(State.Instance.MapName)) + Connection?.SendAsync("UpdatePosition", State.Instance.MapName, State.Instance.MapId, + SessionData.Players.First(p => p.UserId == new Guid(_authenticateResponse.Id))); + }); - Connection.On("RemovePlayer", (player) => - { - var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); - if (p != null) - { - SessionData.Players.Remove(p); - } - }); + Connection.On("RemovePlayer", player => + { + var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); + if (p != null) SessionData.Players.Remove(p); + }); - Connection.On("NewWall", (tile) => - { - SessionData.Walls.Remove(tile.ToString(), out var _); - SessionData.Walls.TryAdd(tile.ToString(), tile); - }); + Connection.On("NewWall", tile => + { + SessionData.Walls.Remove(tile.ToString(), out var _); + SessionData.Walls.TryAdd(tile.ToString(), tile); + }); - Connection.On("NewOverlay", (tile) => + Connection.On("NewOverlay", tile => { SessionData.Overlays.Remove(tile.ToString(), out var _); SessionData.Overlays.TryAdd(tile.ToString(), tile); }); - Connection.On("NewNote", (note) => + Connection.On("NewNote", note => { //SessionData.Notes.Remove(note.ToString(), out var _); SessionData.Notes.AddOrUpdate(note.ToString(), note, (key, oldnote) => note); }); - Connection.On("NewPlayer", (player) => + Connection.On("NewPlayer", player => { var p = SessionData.Players.FirstOrDefault(m => m.UserId == player.UserId); if (p is null) @@ -154,41 +129,11 @@ namespace Sledgemapper } }); - Connection.On("Ping", (ping) => - { - SessionData.Pings.TryAdd(Guid.NewGuid(), ping); - }); + Connection.On("Ping", ping => { SessionData.Pings.TryAdd(Guid.NewGuid(), ping); }); } - - - private Task GetToken() - { - return Task.FromResult(_authenticateResponse.Token); - } - - public async Task Register(RegisterModel registerModel) - { - var result = await Api.Register(registerModel).ConfigureAwait(false); - return result; - } - - public async Task Login(AuthenticateModel authenticateModel) - { - _authenticateResponse = await Api.Authenticate(authenticateModel).ConfigureAwait(false); - return _authenticateResponse; - } - - private async Task Execute(Func call) - { - await Policy - .Handle(ex => ex.StatusCode == HttpStatusCode.RequestTimeout) - - .RetryForeverAsync() - //.RetryAsync(Polly.RetrySyntax., async (exception, retryCount) => await Task.Delay(500)) - .ExecuteAsync(async () => await call().ConfigureAwait(false)) - .ConfigureAwait(false); - } + public IMapApi Api { get; } + public HubConnection Connection { get; } public void Enqueue(BaseMapEntity entity, TileAction action) { @@ -198,64 +143,112 @@ namespace Sledgemapper switch (entity) { case Tile tile: - Queue.Enqueue(async () => await Execute(async () => await Api.NewTile(tile, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.NewTile(tile, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; case Overlay overlay: - Queue.Enqueue(async () => await Execute(async () => await Api.NewOverlay(overlay,State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.NewOverlay(overlay, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; case Wall wall: - Queue.Enqueue(async () => await Execute(async () => await Api.NewWall(wall, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.NewWall(wall, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; case Note note: - Queue.Enqueue(async () => await Execute(async () => await Api.NewNote(note, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.NewNote(note, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; case Room room: - Queue.Enqueue(async () => await Execute(async () => await Api.NewRoom(room, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.NewRoom(room, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; case Line line: - Queue.Enqueue(async () => await Execute(async () => await Api.NewLine(line, State.Instance.CampaignId, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.NewLine(line, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; } + break; case TileAction.Delete: switch (entity) { case Tile tile: - Queue.Enqueue(async () => await Execute(async () => await Api.DeleteTile(tile, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.DeleteTile(tile, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; case Overlay overlay: - Queue.Enqueue(async () => await Execute(async () => await Api.DeleteOverlay(overlay, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.DeleteOverlay(overlay, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; case Wall wall: - Queue.Enqueue(async () => await Execute(async () => await Api.DeleteWall(wall, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.DeleteWall(wall, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; case Note note: - Queue.Enqueue(async () => await Execute(async () => await Api.DeleteNote(note, State.Instance.MapId).ConfigureAwait(false))); + _queue.Enqueue(async () => await Execute(async () => + await Api.DeleteNote(note, State.Instance.CampaignId, State.Instance.MapId) + .ConfigureAwait(false))); break; } + break; } + } + private async Task Execute(Func call) + { + await Policy + .Handle(ex => ex.StatusCode == HttpStatusCode.RequestTimeout) + .RetryForeverAsync() + //.RetryAsync(Polly.RetrySyntax., async (exception, retryCount) => await Task.Delay(500)) + .ExecuteAsync(async () => await call().ConfigureAwait(false)) + .ConfigureAwait(false); + } + + + private Task GetToken() + { + return Task.FromResult(_authenticateResponse.Token); + } + + public async Task Login(AuthenticateModel authenticateModel) + { + _authenticateResponse = await Api.Authenticate(authenticateModel).ConfigureAwait(false); + return _authenticateResponse; } internal async Task Ping(Tile location) { - if (Connection!=null && Connection.State == HubConnectionState.Connected) + if (Connection is { State: HubConnectionState.Connected }) { - await Connection.InvokeAsync("Ping",SessionData.SessionName, location); + await Connection.InvokeAsync("Ping", SessionData.SessionName, location); } } + + public async Task Register(RegisterModel registerModel) + { + var result = await Api.Register(registerModel).ConfigureAwait(false); + return result; + } } - class AuthenticatedHttpClientHandler : HttpClientHandler + internal class AuthenticatedHttpClientHandler : HttpClientHandler { - private readonly Func> getToken; + private readonly Func> _getToken; public AuthenticatedHttpClientHandler(Func> getToken) { - if (getToken == null) throw new ArgumentNullException(nameof(getToken)); - this.getToken = getToken; + _getToken = getToken ?? throw new ArgumentNullException(nameof(getToken)); //if (myConfigurationService.VerifySslCertificate == false) //{ @@ -264,19 +257,18 @@ namespace Sledgemapper //} } - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + protected override async Task SendAsync(HttpRequestMessage request, + CancellationToken cancellationToken) { // See if the request has an authorize header var auth = request.Headers.Authorization; if (auth != null) { - var token = await getToken().ConfigureAwait(false); + var token = await _getToken().ConfigureAwait(false); request.Headers.Authorization = new AuthenticationHeaderValue(auth.Scheme, token); } return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); } - - } -} +} \ No newline at end of file diff --git a/Sledgemapper/IMapApi.cs b/Sledgemapper/IMapApi.cs index f5b6bca..3af30f6 100644 --- a/Sledgemapper/IMapApi.cs +++ b/Sledgemapper/IMapApi.cs @@ -70,17 +70,17 @@ namespace Sledgemapper - [Delete("/session/{sessionName}/wall")] - Task DeleteWall([Body] Wall wall, Guid sessionName); + [Delete("/map/{campaignId}/{mapId}/wall")] + Task DeleteWall([Body] Wall wall, Guid campaignId, Guid mapId); - [Delete("/session/{sessionName}/tile")] - Task DeleteTile([Body] Tile tile, Guid sessionName); + [Delete("/map/{campaignId}/{mapId}/tile")] + Task DeleteTile([Body] Tile tile, Guid campaignId, Guid mapId); - [Delete("/session/{sessionName}/overlay")] - Task DeleteOverlay([Body] Overlay overlay, Guid sessionName); + [Delete("/map/{campaignId}/{mapId}/overlay")] + Task DeleteOverlay([Body] Overlay overlay, Guid campaignId, Guid mapId); - [Delete("/session/{sessionName}/note")] - Task DeleteNote([Body] Note overlay, Guid sessionName); + [Delete("/map/{campaignId}/{mapId}/note")] + Task DeleteNote([Body] Note overlay, Guid campaignId, Guid mapId); public class AuthResult diff --git a/Sledgemapper/Settings.cs b/Sledgemapper/Settings.cs index 4c22f57..f3aa679 100644 --- a/Sledgemapper/Settings.cs +++ b/Sledgemapper/Settings.cs @@ -14,7 +14,7 @@ namespace Sledgemapper public int TileDeleteDivider { get; set; } public int PingDuration {get;set;} - private static readonly Settings instance = new Settings(); + private static readonly Settings instance = new (); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit diff --git a/Sledgemapper/Sledgemapper.cs b/Sledgemapper/Sledgemapper.cs index 42c5bd1..c91d8f6 100644 --- a/Sledgemapper/Sledgemapper.cs +++ b/Sledgemapper/Sledgemapper.cs @@ -1,3 +1,8 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using AsyncAwaitBestPractices; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -10,49 +15,43 @@ using Myra.Graphics2D.UI; using Myra.Utility; using Sledgemapper.Shared.Entities; using Sledgemapper.UI; -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using AsyncAwaitBestPractices; using TinyMessenger; +using Thickness = Myra.Graphics2D.Thickness; namespace Sledgemapper { public class Sledgemapper : Game { private readonly CommunicationManager _communicationManager; - private readonly State _state; - private readonly ArrayPool _vector2Pool; - private readonly GraphicsDeviceManager _graphics; - private SpriteBatch _spriteBatch; - private CachedContent _cachedContent; private readonly Desktop _desktop; - private KeyboardState oldState; - private MouseState oldMouseState; - private bool _isDraggin; - private Dictionary _fonts; - private Texture2D _comment; - private readonly Session _sessionData; - private RenderTarget2D rendertarget; - private MainWidget _mainWidget; + private readonly GraphicsDeviceManager _graphics; private readonly TinyMessengerHub _messenger; - Effect outlineShader; - private Texture2D _transparentRedRectangle; - private Texture2D _whiteRectangle; - private Dictionary _wallsContent; - private SpriteSheet _spriteSheet; + private readonly Session _sessionData; + private readonly State _state; + private CachedContent _cachedContent; + private Texture2D _comment; + private Dictionary _fonts; + private bool _isDragging; + private Label _lblOverlayName; + private MainWidget _mainWidget; + private MouseState _oldMouseState; + private KeyboardState _oldState; + private Effect _outlineShader; + private RenderTarget2D _renderTarget; private SpriteSheet _rippleSpriteSheet; - Label _lblOverlayName; + private SpriteBatch _spriteBatch; + private SpriteSheet _spriteSheet; + private Texture2D _transparentRedRectangle; + private Dictionary _wallsContent; + private Texture2D _whiteRectangle; public Sledgemapper() { _graphics = new GraphicsDeviceManager(this); _graphics.GraphicsProfile = GraphicsProfile.Reach; - _graphics.PreferMultiSampling = false; - + _graphics.PreferMultiSampling = true; + Content.RootDirectory = "Content"; _desktop = new Desktop(); @@ -67,506 +66,12 @@ namespace Sledgemapper _communicationManager.Connection.Closed += OnHubDisconnected; _state = State.Instance; - _vector2Pool = ArrayPool.Create(); _messenger = new TinyMessengerHub(); } - private async Task OnHubDisconnected(Exception arg) - { - // ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Hub disconnected", Type = "SignalR Client Events", Source = _settings.MachineName }); - _mainWidget.lblConnectionStatus.Text = "Disconnected"; - await Task.Yield(); - } - - private async Task OnHubReconnecting(Exception arg) - { - // ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Reconnecting Hub", Type = "SignalR Client Events", Source = _settings.MachineName }); - _mainWidget.lblConnectionStatus.Text = "Reconnecting"; - await Task.Yield(); - } - - private async Task OnHubReconnected(string arg) - { - // ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Hub reconnected", Type = "SignalR Client Events", Source = _settings.MachineName }); - _mainWidget.lblConnectionStatus.Text = "Connected"; - await Task.Yield(); - } - - protected override void Initialize() - { - // ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Initialize", Type = "AppLifecycle", Source = _settings.MachineName }); - IsMouseVisible = true; - Window.AllowUserResizing = true; - Window.ClientSizeChanged += OnClientSizeChanged; - base.Initialize(); - } - - private void ResetRenderTarget() - { - rendertarget = new RenderTarget2D(GraphicsDevice, - GraphicsDevice.Viewport.Width, - GraphicsDevice.Viewport.Height, - false, - SurfaceFormat.Color, - DepthFormat.None, - 0, - RenderTargetUsage.DiscardContents); - } - - private void OnClientSizeChanged(object sender, EventArgs e) - { - rendertarget?.Dispose(); - try - { - ResetRenderTarget(); - } - catch - { - System.Console.WriteLine("rendertarget dispose exception"); - } - - } - - private void AddItemToToolGrid(Grid grid, EventHandler eventAction, Dictionary tilesFolderContent) - { - var indexX = 0; - var indexY = 0; - foreach (var item in tilesFolderContent) - { - var tileButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 }; - tileButton.Click += eventAction; - grid.Widgets.Add(tileButton); - indexY++; - if (indexY == 4) - { - indexY = 0; - indexX++; - } - } - } - - private void AddItemToToolGrid(Grid grid, EventHandler eventAction, SpriteSheet spriteSheet, string e = "") - { - var indexX = 0; - var indexY = 0; - grid.Widgets.Clear(); - _mainWidget.ScrOverlay.ResetScroll(); - foreach (var item in spriteSheet.index.Where(t => String.IsNullOrWhiteSpace(e) || t.Key.ToLower().Contains(e.ToLower()))) - { - var tileButton = new ImageButton { Image = new TextureRegion(spriteSheet.Texture, item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 }; - tileButton.Click += eventAction; - tileButton.MouseMoved += OnTileButtonTouchEntered; - tileButton.MouseLeft += OnTileButtonTouchLeft; - grid.Widgets.Add(tileButton); - indexY++; - if (indexY == 4) - { - indexY = 0; - indexX++; - } - } - } - - private void OnTileButtonTouchLeft(object sender, EventArgs e) - { - _desktop.HideContextMenu(); - _lblOverlayName.Visible = false; - } - - private void OnTileButtonTouchEntered(object sender, EventArgs e) - { - var mouseState = Mouse.GetState().Position; - mouseState.X += 10; - mouseState.Y += 10; - _lblOverlayName.Visible = true; - _lblOverlayName.Text = ((ImageButton)sender).Id; - _desktop.ShowContextMenu(_lblOverlayName, mouseState); - } - - protected override void LoadContent() - { - _spriteBatch = new SpriteBatch(GraphicsDevice); - _cachedContent = CachedContent.Instance; - - outlineShader = Content.Load("shaders/OutlineShader"); - MyraEnvironment.Game = this; - ResetRenderTarget(); - - - _mainWidget = new MainWidget(_communicationManager, _messenger, Window); - - - - - _wallsContent = Content.LoadContentFolder("walls"); - - _spriteSheet = new SpriteSheet(); - _spriteSheet.LoadContent(Content, "spriteIndex", "sprites"); - _rippleSpriteSheet = new SpriteSheet(); - _rippleSpriteSheet.LoadContent(Content, "handcursorsIndex", "handcursors"); - - _lblOverlayName = new Label(); - _lblOverlayName.Background = new SolidBrush(Color.SlateGray); - _lblOverlayName.Padding = new Myra.Graphics2D.Thickness(4); - - AddItemToToolGrid(_mainWidget.GridWalls, OnWallButtonClicked, _wallsContent); - AddItemToToolGrid(_mainWidget.GridOverlays, OnOverlayButtonClicked, _spriteSheet); - - _fonts = Content.LoadContentFolder("fonts"); - _cachedContent.Eye = Content.Load("eye"); - _cachedContent.Location = Content.Load("location"); - _comment = Content.Load("comment"); - _mainWidget.BtnToolbarLine.Image = new TextureRegion(Content.Load("icon_line")); - _mainWidget.BtnToolbarRoom.Image = new TextureRegion(Content.Load("icon_room")); - _mainWidget.BtnToolbarDelete.Image = new TextureRegion(Content.Load("icon_delete")); - _mainWidget.TxtOverlaySearch.TextChangedByUser += OnTxtOverlaySearchChange; - - _desktop.Root = _mainWidget; - - _transparentRedRectangle = new Texture2D(GraphicsDevice, 1, 1); - _transparentRedRectangle.SetData(new[] { new Color(Color.Red, 80) }); - - _whiteRectangle = new Texture2D(GraphicsDevice, 1, 1); - _whiteRectangle.SetData(new[] { Color.White }); - - CenterOnTile(0, 0); - } - - private void OnTxtOverlaySearchChange(object sender, ValueChangedEventArgs e) - { - AddItemToToolGrid(_mainWidget.GridOverlays, OnOverlayButtonClicked, _spriteSheet, e.NewValue); - } - - private void EditNote(Note note) - { - _state.SelectedNote = new Note { X = note.X, Y = note.Y, Text = note.Text }; - new NoteWindow(_communicationManager, note).ShowInModalWindow(_desktop, $" Note on {note.X}:{note.Y}"); - } - - protected override void Update(GameTime gameTime) - { - KeyboardState newState = Keyboard.GetState(); - - if (IsActive && GraphicsDevice.Viewport.Bounds.Contains(Mouse.GetState().Position) && !_desktop.IsMouseOverGUI && !_desktop.HasModalWidget) - { - var mouseState = Mouse.GetState(); - - var screenPosition = new Point(mouseState.Position.X - (int)_state.ViewportCenter.X, mouseState.Position.Y - (int)_state.ViewportCenter.Y); - - if (!_desktop.ContextMenu?.Visible??true) - { - _state.HoveredTile.X = screenPosition.X / _state.TileSize; - _state.HoveredTile.Y = screenPosition.Y / _state.TileSize; - - - if (screenPosition.X < 0) - { - _state.HoveredTile.X--; - } - - if (screenPosition.Y < 0) - { - _state.HoveredTile.Y--; - } - } - - if (_state.InsertMode == InsertMode.Wall) - { - _state.SelectClosestWall(screenPosition); - } - - if (_state.InsertMode == InsertMode.Overlay) - { - _state.SelectOverlay(screenPosition); - } - - if (_state.InsertMode == InsertMode.NewLine || _state.InsertMode == InsertMode.NewRoom || _state.InsertMode == InsertMode.NewDelete) - { - _state.SelectClosestSnapPoint(screenPosition); - } - - if (!newState.IsKeyDown(Keys.LeftControl) && mouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == oldMouseState.LeftButton && - !_desktop.IsMouseOverGUI - ) - { - _state.ViewportCenter = new Vector3(_state.ViewportCenter.X + mouseState.Position.X - oldMouseState.Position.X, _state.ViewportCenter.Y + mouseState.Position.Y - oldMouseState.Position.Y, 0); - if (mouseState.Position != oldMouseState.Position) - { - _isDraggin = true; - } - } - - if (mouseState.LeftButton == ButtonState.Released && mouseState.LeftButton != oldMouseState.LeftButton) - { - if (_isDraggin) - { - _isDraggin = false; - } - else - { - _state.SelectedTile.X = _state.HoveredTile.X; - _state.SelectedTile.Y = _state.HoveredTile.Y; - _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapName, State.Instance.MapId, _state.SelectedTile); - - } - } - - if (mouseState.RightButton == ButtonState.Released && mouseState.RightButton != oldMouseState.RightButton) - { - _state.SelectedNote.X = _state.HoveredTile.X; - _state.SelectedNote.Y = _state.HoveredTile.Y; - - var popup = new VerticalStackPanel { Padding = new Myra.Graphics2D.Thickness(1), Spacing = 2, Background = new SolidBrush(Color.DarkGray) }; - - if (!_sessionData.Notes.ContainsKey(_state.SelectedNote.ToString())) - { - var newNoteButton = new TextButton { Text = "New Note", Width = 80, Height = 20, Padding = new Myra.Graphics2D.Thickness(2), HorizontalAlignment = HorizontalAlignment.Left }; - newNoteButton.Click += OnContextMenuNewNoteClick; - popup.AddChild(newNoteButton); - - - } - else - { - _sessionData.Notes.TryGetValue(_state.SelectedNote.ToString(), out var n); - _state.SelectedNote = n; - var viewNoteButton = new TextButton { Text = "View Note", Width = 80, Height = 20, Padding = new Myra.Graphics2D.Thickness(2), HorizontalAlignment = HorizontalAlignment.Left }; - var deleteNoteButton = new TextButton { Text = "Delete Note", Width = 80, Height = 20, Padding = new Myra.Graphics2D.Thickness(2), HorizontalAlignment = HorizontalAlignment.Left }; - viewNoteButton.Click += OnContextMenuViewNoteClick; - deleteNoteButton.Click += OnContextMenuDeleteNoteClick; - - popup.AddChild(viewNoteButton); - popup.AddChild(deleteNoteButton); - } - - var pingButton = new TextButton { Text = "Ping", Width = 80, Height = 20, Padding = new Myra.Graphics2D.Thickness(2), HorizontalAlignment = HorizontalAlignment.Left }; - var location = new Tile { X = _state.HoveredTile.X, Y = _state.HoveredTile.Y }; - pingButton.Click += (s, e) => OnContextMenuPingClick(s, e, location); - popup.AddChild(pingButton); - - _desktop.ShowContextMenu(popup, mouseState.Position); - } - - if (newState.IsKeyDown(Keys.LeftControl) - && mouseState.LeftButton == ButtonState.Released - && mouseState.LeftButton != oldMouseState.LeftButton) - { - switch (_state.InsertMode) - { - case InsertMode.Tile: - _state.SelectedTile.X = _state.HoveredTile.X; - _state.SelectedTile.Y = _state.HoveredTile.Y; - _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapName, State.Instance.MapId, _state.SelectedTile); - - _sessionData.NewTile(_state.SelectedTile, _state.CurrentTileId); - break; - case InsertMode.Wall: - _sessionData.NewWall(_state.SelectedWall, _state.CurrentWallId); - - break; - case InsertMode.Overlay: - _sessionData.NewOverlay(_state.SelectedOverlay, _state.CurrentOverlayId); - break; - } - } - - - if (_state.InsertMode == InsertMode.NewLine && newState.IsKeyDown(Keys.LeftControl) - && mouseState.LeftButton == ButtonState.Released - && mouseState.LeftButton != oldMouseState.LeftButton) - { - if (_state.LineStart is null) - { - _state.LineStart = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index }; - } - else - { - - var line = new Line - { - Start = new SnapPoint { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index }, - End = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index }, - Width = _state.LineWidth - }; - _state.LineStart = null; - _state.LineWidth = 1; - _sessionData.NewLine(line); - } - } - - if (_state.InsertMode == InsertMode.NewRoom && newState.IsKeyDown(Keys.LeftControl) - && mouseState.LeftButton == ButtonState.Released - && mouseState.LeftButton != oldMouseState.LeftButton) - { - if (_state.LineStart is null) - { - _state.LineStart = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index }; - } - else - { - - var line = new Room - { - Start = new SnapPoint { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index }, - End = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index } - }; - _state.LineStart = null; - _state.LineWidth = 1; - _sessionData.NewRoom(line); - } - - } - - - if (_state.InsertMode == InsertMode.NewDelete && newState.IsKeyDown(Keys.LeftControl) - && mouseState.LeftButton == ButtonState.Released - && mouseState.LeftButton != oldMouseState.LeftButton) - { - if (_state.LineStart is null) - { - _state.LineStart = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index }; - } - else - { - - var line = new Room - { - Start = new SnapPoint { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index }, - End = new SnapPoint { X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, Index = _state.SelectedSnapPoint.Index }, - Delete = true - }; - _state.LineStart = null; - _state.LineWidth = 1; - _sessionData.NewRoom(line); - } - - } - - if (_state.InsertMode == InsertMode.NewLine && _state.LineStart != null) - { - if (mouseState.ScrollWheelValue > oldMouseState.ScrollWheelValue) - { - _state.LineWidth += .01f; - } - else if (mouseState.ScrollWheelValue < oldMouseState.ScrollWheelValue) - { - _state.LineWidth -= .01f; - } - } - - if (newState.IsKeyDown(Keys.LeftControl) && mouseState.ScrollWheelValue != oldMouseState.ScrollWheelValue) - { - var maxTileSize = 500; - var center = new Point((Window.ClientBounds.Width + 200) / 2 - _state.TileSize / 2, Window.ClientBounds.Height / 2 - _state.TileSize / 2); - - var tx = (center.X - (int)_state.ViewportCenter.X) / _state.TileSize; - var ty = (center.Y - (int)_state.ViewportCenter.Y) / _state.TileSize; - - if (mouseState.ScrollWheelValue > oldMouseState.ScrollWheelValue) - { - _state.TileSize = Math.Min(maxTileSize, _state.TileSize + 10); - - } - else if (mouseState.ScrollWheelValue < oldMouseState.ScrollWheelValue) - { - _state.TileSize = Math.Max(10, _state.TileSize - 10); - } - - CenterOnTile(tx, ty); - } - - oldMouseState = mouseState; - } - - - if (newState.IsKeyDown(Keys.Delete)) - { - switch (_state.InsertMode) - { - case InsertMode.Tile: - case InsertMode.NewRoom: - case InsertMode.NewLine: - case InsertMode.NewDelete: - _state.SelectedTile.X = _state.HoveredTile.X; - _state.SelectedTile.Y = _state.HoveredTile.Y; - _sessionData.DeleteTile(_state.SelectedTile); - break; - case InsertMode.Wall: - _sessionData.DeleteWall(_state.SelectedWall); - break; - case InsertMode.Overlay: - _sessionData.DeleteOverlay(_state.SelectedOverlay); - break; - } - } - - if (oldState.IsKeyDown(Keys.P) && newState.IsKeyUp(Keys.P)) - { - _communicationManager.Ping(_state.HoveredTile).SafeFireAndForget(); - } - - foreach (var key in newState.GetPressedKeys()) - { - switch (key) - { - case Keys.Left: - if (oldState.IsKeyUp(Keys.Left) && newState.IsKeyDown(Keys.Left)) - { - _state.SelectedTile.X--; - _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapId, _state.SelectedTile); - } - break; - case Keys.Right: - if (oldState.IsKeyUp(Keys.Right) && newState.IsKeyDown(Keys.Right)) - { - _state.SelectedTile.X++; - _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapId, _state.SelectedTile); - } - break; - case Keys.Up: - if (oldState.IsKeyUp(Keys.Up) && newState.IsKeyDown(Keys.Up)) - { - _state.SelectedTile.Y--; - _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapId, _state.SelectedTile); - } - break; - case Keys.Down: - if (oldState.IsKeyUp(Keys.Down) && newState.IsKeyDown(Keys.Down)) - { - _state.SelectedTile.Y++; - _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapId, _state.SelectedTile); - } - break; - } - - } - - oldState = newState; - - base.Update(gameTime); - } - - private void CenterOnTile(int x, int y) - { - - var center = new Point((Window.ClientBounds.Width + 200) / 2 - _state.TileSize / 2, Window.ClientBounds.Height / 2 - _state.TileSize / 2); - var dx = center.X - x * _state.TileSize - _state.ViewportCenter.X; - var dy = center.Y - y * _state.TileSize - _state.ViewportCenter.Y; - _state.ViewportCenter = new Vector3(_state.ViewportCenter.X + dx, _state.ViewportCenter.Y + dy, _state.ViewportCenter.Z); - } - - private void OnContextMenuPingClick(object sender, EventArgs e, Tile location) - { - _desktop.HideContextMenu(); - _communicationManager.Ping(location).SafeFireAndForget(); - } - protected override void Draw(GameTime gameTime) { - if (_spriteBatch is null) - { - return; - } + if (_spriteBatch is null) return; var visibleTilesX = GraphicsDevice.Viewport.Width / _state.TileSize + 1; var visibleTilesY = GraphicsDevice.Viewport.Height / _state.TileSize + 1; @@ -574,8 +79,8 @@ namespace Sledgemapper ApplyShaderToMap(); _spriteBatch.Begin( - transformMatrix: Matrix.CreateTranslation(_state.ViewportCenter), - sortMode: SpriteSortMode.Texture, samplerState: SamplerState.PointClamp); + transformMatrix: Matrix.CreateTranslation(_state.ViewportCenter), + sortMode: SpriteSortMode.Texture, samplerState: SamplerState.PointClamp); DrawTiles(); @@ -609,255 +114,676 @@ namespace Sledgemapper } catch { - System.Console.WriteLine("Desktop render error"); + Console.WriteLine("Desktop render error"); } + base.Draw(gameTime); } - private void DrawRipple(GameTime gameTime) + protected override void Initialize() { - _spriteBatch.Begin( - blendState: BlendState.NonPremultiplied, - transformMatrix: Matrix.CreateTranslation(_state.ViewportCenter)); + // ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Initialize", Type = "AppLifecycle", Source = _settings.MachineName }); + IsMouseVisible = true; + Window.AllowUserResizing = true; + Window.ClientSizeChanged += OnClientSizeChanged; + base.Initialize(); + } - var durationMs = 2000; - var baseRadius = _state.TileSize / 4f; - var baseOuterRadius = (float)_state.TileSize; - var iterations = 3f; - var guids = _sessionData.Pings.Keys.ToArray(); + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + _cachedContent = CachedContent.Instance; - foreach (var guid in guids) + _outlineShader = Content.Load("shaders/OutlineShader"); + MyraEnvironment.Game = this; + ResetRenderTarget(); + + + _mainWidget = new MainWidget(_communicationManager, _messenger, Window); + + + _wallsContent = Content.LoadContentFolder("walls"); + + _spriteSheet = new SpriteSheet(); + _spriteSheet.LoadContent(Content, "spriteIndex", "sprites"); + _rippleSpriteSheet = new SpriteSheet(); + _rippleSpriteSheet.LoadContent(Content, "handcursorsIndex", "handcursors"); + + _lblOverlayName = new Label { - var pingFound = _sessionData.Pings.TryGetValue(guid, out var ping); - if (!pingFound) + Background = new SolidBrush(Color.SlateGray), + Padding = new Thickness(4) + }; + + AddItemToToolGrid(_mainWidget.GridWalls, OnWallButtonClicked, _wallsContent); + AddItemToToolGrid(_mainWidget.GridOverlays, OnOverlayButtonClicked, _spriteSheet); + + _fonts = Content.LoadContentFolder("fonts"); + _cachedContent.Eye = Content.Load("eye"); + _cachedContent.Location = Content.Load("location"); + _comment = Content.Load("comment"); + _mainWidget.BtnToolbarLine.Image = new TextureRegion(Content.Load("icon_line")); + _mainWidget.BtnToolbarRoom.Image = new TextureRegion(Content.Load("icon_room")); + _mainWidget.BtnToolbarDelete.Image = new TextureRegion(Content.Load("icon_delete")); + _mainWidget.TxtOverlaySearch.TextChangedByUser += OnTxtOverlaySearchChange; + + _desktop.Root = _mainWidget; + + _transparentRedRectangle = new Texture2D(GraphicsDevice, 1, 1); + _transparentRedRectangle.SetData(new[] { new Color(Color.Red, 80) }); + + _whiteRectangle = new Texture2D(GraphicsDevice, 1, 1); + _whiteRectangle.SetData(new[] { Color.White }); + + CenterOnTile(0, 0); + } + + protected override void Update(GameTime gameTime) + { + var newState = Keyboard.GetState(); + + if (IsActive && GraphicsDevice.Viewport.Bounds.Contains(Mouse.GetState().Position) && + !_desktop.IsMouseOverGUI && !_desktop.HasModalWidget) + { + var mouseState = Mouse.GetState(); + + var screenPosition = new Point(mouseState.Position.X - (int)_state.ViewportCenter.X, + mouseState.Position.Y - (int)_state.ViewportCenter.Y); + + if (!_desktop.ContextMenu?.Visible ?? true) { - continue; + _state.HoveredTile.X = screenPosition.X / _state.TileSize; + _state.HoveredTile.Y = screenPosition.Y / _state.TileSize; + + + if (screenPosition.X < 0) _state.HoveredTile.X--; + + if (screenPosition.Y < 0) _state.HoveredTile.Y--; } - if (ping.StartTime == 0) + if (_state.InsertMode == InsertMode.Wall) _state.SelectClosestWall(screenPosition); + + if (_state.InsertMode == InsertMode.Overlay) _state.SelectOverlay(screenPosition); + + if (_state.InsertMode == InsertMode.NewLine || _state.InsertMode == InsertMode.NewRoom || + _state.InsertMode == InsertMode.NewDelete) _state.SelectClosestSnapPoint(screenPosition); + + if (!newState.IsKeyDown(Keys.LeftControl) && mouseState.LeftButton == ButtonState.Pressed && + mouseState.LeftButton == _oldMouseState.LeftButton && + !_desktop.IsMouseOverGUI + ) { - ping.StartTime = gameTime.TotalGameTime.TotalMilliseconds; + _state.ViewportCenter = + new Vector3(_state.ViewportCenter.X + mouseState.Position.X - _oldMouseState.Position.X, + _state.ViewportCenter.Y + mouseState.Position.Y - _oldMouseState.Position.Y, 0); + if (mouseState.Position != _oldMouseState.Position) _isDragging = true; } - var x = ping.X * _state.TileSize + _state.TileSize / 2f; - var y = ping.Y * _state.TileSize + _state.TileSize / 2f; - - if (IsOffscreen(new Tile { X = ping.X, Y = ping.Y })) + if (mouseState.LeftButton == ButtonState.Released && mouseState.LeftButton != _oldMouseState.LeftButton) { - DrawPingPointer(ping, gameTime); - } - else - { - - _spriteBatch.DrawCircle( - center: new Vector2(x, y), - radius: baseRadius, - sides: 20, - color: ping.Player.Color.ToColor(), - thickness: baseRadius); - - for (var i = 0; i < iterations; i++) + if (_isDragging) { - var cycleTime = (((float)gameTime.TotalGameTime.TotalMilliseconds + (float)i * durationMs / iterations) % durationMs) / durationMs; - var easing = Easings.Interpolate(cycleTime, Easings.Functions.SineEaseInOut); - _spriteBatch.DrawCircle( - center: new Vector2(x, y), - radius: baseRadius + baseOuterRadius * easing, - sides: 20, - color: new Color(ping.Player.Color.ToColor(), (1 - easing)), - thickness: 2 + 5 * (1 - easing)); - - + _isDragging = false; + } + else + { + _state.SelectedTile.X = _state.HoveredTile.X; + _state.SelectedTile.Y = _state.HoveredTile.Y; + _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapName, + State.Instance.MapId, _state.SelectedTile); } } + + if (mouseState.RightButton == ButtonState.Released && + mouseState.RightButton != _oldMouseState.RightButton) + { + _state.SelectedNote.X = _state.HoveredTile.X; + _state.SelectedNote.Y = _state.HoveredTile.Y; + + var popup = new VerticalStackPanel + { Padding = new Thickness(1), Spacing = 2, Background = new SolidBrush(Color.DarkGray) }; + + if (!_sessionData.Notes.ContainsKey(_state.SelectedNote.ToString())) + { + var newNoteButton = new TextButton + { + Text = "New Note", Width = 80, Height = 20, Padding = new Thickness(2), + HorizontalAlignment = HorizontalAlignment.Left + }; + newNoteButton.Click += OnContextMenuNewNoteClick; + popup.AddChild(newNoteButton); + } + else + { + _sessionData.Notes.TryGetValue(_state.SelectedNote.ToString(), out var n); + _state.SelectedNote = n; + var viewNoteButton = new TextButton + { + Text = "View Note", Width = 80, Height = 20, Padding = new Thickness(2), + HorizontalAlignment = HorizontalAlignment.Left + }; + var deleteNoteButton = new TextButton + { + Text = "Delete Note", Width = 80, Height = 20, Padding = new Thickness(2), + HorizontalAlignment = HorizontalAlignment.Left + }; + viewNoteButton.Click += OnContextMenuViewNoteClick; + deleteNoteButton.Click += OnContextMenuDeleteNoteClick; + + popup.AddChild(viewNoteButton); + popup.AddChild(deleteNoteButton); + } + + var pingButton = new TextButton + { + Text = "Ping", Width = 80, Height = 20, Padding = new Thickness(2), + HorizontalAlignment = HorizontalAlignment.Left + }; + var location = new Tile { X = _state.HoveredTile.X, Y = _state.HoveredTile.Y }; + pingButton.Click += (s, e) => OnContextMenuPingClick(s, e, location); + popup.AddChild(pingButton); + + _desktop.ShowContextMenu(popup, mouseState.Position); + } + + if (newState.IsKeyDown(Keys.LeftControl) + && mouseState.LeftButton == ButtonState.Released + && mouseState.LeftButton != _oldMouseState.LeftButton) + switch (_state.InsertMode) + { + case InsertMode.Tile: + _state.SelectedTile.X = _state.HoveredTile.X; + _state.SelectedTile.Y = _state.HoveredTile.Y; + _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapName, + State.Instance.MapId, _state.SelectedTile); + + _sessionData.NewTile(_state.SelectedTile, _state.CurrentTileId); + break; + case InsertMode.Wall: + _sessionData.NewWall(_state.SelectedWall, _state.CurrentWallId); + + break; + case InsertMode.Overlay: + _sessionData.NewOverlay(_state.SelectedOverlay, _state.CurrentOverlayId); + break; + } + + + if (_state.InsertMode == InsertMode.NewLine && newState.IsKeyDown(Keys.LeftControl) + && mouseState.LeftButton == ButtonState.Released + && mouseState.LeftButton != _oldMouseState.LeftButton) + { + if (_state.LineStart is null) + { + _state.LineStart = new SnapPoint + { + X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, + Index = _state.SelectedSnapPoint.Index + }; + } + else + { + var line = new Line + { + Start = new SnapPoint + { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index }, + End = new SnapPoint + { + X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, + Index = _state.SelectedSnapPoint.Index + }, + Width = _state.LineWidth + }; + _state.LineStart = null; + _state.LineWidth = 1; + _sessionData.NewLine(line); + } + } + + if (_state.InsertMode == InsertMode.NewRoom && newState.IsKeyDown(Keys.LeftControl) + && mouseState.LeftButton == ButtonState.Released + && mouseState.LeftButton != _oldMouseState.LeftButton) + { + if (_state.LineStart is null) + { + _state.LineStart = new SnapPoint + { + X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, + Index = _state.SelectedSnapPoint.Index + }; + } + else + { + var line = new Room + { + Start = new SnapPoint + { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index }, + End = new SnapPoint + { + X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, + Index = _state.SelectedSnapPoint.Index + } + }; + _state.LineStart = null; + _state.LineWidth = 1; + _sessionData.NewRoom(line); + } + } + + + if (_state.InsertMode == InsertMode.NewDelete && newState.IsKeyDown(Keys.LeftControl) + && mouseState.LeftButton == ButtonState.Released + && mouseState.LeftButton != _oldMouseState.LeftButton) + { + if (_state.LineStart is null) + { + _state.LineStart = new SnapPoint + { + X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, + Index = _state.SelectedSnapPoint.Index + }; + } + else + { + var line = new Room + { + Start = new SnapPoint + { X = _state.LineStart.X, Y = _state.LineStart.Y, Index = _state.LineStart.Index }, + End = new SnapPoint + { + X = _state.SelectedSnapPoint.X, Y = _state.SelectedSnapPoint.Y, + Index = _state.SelectedSnapPoint.Index + }, + Delete = true + }; + _state.LineStart = null; + _state.LineWidth = 1; + _sessionData.NewRoom(line); + } + } + + if (_state.InsertMode == InsertMode.NewLine && _state.LineStart != null) + { + if (mouseState.ScrollWheelValue > _oldMouseState.ScrollWheelValue) + _state.LineWidth += .01f; + else if (mouseState.ScrollWheelValue < _oldMouseState.ScrollWheelValue) _state.LineWidth -= .01f; + } + + if (newState.IsKeyDown(Keys.LeftControl) && + mouseState.ScrollWheelValue != _oldMouseState.ScrollWheelValue) + { + var maxTileSize = 500; + var center = new Point((Window.ClientBounds.Width + 200) / 2 - _state.TileSize / 2, + Window.ClientBounds.Height / 2 - _state.TileSize / 2); + + var tx = (center.X - (int)_state.ViewportCenter.X) / _state.TileSize; + var ty = (center.Y - (int)_state.ViewportCenter.Y) / _state.TileSize; + + if (mouseState.ScrollWheelValue > _oldMouseState.ScrollWheelValue) + _state.TileSize = Math.Min(maxTileSize, _state.TileSize + 10); + else if (mouseState.ScrollWheelValue < _oldMouseState.ScrollWheelValue) + _state.TileSize = Math.Max(10, _state.TileSize - 10); + + CenterOnTile(tx, ty); + } + + _oldMouseState = mouseState; } - foreach (var guid in guids) + + + if (newState.IsKeyDown(Keys.Delete)) + switch (_state.InsertMode) + { + case InsertMode.Tile: + case InsertMode.NewRoom: + case InsertMode.NewLine: + case InsertMode.NewDelete: + _state.SelectedTile.X = _state.HoveredTile.X; + _state.SelectedTile.Y = _state.HoveredTile.Y; + _sessionData.DeleteTile(_state.SelectedTile); + break; + case InsertMode.Wall: + _sessionData.DeleteWall(_state.SelectedWall); + break; + case InsertMode.Overlay: + _sessionData.DeleteOverlay(_state.SelectedOverlay); + break; + } + + if (_oldState.IsKeyDown(Keys.P) && newState.IsKeyUp(Keys.P)) + _communicationManager.Ping(_state.HoveredTile).SafeFireAndForget(); + + foreach (var key in newState.GetPressedKeys()) + switch (key) + { + case Keys.Left: + if (_oldState.IsKeyUp(Keys.Left) && newState.IsKeyDown(Keys.Left)) + { + _state.SelectedTile.X--; + _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapId, + _state.SelectedTile); + } + + break; + case Keys.Right: + if (_oldState.IsKeyUp(Keys.Right) && newState.IsKeyDown(Keys.Right)) + { + _state.SelectedTile.X++; + _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapId, + _state.SelectedTile); + } + + break; + case Keys.Up: + if (_oldState.IsKeyUp(Keys.Up) && newState.IsKeyDown(Keys.Up)) + { + _state.SelectedTile.Y--; + _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapId, + _state.SelectedTile); + } + + break; + case Keys.Down: + if (_oldState.IsKeyUp(Keys.Down) && newState.IsKeyDown(Keys.Down)) + { + _state.SelectedTile.Y++; + _communicationManager.Connection?.SendAsync("UpdatePosition", State.Instance.MapId, + _state.SelectedTile); + } + + break; + } + + _oldState = newState; + + base.Update(gameTime); + } + + private void AddItemToToolGrid(Grid grid, EventHandler eventAction, Dictionary tilesFolderContent) + { + var indexX = 0; + var indexY = 0; + foreach (var item in tilesFolderContent) { - var pingFound = _sessionData.Pings.TryGetValue(guid, out var ping); - if (!pingFound) + var tileButton = new ImageButton { - continue; - } - - if ((gameTime.TotalGameTime.TotalMilliseconds - ping.StartTime) > Settings.Instance.PingDuration) + Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, + Width = 40, Height = 40 + }; + tileButton.Click += eventAction; + grid.Widgets.Add(tileButton); + indexY++; + if (indexY == 4) { - _sessionData.Pings.TryRemove(guid, out var _); + indexY = 0; + indexX++; } } + } + private void AddItemToToolGrid(Grid grid, EventHandler eventAction, SpriteSheet spriteSheet, string e = "") + { + var indexX = 0; + var indexY = 0; + grid.Widgets.Clear(); + _mainWidget.ScrOverlay.ResetScroll(); + foreach (var item in spriteSheet.index.Where(t => + string.IsNullOrWhiteSpace(e) || t.Key.ToLower().Contains(e.ToLower()))) + { + var tileButton = new ImageButton + { + Image = new TextureRegion(spriteSheet.Texture, item.Value), GridColumn = indexY, GridRow = indexX, + Id = item.Key, Width = 40, Height = 40 + }; + tileButton.Click += eventAction; + tileButton.MouseMoved += OnTileButtonTouchEntered; + tileButton.MouseLeft += OnTileButtonTouchLeft; + grid.Widgets.Add(tileButton); + indexY++; + if (indexY == 4) + { + indexY = 0; + indexX++; + } + } + } + private void ApplyShaderToMap() + { + var texelSize = new Vector2(_renderTarget.Width, _renderTarget.Height); + _outlineShader.Parameters["ImageSize"].SetValue(texelSize); + _outlineShader.Parameters["BorderSize"].SetValue((int)(_state.TileSize / 100f * 10f)); + + _outlineShader.Parameters["R"].SetValue(Settings.Instance.OverlayTintColor.R / 255.0f); + _outlineShader.Parameters["G"].SetValue(Settings.Instance.OverlayTintColor.G / 255.0f); + _outlineShader.Parameters["B"].SetValue(Settings.Instance.OverlayTintColor.B / 255.0f); + + GraphicsDevice.Clear(Settings.Instance.BackgroundColor); + + _spriteBatch.Begin( + effect: _outlineShader, + sortMode: SpriteSortMode.Immediate); + _spriteBatch.Draw(_renderTarget, Vector2.Zero, null, Color.White); _spriteBatch.End(); } - private void DrawRoomPreview() + private void CenterOnTile(int x, int y) { - if ((_state.InsertMode == InsertMode.NewRoom || _state.InsertMode == InsertMode.NewDelete) && _state.SelectedSnapPoint != null) + var center = new Point((Window.ClientBounds.Width + 200) / 2 - _state.TileSize / 2, + Window.ClientBounds.Height / 2 - _state.TileSize / 2); + var dx = center.X - x * _state.TileSize - _state.ViewportCenter.X; + var dy = center.Y - y * _state.TileSize - _state.ViewportCenter.Y; + _state.ViewportCenter = new Vector3(_state.ViewportCenter.X + dx, _state.ViewportCenter.Y + dy, + _state.ViewportCenter.Z); + } + + private void DrawDelete(Room tile) + { + var posX = tile.Start.X * _state.TileSize; + var posY = tile.Start.Y * _state.TileSize; + + var endposX = tile.End.X * _state.TileSize; + var endposY = tile.End.Y * _state.TileSize; + + + var ww = _state.TileSize / Settings.Instance.TileDeleteDivider; + if (posX == endposX) { - var snapPoint = new Vector2(_state.SelectedSnapPoint.X * _state.TileSize, _state.SelectedSnapPoint.Y * _state.TileSize); + endposX += ww; + posX -= ww; + } - switch (_state.SelectedSnapPoint.Index) + if (posY == endposY) + { + endposY += ww; + posY -= ww; + } + + switch (tile.Start.Index) + { + case 1: + break; + case 2: + posX += _state.TileSize / 2; + break; + case 3: + posY += _state.TileSize / 2; + + break; + case 4: + posX += _state.TileSize / 2; + posY += _state.TileSize / 2; + break; + } + + switch (tile.End.Index) + { + case 1: + break; + case 2: + endposX += _state.TileSize / 2; + break; + case 3: + endposY += _state.TileSize / 2; + + break; + case 4: + endposX += _state.TileSize / 2; + endposY += _state.TileSize / 2; + break; + } + + if (posX != endposX && posY != endposY) + { + var r = new Rectangle(); + + if (posX < endposX && posY < endposY) { - case 1: - break; - case 2: - snapPoint.X += _state.TileSize / 2; - break; - case 3: - snapPoint.Y += _state.TileSize / 2; - break; - case 4: - snapPoint.Y += _state.TileSize / 2; - snapPoint.X += _state.TileSize / 2; - break; + r = new Rectangle(posX, posY, endposX - posX, endposY - posY); + } + else if (posX > endposX && posY > endposY) + { + r = new Rectangle(posX, posY, endposX - posX, endposY - posY); + } + else + { + if (endposY < posY) r = new Rectangle(posX, endposY, endposX - posX, posY - endposY); + if (endposX < posX) r = new Rectangle(endposX, posY, posX - endposX, endposY - posY); } - _spriteBatch.DrawCircle(snapPoint, _state.TileSize / 6f, 50, Color.Red, 2); + _spriteBatch.Draw(_whiteRectangle, r, null, Color.Black, 0, Vector2.Zero, SpriteEffects.None, 1); + } + } - if (_state.LineStart != null) + private void DrawGrid(int visibleTilesX, int visibleTilesY) + { + for (var i = -1; i < visibleTilesX + 3; i++) + { + var posX1 = i * _state.TileSize - _state.ViewportCenter.X; + var posY1 = -_state.ViewportCenter.Y; + posX1 -= posX1 % _state.TileSize; + posY1 -= posY1 % _state.TileSize; + var posX2 = i * _state.TileSize - _state.ViewportCenter.X; + var posY2 = GraphicsDevice.Viewport.Height - _state.ViewportCenter.Y; + posX2 -= posX2 % _state.TileSize; + posY2 -= posY2 % _state.TileSize; + + _spriteBatch.DrawLine( + posX1, posY1, + posX2, + posY2+ _state.TileSize, + Settings.Instance.GridColor); + } + + for (var i = -1; i < visibleTilesY + 2; i++) + { + var posX1 = -_state.ViewportCenter.X; + var posY1 = i * _state.TileSize - _state.ViewportCenter.Y; + posX1 -= posX1 % _state.TileSize; + posY1 -= posY1 % _state.TileSize; + var posX2 = GraphicsDevice.Viewport.Width - _state.ViewportCenter.X; + var posY2 = i * _state.TileSize - _state.ViewportCenter.Y; + posX2 -= posX2 % _state.TileSize; + posY2 -= posY2 % _state.TileSize; + + _spriteBatch.DrawLine(posX1, posY1, + posX2 + _state.TileSize, + posY2, + Settings.Instance.GridColor); + } + + + if (_state.ShowCellNumbers && _state.TileSize >= 30) + { + var ffont = + _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize / 8).Value ?? + _fonts.Last().Value; + var fscale = 1f; + + for (var i = -1; i < visibleTilesX + 2; i++) + for (var j = -1; j < visibleTilesY + 2; j++) { - var posX = _state.LineStart.X * _state.TileSize; - var posY = _state.LineStart.Y * _state.TileSize; + var screenPosition = new Point(i * _state.TileSize - (int)_state.ViewportCenter.X, + j * _state.TileSize - (int)_state.ViewportCenter.Y); - var endposX = _state.SelectedSnapPoint.X * _state.TileSize; - var endposY = _state.SelectedSnapPoint.Y * _state.TileSize; - if (_state.InsertMode == InsertMode.NewDelete) - { - var ww = _state.TileSize / Settings.Instance.TileDeleteDivider; - if (posX == endposX) { endposX += ww; posX -= ww; } - if (posY == endposY) { endposY += ww; posY -= ww; } - } - switch (_state.LineStart.Index) - { - case 1: - break; - case 2: - posX += _state.TileSize / 2; - break; - case 3: - posY += _state.TileSize / 2; + var x = screenPosition.X / _state.TileSize; + var y = screenPosition.Y / _state.TileSize; - break; - case 4: - posX += _state.TileSize / 2; - posY += _state.TileSize / 2; - break; - } - - switch (_state.SelectedSnapPoint.Index) - { - case 1: - break; - case 2: - endposX += _state.TileSize / 2; - break; - case 3: - endposY += _state.TileSize / 2; - - break; - case 4: - endposX += _state.TileSize / 2; - endposY += _state.TileSize / 2; - break; - } - - var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize / 3).Value ?? _fonts.Last().Value; - var fscale = 1.2f; - var width = Math.Abs((endposX - posX)); - var height = Math.Abs((posY - endposY)); - var tilesWidth = width / (double)_state.TileSize; - var tilesHeight = height / (double)_state.TileSize; - tilesWidth = Math.Round(tilesWidth * 2, MidpointRounding.AwayFromZero) / 2; - tilesHeight = Math.Round(tilesHeight * 2, MidpointRounding.AwayFromZero) / 2; - var xmeasure = ffont.MeasureString($"{tilesWidth}"); - var ymeasure = ffont.MeasureString($"{tilesHeight}"); - float widthX = 0, widthY = 0, heightX = 0, heightY = 0; - - Rectangle area = new Rectangle(); - if (posX != endposX && posY != endposY) - { - if ((posX > endposX && posY > endposY) || (posX < endposX && posY < endposY)) - { - area = new Rectangle(posX, posY, endposX - posX, endposY - posY); - - if (posX > endposX && posY > endposY) - { - widthX = endposX + (width / 2) - xmeasure.X / 2; - widthY = endposY - ymeasure.Y * 1.2f; - - heightX = posX + xmeasure.X / 2; - heightY = endposY + (height / 2) - ymeasure.Y / 2; - } - else if (posX < endposX && posY < endposY) - { - widthX = posX + (width / 2) - xmeasure.X / 2; - widthY = posY - ymeasure.Y * 1.2f; - - heightX = endposX + xmeasure.X / 2; - heightY = posY + (height / 2) - ymeasure.Y / 2; - } - } - else - { - if (endposY < posY) - { - area = new Rectangle(posX, endposY, endposX - posX, posY - endposY); - - widthX = posX + (width / 2) - xmeasure.X / 2; - widthY = endposY - ymeasure.Y * 1.2f; - - heightX = endposX + xmeasure.X / 2; - heightY = endposY + (height / 2) - ymeasure.Y / 2; - } - - if (endposX < posX) - { - area = new Rectangle(endposX, posY, posX - endposX, endposY - posY); - - widthX = endposX + (width / 2) - xmeasure.X / 2; - widthY = posY - ymeasure.Y * 1.2f; - - heightX = posX + xmeasure.X / 2; - heightY = posY + (height / 2) - ymeasure.Y / 2; - } - } - - _spriteBatch.Draw(_transparentRedRectangle, area, null, Color.White, 0, new Vector2(0, 0), SpriteEffects.None, 1); - - _spriteBatch.DrawString(ffont, - $"{tilesWidth}", - new Vector2( - widthX, - widthY - ), - Color.Red, - 0, - Vector2.Zero, - fscale, - SpriteEffects.None, - 0); - - _spriteBatch.DrawString(ffont, - $"{tilesHeight}", - new Vector2( - heightX, heightY - ), - Color.Red, - 0, - Vector2.Zero, - fscale, - SpriteEffects.None, - 0); - - } + _spriteBatch.DrawString(ffont, + $"{x}:{y}", + new Vector2( + x * _state.TileSize + 2, + y * _state.TileSize + 2 + ), + Color.Black, + 0, + Vector2.Zero, + fscale, + SpriteEffects.None, + 0); } } } + private void DrawLine(Line tile) + { + var posX = tile.Start.X * _state.TileSize; + var posY = tile.Start.Y * _state.TileSize; + + var endposX = tile.End.X * _state.TileSize; + var endposY = tile.End.Y * _state.TileSize; + + switch (tile.Start.Index) + { + case 1: + break; + case 2: + posX += _state.TileSize / 2; + break; + case 3: + posY += _state.TileSize / 2; + + break; + case 4: + posX += _state.TileSize / 2; + posY += _state.TileSize / 2; + break; + } + + switch (tile.End.Index) + { + case 1: + break; + case 2: + endposX += _state.TileSize / 2; + break; + case 3: + endposY += _state.TileSize / 2; + + break; + case 4: + endposX += _state.TileSize / 2; + endposY += _state.TileSize / 2; + break; + } + + var length = (int)Math.Sqrt(Math.Pow(posX - endposX, 2) + Math.Pow(posY - endposY, 2)); + var height = (int)(_state.TileSize * tile.Width); + if (length > 0) + { + var angle = Math.Atan2(posY - endposY, endposX - posX); + var angleRad = -(float)angle; + _spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, length, height), null, Color.White, + angleRad, new Vector2(0, 0), SpriteEffects.None, 1); + } + } + private void DrawLinePreview() { if (_state.InsertMode == InsertMode.NewLine && _state.SelectedSnapPoint != null) { - var snapPoint = new Vector2(_state.SelectedSnapPoint.X * _state.TileSize, _state.SelectedSnapPoint.Y * _state.TileSize); + var snapPoint = new Vector2(_state.SelectedSnapPoint.X * _state.TileSize, + _state.SelectedSnapPoint.Y * _state.TileSize); switch (_state.SelectedSnapPoint.Index) { @@ -924,89 +850,30 @@ namespace Sledgemapper var angle = Math.Atan2(posY - endposY, endposX - posX); var angleRad = -(float)angle; if (l > 0) - { - _spriteBatch.Draw(_transparentRedRectangle, new Rectangle(posX, posY, (int)l, (int)(_state.TileSize * _state.LineWidth)), null, Color.White, angleRad, new Vector2(0, 0), SpriteEffects.None, 1); - } + _spriteBatch.Draw(_transparentRedRectangle, + new Rectangle(posX, posY, (int)l, (int)(_state.TileSize * _state.LineWidth)), null, + Color.White, angleRad, new Vector2(0, 0), SpriteEffects.None, 1); } } } - private void DrawSelectedIntersection() - { - if (_state.InsertMode == InsertMode.Overlay && _state.SelectedOverlay.Intersection) - { - var overlay = new Vector2(_state.SelectedOverlay.X * _state.TileSize, _state.SelectedOverlay.Y * _state.TileSize); - _spriteBatch.DrawCircle(overlay, _state.TileSize / 3f, 100, Color.Red, 2); - } - } - - private void DrawSelectedWall() - { - if (_state.InsertMode == InsertMode.Wall) - { - var startWall = new Vector2(_state.SelectedWall.X * _state.TileSize, _state.SelectedWall.Y * _state.TileSize); - _spriteBatch.DrawLine(startWall, _state.TileSize, MathHelper.ToRadians(90 * _state.SelectedWall.Rotation), Color.Red, 2); - } - } - - private void DrawPlayerOffline() - { - if (string.IsNullOrWhiteSpace(_sessionData.SessionName)) - { - var isoffscreen = IsOffscreen(_state.SelectedTile); - if (isoffscreen) - { - var validPointer = GetPointerVector(new Point(_state.SelectedTile.X, _state.SelectedTile.Y), out var points); - if (validPointer) - { - _spriteBatch.DrawPolygon(Vector2.Zero, points, Color.Red, 2); - } - } - else - { - _spriteBatch.DrawRectangle(new Rectangle((_state.SelectedTile.X * _state.TileSize) - 2, (_state.SelectedTile.Y * _state.TileSize) - 2, _state.TileSize + 3, _state.TileSize + 3), Color.Red, 2); - } - } - } - - private void ApplyShaderToMap() - { - Vector2 texelSize = new Vector2((float)rendertarget.Width, (float)rendertarget.Height); - outlineShader.Parameters["ImageSize"].SetValue(texelSize); - outlineShader.Parameters["BorderSize"].SetValue((int)(_state.TileSize / 100f * 10f)); - - outlineShader.Parameters["R"].SetValue(Settings.Instance.OverlayTintColor.R / 255.0f); - outlineShader.Parameters["G"].SetValue(Settings.Instance.OverlayTintColor.G / 255.0f); - outlineShader.Parameters["B"].SetValue(Settings.Instance.OverlayTintColor.B / 255.0f); - - GraphicsDevice.Clear(Settings.Instance.BackgroundColor); - - _spriteBatch.Begin( - effect: outlineShader, - sortMode: SpriteSortMode.Immediate); - _spriteBatch.Draw(rendertarget, Vector2.Zero, null, Color.White); - _spriteBatch.End(); - } - private void DrawMap() { - GraphicsDevice.SetRenderTarget(rendertarget); + GraphicsDevice.SetRenderTarget(_renderTarget); GraphicsDevice.Clear(Color.Transparent); _spriteBatch.Begin( - transformMatrix: Matrix.CreateTranslation(_state.ViewportCenter), - samplerState: SamplerState.PointClamp - ); + transformMatrix: Matrix.CreateTranslation(_state.ViewportCenter), + samplerState: SamplerState.PointClamp + ); - var items = _sessionData.Lines.Values.Union(_sessionData.Rooms.Values).OrderBy(t => t.Timestamp).ToArray(); + var items = _sessionData.Lines.Values.Union(_sessionData.Rooms.Values) + .OrderBy(t => t.Timestamp).ToArray(); for (var i = 0; i < items.Count(); i++) { var item = items.ElementAt(i); - if (IsMapElementOffscreen(item)) - { - continue; - } + if (IsMapElementOffscreen(item)) continue; switch (item) { case Line l: @@ -1015,153 +882,42 @@ namespace Sledgemapper case Room room: if (room.Delete) - { DrawDelete(room); - } else - { DrawRoom(room); - } break; } } + _spriteBatch.End(); GraphicsDevice.SetRenderTarget(null); } - private bool IsMapElementOffscreen(BaseMapEntity item) - { - SnapPoint start, end; - - switch (item) - { - case Line l: - start = l.Start; - end = l.End; - break; - - case Room room: - start = room.Start; - end = room.End; - break; - default: - return true; - } - - var visibleTilesX = GraphicsDevice.Viewport.Width / _state.TileSize + 1; - var visibleTilesY = GraphicsDevice.Viewport.Height / _state.TileSize + 1; - - var screenPositionTopLeft = new Point(200 - _state.TileSize + 0 * _state.TileSize - (int)_state.ViewportCenter.X, 0 * _state.TileSize + _state.TileSize - (int)_state.ViewportCenter.Y); - var screenPositionBottomRight = new Point(visibleTilesX * _state.TileSize - (int)_state.ViewportCenter.X, visibleTilesY * _state.TileSize - 20 - (int)_state.ViewportCenter.Y); - var tileTopLeft = new Point(screenPositionTopLeft.X / _state.TileSize, screenPositionTopLeft.Y / _state.TileSize); - var tileBottomRight = new Point(screenPositionBottomRight.X / _state.TileSize, screenPositionBottomRight.Y / _state.TileSize); - - if (start.X < tileTopLeft.X && start.Y < tileTopLeft.Y && start.X > tileBottomRight.X && start.Y > tileBottomRight.Y && - end.X < tileTopLeft.X && end.Y < tileTopLeft.Y && end.X > tileBottomRight.X && end.Y > tileBottomRight.Y - ) - { - return true; - } - return false; - } - - private void DrawGrid(int visibleTilesX, int visibleTilesY) - { - for (var i = -1; i < visibleTilesX + 2; i++) - { - var posX1 = i * _state.TileSize - _state.ViewportCenter.X; - var posY1 = -_state.ViewportCenter.Y; - posX1 -= posX1 % _state.TileSize; - posY1 -= posY1 % _state.TileSize; - var posX2 = i * _state.TileSize - _state.ViewportCenter.X; - var posY2 = GraphicsDevice.Viewport.Height - _state.ViewportCenter.Y; - posX2 -= posX2 % _state.TileSize; - posY2 -= posY2 % _state.TileSize; - - _spriteBatch.DrawLine( - posX1, posY1, - posX2, - posY2, - Settings.Instance.GridColor); - } - - for (var i = -1; i < visibleTilesY + 2; i++) - { - var posX1 = -_state.ViewportCenter.X; - var posY1 = i * _state.TileSize - _state.ViewportCenter.Y; - posX1 -= posX1 % _state.TileSize; - posY1 -= posY1 % _state.TileSize; - var posX2 = GraphicsDevice.Viewport.Width - _state.ViewportCenter.X; - var posY2 = i * _state.TileSize - _state.ViewportCenter.Y; - posX2 -= posX2 % _state.TileSize; - posY2 -= posY2 % _state.TileSize; - - _spriteBatch.DrawLine(posX1, posY1, - posX2, - posY2, - Settings.Instance.GridColor); - } - - - if (_state.ShowCellNumbers && _state.TileSize >= 30) - { - var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize / 8).Value ?? _fonts.Last().Value; - var fscale = 1f; - - for (var i = -1; i < visibleTilesX + 2; i++) - { - for (var j = -1; j < visibleTilesY + 2; j++) - { - var screenPosition = new Point(i * _state.TileSize - (int)_state.ViewportCenter.X, j * _state.TileSize - (int)_state.ViewportCenter.Y); - - var x = screenPosition.X / _state.TileSize; - var y = screenPosition.Y / _state.TileSize; - - _spriteBatch.DrawString(ffont, - $"{x}:{y}", - new Vector2( - x * _state.TileSize + 2, - y * _state.TileSize + 2 - ), - Color.Black, - 0, - Vector2.Zero, - fscale, - SpriteEffects.None, - 0); - } - } - } - } - private void DrawNotes() { - if (_state.TileSize < 30) - { - return; - } + if (_state.TileSize < 30) return; for (var i = 0; i < _sessionData.Notes.Values.Count; i++) { var note = _sessionData.Notes.Values.ElementAt(i); _spriteBatch.Draw( - _comment, - new Rectangle( - note.X * _state.TileSize + _state.TileSize - (int)(_state.TileSize / 2) + _state.TileSize / 25, - note.Y * _state.TileSize + _state.TileSize / 8 + _state.TileSize / 25, - (int)(_state.TileSize / 2.5), (int)(_state.TileSize / 2.5 / 1.136) - ), Color.Black * .2f - ); + _comment, + new Rectangle( + note.X * _state.TileSize + _state.TileSize - _state.TileSize / 2 + _state.TileSize / 25, + note.Y * _state.TileSize + _state.TileSize / 8 + _state.TileSize / 25, + (int)(_state.TileSize / 2.5), (int)(_state.TileSize / 2.5 / 1.136) + ), Color.Black * .2f + ); _spriteBatch.Draw( _comment, new Rectangle( - note.X * _state.TileSize + _state.TileSize - (int)(_state.TileSize / 2), - note.Y * _state.TileSize + _state.TileSize / 8, - (int)(_state.TileSize / 2.5), (int)(_state.TileSize / 2.5 / 1.136) + note.X * _state.TileSize + _state.TileSize - _state.TileSize / 2, + note.Y * _state.TileSize + _state.TileSize / 8, + (int)(_state.TileSize / 2.5), (int)(_state.TileSize / 2.5 / 1.136) ), Settings.Instance.NoteColor - ); + ); } } @@ -1180,8 +936,15 @@ namespace Sledgemapper posX = tile.X * _state.TileSize; posY = tile.Y * _state.TileSize; - _spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX + _state.TileSize / 25, posY + _state.TileSize / 25), spriteRec, Color.Black * .2f, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0); - _spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX, posY), spriteRec, Settings.Instance.OverlayTintColor, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0); + _spriteBatch.Draw(_spriteSheet.Texture, + new Vector2(posX + _state.TileSize / 25, posY + _state.TileSize / 25), spriteRec, + Color.Black * .2f, MathHelper.ToRadians(90 * tile.Rotation), + new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), + ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0); + _spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX, posY), spriteRec, + Settings.Instance.OverlayTintColor, MathHelper.ToRadians(90 * tile.Rotation), + new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), + ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0); } else { @@ -1189,15 +952,91 @@ namespace Sledgemapper posY = tile.Y * _state.TileSize + _state.TileSize / 2f; } - _spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX + _state.TileSize / 25, posY + _state.TileSize / 25), spriteRec, Color.Black * .2f, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0); - _spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX, posY), spriteRec, Settings.Instance.OverlayTintColor, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0); + _spriteBatch.Draw(_spriteSheet.Texture, + new Vector2(posX + _state.TileSize / 25, posY + _state.TileSize / 25), spriteRec, Color.Black * .2f, + MathHelper.ToRadians(90 * tile.Rotation), + new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), + ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0); + _spriteBatch.Draw(_spriteSheet.Texture, new Vector2(posX, posY), spriteRec, + Settings.Instance.OverlayTintColor, MathHelper.ToRadians(90 * tile.Rotation), + new Vector2(spriteRec.Value.Width / 2, spriteRec.Value.Height / 2), + ((float)_state.TileSize - 10) / spriteRec.Value.Width, SpriteEffects.None, 0); } } + private void DrawPingPointer(Ping ping, GameTime gameTime) + { + var durationMs = 2000f; + var baseRadius = _state.TileSize / 4f; + var baseOuterRadius = (float)_state.TileSize; + var iterations = 3f; + var validPointer = GetPointerVector(new Point(ping.X, ping.Y), out var points); + + if (validPointer) + { + _spriteBatch.DrawPolygon(Vector2.Zero, points, ping.Player.Color.ToColor(), 4); + + + for (var j = 0; j < iterations; j++) + { + var cycleTime = ((float)gameTime.TotalGameTime.TotalMilliseconds + j * durationMs / iterations) % + durationMs / durationMs; + var easing = Easings.Interpolate(cycleTime, Easings.Functions.SineEaseInOut); + var v2 = new Vector2[points.Length]; + + + var tCenter = new Vector2((points[0].X + points[1].X + points[2].X) / 3f, + (points[0].Y + points[1].Y + points[2].Y) / 3f); + + + for (var i1 = 0; i1 < v2.Length; i1++) + { + var svx = (points[i1].X - tCenter.X) * (1 + 2 * easing) + tCenter.X; + var svy = (points[i1].Y - tCenter.Y) * (1 + 2 * easing) + tCenter.Y; + v2[i1] = new Vector2(svx, svy); + } + + _spriteBatch.DrawPolygon( + Vector2.Zero, + v2, + new Color(ping.Player.Color.ToColor(), 1f - easing), + 2 + 2 * (1 - easing)); + } + } + } + + private void DrawPlayerOffline() + { + if (string.IsNullOrWhiteSpace(_sessionData.SessionName)) + { + var isoffscreen = IsOffscreen(_state.SelectedTile); + if (isoffscreen) + { + var validPointer = GetPointerVector(new Point(_state.SelectedTile.X, _state.SelectedTile.Y), + out var points); + if (validPointer) _spriteBatch.DrawPolygon(Vector2.Zero, points, Color.Red, 2); + } + else + { + _spriteBatch.DrawRectangle( + new Rectangle(_state.SelectedTile.X * _state.TileSize - 2, + _state.SelectedTile.Y * _state.TileSize - 2, _state.TileSize + 3, _state.TileSize + 3), + Color.Red, 2); + } + } + } + + private void DrawPlayerPointer(Player player) + { + var validPointer = GetPointerVector(new Point(player.Position.X, player.Position.Y), out var points); + if (validPointer) _spriteBatch.DrawPolygon(Vector2.Zero, points, player.Color.ToColor(), 2); + } + private void DrawPlayers() { - var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize).Value ?? _fonts.Last().Value; - var fscale = _state.TileSize / ((float)ffont.LineSpacing * 3f); + var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize).Value ?? + _fonts.Last().Value; + var fscale = _state.TileSize / (ffont.LineSpacing * 3f); var playerCells = _sessionData.Players.Select(m => m.Position).Distinct().ToList(); @@ -1253,6 +1092,7 @@ namespace Sledgemapper player.Position.X * _state.TileSize + _state.TileSize / 2 + 1, player.Position.Y * _state.TileSize + _state.TileSize - measure.Y * fscale); } + i++; } else if (playersInCell.Count >= 3) @@ -1306,239 +1146,92 @@ namespace Sledgemapper break; } + i++; } _spriteBatch.DrawRectangle(rectangle, color, 2); _spriteBatch.DrawString(ffont, - player.Initials, - stringPosition, - color, - 0, - Vector2.Zero, - fscale, - SpriteEffects.None, - 0); + player.Initials, + stringPosition, + color, + 0, + Vector2.Zero, + fscale, + SpriteEffects.None, + 0); } - } foreach (var player in _sessionData.Players) { var isOffscreen = IsOffscreen(player.Position); - if (isOffscreen) - { - DrawPlayerPointer(player); - } + if (isOffscreen) DrawPlayerPointer(player); } } - private void DrawPingPointer(Ping ping, GameTime gameTime) + private void DrawRipple(GameTime gameTime) { - var durationMs = 2000f; + _spriteBatch.Begin( + blendState: BlendState.NonPremultiplied, + transformMatrix: Matrix.CreateTranslation(_state.ViewportCenter)); + + var durationMs = 2000; var baseRadius = _state.TileSize / 4f; var baseOuterRadius = (float)_state.TileSize; var iterations = 3f; - var validPointer = GetPointerVector(new Point(ping.X, ping.Y), out var points); + var guids = _sessionData.Pings.Keys.ToArray(); - if (validPointer) + foreach (var guid in guids) { - _spriteBatch.DrawPolygon(Vector2.Zero, points, ping.Player.Color.ToColor(), 4); + var pingFound = _sessionData.Pings.TryGetValue(guid, out var ping); + if (!pingFound) continue; + if (ping.StartTime == 0) ping.StartTime = gameTime.TotalGameTime.TotalMilliseconds; - for (var j = 0; j < iterations; j++) + var x = ping.X * _state.TileSize + _state.TileSize / 2f; + var y = ping.Y * _state.TileSize + _state.TileSize / 2f; + + if (IsOffscreen(new Tile { X = ping.X, Y = ping.Y })) { - var cycleTime = (((float)gameTime.TotalGameTime.TotalMilliseconds + (float)j * durationMs / iterations) % durationMs) / durationMs; - var easing = Easings.Interpolate(cycleTime, Easings.Functions.SineEaseInOut); - var v2 = new Vector2[points.Length]; + DrawPingPointer(ping, gameTime); + } + else + { + _spriteBatch.DrawCircle( + new Vector2(x, y), + baseRadius, + 20, + ping.Player.Color.ToColor(), + baseRadius); - - var tCenter = new Vector2((points[0].X + points[1].X + points[2].X) / 3f, (points[0].Y + points[1].Y + points[2].Y) / 3f); - - - for (int i1 = 0; i1 < v2.Length; i1++) + for (var i = 0; i < iterations; i++) { - - var svx = ((points[i1].X - tCenter.X) * (1 + (2 * easing))) + tCenter.X; - var svy = ((points[i1].Y - tCenter.Y) * (1 + (2 * easing))) + tCenter.Y; - v2[i1] = new Vector2(svx, svy); + var cycleTime = + ((float)gameTime.TotalGameTime.TotalMilliseconds + (float)i * durationMs / iterations) % + durationMs / durationMs; + var easing = Easings.Interpolate(cycleTime, Easings.Functions.SineEaseInOut); + _spriteBatch.DrawCircle( + new Vector2(x, y), + baseRadius + baseOuterRadius * easing, + 20, + new Color(ping.Player.Color.ToColor(), 1 - easing), + 2 + 5 * (1 - easing)); } - - _spriteBatch.DrawPolygon( - offset: Vector2.Zero, - points: v2, - color: new Color(ping.Player.Color.ToColor(), 1f - easing), - thickness: 2 + 2 * (1 - easing)); - } - } - } - private bool GetPointerVector(Point target, out Vector2[] points) - { - var offset = _state.TileSize / 2; - var leftBound = 200 + offset; - var topBound = 75 + offset; - var bottomBound = 25 + offset; - var rightBound = offset; - points = new Vector2[0]; - var center = new Point((Window.ClientBounds.Width + leftBound) / 2 - (int)_state.ViewportCenter.X, Window.ClientBounds.Height / 2 - (int)_state.ViewportCenter.Y); - - // center - var p1 = new Vector2(center.X, center.Y); - - // point - var p2 = new Vector2( - target.X * _state.TileSize + offset, - target.Y * _state.TileSize + offset); - - // top right - var p3 = new Vector2( - Window.ClientBounds.Width - _state.ViewportCenter.X - rightBound, - topBound - _state.ViewportCenter.Y); - - //bottom right - var p4 = new Vector2( - Window.ClientBounds.Width - _state.ViewportCenter.X - rightBound, - Window.ClientBounds.Height - _state.ViewportCenter.Y - bottomBound); - - var ua1 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); - - p3 = new Vector2(leftBound - _state.ViewportCenter.X, topBound - _state.ViewportCenter.Y); - p4 = new Vector2(Window.ClientBounds.Width - _state.ViewportCenter.X, topBound - _state.ViewportCenter.Y); - var ua2 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); - - p3 = new Vector2(leftBound - _state.ViewportCenter.X, topBound - _state.ViewportCenter.Y); - p4 = new Vector2(leftBound - _state.ViewportCenter.X, Window.ClientBounds.Height - _state.ViewportCenter.Y - bottomBound); - var ua3 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); - - p3 = new Vector2(leftBound - _state.ViewportCenter.X, Window.ClientBounds.Height - _state.ViewportCenter.Y - bottomBound); - p4 = new Vector2(Window.ClientBounds.Width - _state.ViewportCenter.X, Window.ClientBounds.Height - _state.ViewportCenter.Y - bottomBound); - var ua4 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); - - var uas = new List { ua1, ua2, ua3, ua4 }; - if (uas.Any(u => u > 0 && u < 1)) + foreach (var guid in guids) { - var ua = uas.Where(u => u > 0 && u < 1).Min(); - var i = uas.IndexOf(ua); - var x = (p1.X + ua * (p2.X - p1.X)); - var y = (p1.Y + ua * (p2.Y - p1.Y)); + var pingFound = _sessionData.Pings.TryGetValue(guid, out var ping); + if (!pingFound) continue; - switch (i) - { - case 0: - x += offset; - points = new Vector2[] { new Vector2(x, y), new Vector2(x - 20, y - 10), new Vector2(x - 20, y + 10), new Vector2(x, y) }; - break; - case 1: - y -= offset; - points = new Vector2[] { new Vector2(x, y), new Vector2(x - 10, y + 20), new Vector2(x + 10, y + 20), new Vector2(x, y) }; - break; - case 2: - x -= offset; - points = new Vector2[] { new Vector2(x, y), new Vector2(x + 20, y + 10), new Vector2(x + 20, y - 10), new Vector2(x, y) }; - break; - case 3: - y += offset; - points = new Vector2[] { new Vector2(x, y), new Vector2(x + 10, y - 20), new Vector2(x - 10, y - 20), new Vector2(x, y) }; - break; - } - return true; - } - return false; - } - - private void DrawPlayerPointer(Player player) - { - var validPointer = GetPointerVector(new Point(player.Position.X, player.Position.Y), out var points); - if (validPointer) - { - _spriteBatch.DrawPolygon(Vector2.Zero, points, player.Color.ToColor(), 2); - } - } - - private bool IsOffscreen(Tile position) - { - var boxTL = new Point(200 - _state.TileSize / 2, 75 - _state.TileSize / 2); - var boxBR = new Point(GraphicsDevice.Viewport.Width + _state.TileSize / 2, GraphicsDevice.Viewport.Height - 25 + _state.TileSize / 2); - - var tileTL = new Point(position.X * _state.TileSize + (int)_state.ViewportCenter.X, position.Y * _state.TileSize + (int)_state.ViewportCenter.Y); - var tileBR = new Point(position.X * _state.TileSize + (int)_state.ViewportCenter.X + _state.TileSize, position.Y * _state.TileSize + (int)_state.ViewportCenter.Y + _state.TileSize); - - if (tileTL.X <= boxTL.X || tileTL.Y <= boxTL.Y || tileBR.X >= boxBR.X || tileBR.Y >= boxBR.Y) - { - return true; + if (gameTime.TotalGameTime.TotalMilliseconds - ping.StartTime > Settings.Instance.PingDuration) + _sessionData.Pings.TryRemove(guid, out var _); } - return false; - } - private void DrawTiles() - { - for (var i = 0; i < _sessionData.Map.Values.Count; i++) - { - var tile = _sessionData.Map.Values.ElementAt(i); - var content = Content.Load($"tiles/{tile.ID}"); - - var posX = tile.X * _state.TileSize + _state.TileSize / 2f; - var posY = tile.Y * _state.TileSize + _state.TileSize / 2f; - - _spriteBatch.Draw(content, new Vector2(posX, posY), - null, Color.White, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_state.TileSize) / content.Width, SpriteEffects.None, 0); - } - } - - private void DrawLine(Line tile) - { - var posX = tile.Start.X * _state.TileSize; - var posY = tile.Start.Y * _state.TileSize; - - var endposX = tile.End.X * _state.TileSize; - var endposY = tile.End.Y * _state.TileSize; - - switch (tile.Start.Index) - { - case 1: - break; - case 2: - posX += _state.TileSize / 2; - break; - case 3: - posY += _state.TileSize / 2; - - break; - case 4: - posX += _state.TileSize / 2; - posY += _state.TileSize / 2; - break; - } - - switch (tile.End.Index) - { - case 1: - break; - case 2: - endposX += _state.TileSize / 2; - break; - case 3: - endposY += _state.TileSize / 2; - - break; - case 4: - endposX += _state.TileSize / 2; - endposY += _state.TileSize / 2; - break; - } - - var length = (int)Math.Sqrt(Math.Pow(posX - endposX, 2) + Math.Pow(posY - endposY, 2)); - var height = (int)(_state.TileSize * tile.Width); - if (length > 0) - { - var angle = Math.Atan2(posY - endposY, endposX - posX); - var angleRad = -(float)angle; - _spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, length, height), null, Color.White, angleRad, new Vector2(0, 0), SpriteEffects.None, 1); - } + _spriteBatch.End(); } private void DrawRoom(Room tile) @@ -1585,106 +1278,243 @@ namespace Sledgemapper if (posX != endposX && posY != endposY) { - - - if ((posX < endposX && posY < endposY)) + if (posX < endposX && posY < endposY) { - _spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, endposX - posX, endposY - posY), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1); + _spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, endposX - posX, endposY - posY), null, + Color.White, 0, Vector2.Zero, SpriteEffects.None, 1); } - else if ((posX > endposX && posY > endposY)) + else if (posX > endposX && posY > endposY) { - _spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, endposX - posX, endposY - posY), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1); + _spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, posY, endposX - posX, endposY - posY), null, + Color.White, 0, Vector2.Zero, SpriteEffects.None, 1); } else { if (endposY < posY) - { - _spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, endposY, endposX - posX, posY - endposY), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1); - } + _spriteBatch.Draw(_whiteRectangle, new Rectangle(posX, endposY, endposX - posX, posY - endposY), + null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1); if (endposX < posX) + _spriteBatch.Draw(_whiteRectangle, new Rectangle(endposX, posY, posX - endposX, endposY - posY), + null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1); + } + } + } + + private void DrawRoomPreview() + { + if ((_state.InsertMode == InsertMode.NewRoom || _state.InsertMode == InsertMode.NewDelete) && + _state.SelectedSnapPoint != null) + { + var snapPoint = new Vector2(_state.SelectedSnapPoint.X * _state.TileSize, + _state.SelectedSnapPoint.Y * _state.TileSize); + + switch (_state.SelectedSnapPoint.Index) + { + case 1: + break; + case 2: + snapPoint.X += _state.TileSize / 2; + break; + case 3: + snapPoint.Y += _state.TileSize / 2; + break; + case 4: + snapPoint.Y += _state.TileSize / 2; + snapPoint.X += _state.TileSize / 2; + break; + } + + _spriteBatch.DrawCircle(snapPoint, _state.TileSize / 6f, 50, Color.Red, 2); + + if (_state.LineStart != null) + { + var posX = _state.LineStart.X * _state.TileSize; + var posY = _state.LineStart.Y * _state.TileSize; + + var endposX = _state.SelectedSnapPoint.X * _state.TileSize; + var endposY = _state.SelectedSnapPoint.Y * _state.TileSize; + if (_state.InsertMode == InsertMode.NewDelete) { - _spriteBatch.Draw(_whiteRectangle, new Rectangle(endposX, posY, posX - endposX, endposY - posY), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 1); + var ww = _state.TileSize / Settings.Instance.TileDeleteDivider; + if (posX == endposX) + { + endposX += ww; + posX -= ww; + } + + if (posY == endposY) + { + endposY += ww; + posY -= ww; + } + } + + switch (_state.LineStart.Index) + { + case 1: + break; + case 2: + posX += _state.TileSize / 2; + break; + case 3: + posY += _state.TileSize / 2; + + break; + case 4: + posX += _state.TileSize / 2; + posY += _state.TileSize / 2; + break; + } + + switch (_state.SelectedSnapPoint.Index) + { + case 1: + break; + case 2: + endposX += _state.TileSize / 2; + break; + case 3: + endposY += _state.TileSize / 2; + + break; + case 4: + endposX += _state.TileSize / 2; + endposY += _state.TileSize / 2; + break; + } + + var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state.TileSize / 3) + .Value ?? _fonts.Last().Value; + var fscale = 1.2f; + var width = Math.Abs(endposX - posX); + var height = Math.Abs(posY - endposY); + var tilesWidth = width / (double)_state.TileSize; + var tilesHeight = height / (double)_state.TileSize; + tilesWidth = Math.Round(tilesWidth * 2, MidpointRounding.AwayFromZero) / 2; + tilesHeight = Math.Round(tilesHeight * 2, MidpointRounding.AwayFromZero) / 2; + var xmeasure = ffont.MeasureString($"{tilesWidth}"); + var ymeasure = ffont.MeasureString($"{tilesHeight}"); + float widthX = 0, widthY = 0, heightX = 0, heightY = 0; + + var area = new Rectangle(); + if (posX != endposX && posY != endposY) + { + if (posX > endposX && posY > endposY || posX < endposX && posY < endposY) + { + area = new Rectangle(posX, posY, endposX - posX, endposY - posY); + + if (posX > endposX && posY > endposY) + { + widthX = endposX + width / 2 - xmeasure.X / 2; + widthY = endposY - ymeasure.Y * 1.2f; + + heightX = posX + xmeasure.X / 2; + heightY = endposY + height / 2 - ymeasure.Y / 2; + } + else if (posX < endposX && posY < endposY) + { + widthX = posX + width / 2 - xmeasure.X / 2; + widthY = posY - ymeasure.Y * 1.2f; + + heightX = endposX + xmeasure.X / 2; + heightY = posY + height / 2 - ymeasure.Y / 2; + } + } + else + { + if (endposY < posY) + { + area = new Rectangle(posX, endposY, endposX - posX, posY - endposY); + + widthX = posX + width / 2 - xmeasure.X / 2; + widthY = endposY - ymeasure.Y * 1.2f; + + heightX = endposX + xmeasure.X / 2; + heightY = endposY + height / 2 - ymeasure.Y / 2; + } + + if (endposX < posX) + { + area = new Rectangle(endposX, posY, posX - endposX, endposY - posY); + + widthX = endposX + width / 2 - xmeasure.X / 2; + widthY = posY - ymeasure.Y * 1.2f; + + heightX = posX + xmeasure.X / 2; + heightY = posY + height / 2 - ymeasure.Y / 2; + } + } + + _spriteBatch.Draw(_transparentRedRectangle, area, null, Color.White, 0, new Vector2(0, 0), + SpriteEffects.None, 1); + + _spriteBatch.DrawString(ffont, + $"{tilesWidth}", + new Vector2( + widthX, + widthY + ), + Color.Red, + 0, + Vector2.Zero, + fscale, + SpriteEffects.None, + 0); + + _spriteBatch.DrawString(ffont, + $"{tilesHeight}", + new Vector2( + heightX, heightY + ), + Color.Red, + 0, + Vector2.Zero, + fscale, + SpriteEffects.None, + 0); } } } } - private void DrawDelete(Room tile) + private void DrawSelectedIntersection() { - var posX = tile.Start.X * _state.TileSize; - var posY = tile.Start.Y * _state.TileSize; - - var endposX = tile.End.X * _state.TileSize; - var endposY = tile.End.Y * _state.TileSize; - - - var ww = _state.TileSize / Settings.Instance.TileDeleteDivider; - if (posX == endposX) { endposX += ww; posX -= ww; } - if (posY == endposY) { endposY += ww; posY -= ww; } - switch (tile.Start.Index) + if (_state.InsertMode == InsertMode.Overlay && _state.SelectedOverlay.Intersection) { - case 1: - break; - case 2: - posX += _state.TileSize / 2; - break; - case 3: - posY += _state.TileSize / 2; - - break; - case 4: - posX += _state.TileSize / 2; - posY += _state.TileSize / 2; - break; + var overlay = new Vector2(_state.SelectedOverlay.X * _state.TileSize, + _state.SelectedOverlay.Y * _state.TileSize); + _spriteBatch.DrawCircle(overlay, _state.TileSize / 3f, 100, Color.Red, 2); } + } - switch (tile.End.Index) + private void DrawSelectedWall() + { + if (_state.InsertMode == InsertMode.Wall) { - case 1: - break; - case 2: - endposX += _state.TileSize / 2; - break; - case 3: - endposY += _state.TileSize / 2; - - break; - case 4: - endposX += _state.TileSize / 2; - endposY += _state.TileSize / 2; - break; + var startWall = new Vector2(_state.SelectedWall.X * _state.TileSize, + _state.SelectedWall.Y * _state.TileSize); + _spriteBatch.DrawLine(startWall, _state.TileSize, + MathHelper.ToRadians(90 * _state.SelectedWall.Rotation), Color.Red, 2); } + } - if (posX != endposX && posY != endposY) + private void DrawTiles() + { + for (var i = 0; i < _sessionData.Map.Values.Count; i++) { - Rectangle r = new Rectangle(); + var tile = _sessionData.Map.Values.ElementAt(i); + var content = Content.Load($"tiles/{tile.ID}"); - if ((posX < endposX && posY < endposY)) - { - - r = new Rectangle(posX, posY, endposX - posX, endposY - posY); - } - else if ((posX > endposX && posY > endposY)) - { - r = new Rectangle(posX, posY, endposX - posX, endposY - posY); - } - else - { - if (endposY < posY) - { - r = new Rectangle(posX, endposY, endposX - posX, posY - endposY); - } - if (endposX < posX) - { - r = new Rectangle(endposX, posY, posX - endposX, endposY - posY); - } - } - - _spriteBatch.Draw(_whiteRectangle, r, null, Color.Black, 0, Vector2.Zero, SpriteEffects.None, 1); + var posX = tile.X * _state.TileSize + _state.TileSize / 2f; + var posY = tile.Y * _state.TileSize + _state.TileSize / 2f; + _spriteBatch.Draw(content, new Vector2(posX, posY), + null, Color.White, MathHelper.ToRadians(90 * tile.Rotation), + new Vector2(content.Width / 2, content.Height / 2), (float)_state.TileSize / content.Width, + SpriteEffects.None, 0); } } @@ -1699,21 +1529,172 @@ namespace Sledgemapper var posX = wall.X * _state.TileSize; var posY = wall.Y * _state.TileSize; if (wall.Rotation == 1) - { posX -= (int)offset; - } - else if (wall.Rotation == 0) - { - posY += (int)offset; - } - _spriteBatch.Draw(content, new Vector2(posX, posY), null, Color.White, MathHelper.ToRadians(90 * (wall.Rotation - 1)), new Vector2(0, 0), scale, SpriteEffects.None, 0); + else if (wall.Rotation == 0) posY += (int)offset; + _spriteBatch.Draw(content, new Vector2(posX, posY), null, Color.White, + MathHelper.ToRadians(90 * (wall.Rotation - 1)), new Vector2(0, 0), scale, SpriteEffects.None, 0); } } - private void OnContextMenuNewNoteClick(object sender, EventArgs e) + private void EditNote(Note note) { - _desktop.HideContextMenu(); - new NoteWindow(_communicationManager, new Note()).ShowInModalWindow(_desktop, $" Note on {_state.HoveredTile.X}:{_state.HoveredTile.Y}"); + _state.SelectedNote = new Note { X = note.X, Y = note.Y, Text = note.Text }; + new NoteWindow(_communicationManager, note).ShowInModalWindow(_desktop, $" Note on {note.X}:{note.Y}"); + } + + private bool GetPointerVector(Point target, out Vector2[] points) + { + var offset = _state.TileSize / 2; + var leftBound = 200 + offset; + var topBound = 75 + offset; + var bottomBound = 25 + offset; + var rightBound = offset; + points = Array.Empty(); + var center = new Point((Window.ClientBounds.Width + leftBound) / 2 - (int)_state.ViewportCenter.X, + Window.ClientBounds.Height / 2 - (int)_state.ViewportCenter.Y); + + // center + var p1 = new Vector2(center.X, center.Y); + + // point + var p2 = new Vector2( + target.X * _state.TileSize + offset, + target.Y * _state.TileSize + offset); + + // top right + var p3 = new Vector2( + Window.ClientBounds.Width - _state.ViewportCenter.X - rightBound, + topBound - _state.ViewportCenter.Y); + + //bottom right + var p4 = new Vector2( + Window.ClientBounds.Width - _state.ViewportCenter.X - rightBound, + Window.ClientBounds.Height - _state.ViewportCenter.Y - bottomBound); + + var ua1 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / + ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); + + p3 = new Vector2(leftBound - _state.ViewportCenter.X, topBound - _state.ViewportCenter.Y); + p4 = new Vector2(Window.ClientBounds.Width - _state.ViewportCenter.X, topBound - _state.ViewportCenter.Y); + var ua2 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / + ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); + + p3 = new Vector2(leftBound - _state.ViewportCenter.X, topBound - _state.ViewportCenter.Y); + p4 = new Vector2(leftBound - _state.ViewportCenter.X, + Window.ClientBounds.Height - _state.ViewportCenter.Y - bottomBound); + var ua3 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / + ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); + + p3 = new Vector2(leftBound - _state.ViewportCenter.X, + Window.ClientBounds.Height - _state.ViewportCenter.Y - bottomBound); + p4 = new Vector2(Window.ClientBounds.Width - _state.ViewportCenter.X, + Window.ClientBounds.Height - _state.ViewportCenter.Y - bottomBound); + var ua4 = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / + ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); + + var uas = new List { ua1, ua2, ua3, ua4 }; + if (uas.Any(u => u > 0 && u < 1)) + { + var ua = uas.Where(u => u > 0 && u < 1).Min(); + var i = uas.IndexOf(ua); + var x = p1.X + ua * (p2.X - p1.X); + var y = p1.Y + ua * (p2.Y - p1.Y); + + switch (i) + { + case 0: + x += offset; + points = new[] + { new(x, y), new Vector2(x - 20, y - 10), new Vector2(x - 20, y + 10), new Vector2(x, y) }; + break; + case 1: + y -= offset; + points = new[] + { new(x, y), new Vector2(x - 10, y + 20), new Vector2(x + 10, y + 20), new Vector2(x, y) }; + break; + case 2: + x -= offset; + points = new[] + { new(x, y), new Vector2(x + 20, y + 10), new Vector2(x + 20, y - 10), new Vector2(x, y) }; + break; + case 3: + y += offset; + points = new[] + { new(x, y), new Vector2(x + 10, y - 20), new Vector2(x - 10, y - 20), new Vector2(x, y) }; + break; + } + + return true; + } + + return false; + } + + private bool IsMapElementOffscreen(BaseMapEntity item) + { + SnapPoint start, end; + + switch (item) + { + case Line l: + start = l.Start; + end = l.End; + break; + + case Room room: + start = room.Start; + end = room.End; + break; + default: + return true; + } + + var visibleTilesX = GraphicsDevice.Viewport.Width / _state.TileSize + 1; + var visibleTilesY = GraphicsDevice.Viewport.Height / _state.TileSize + 1; + + var screenPositionTopLeft = + new Point(200 - _state.TileSize + 0 * _state.TileSize - (int)_state.ViewportCenter.X, + 0 * _state.TileSize + _state.TileSize - (int)_state.ViewportCenter.Y); + var screenPositionBottomRight = new Point(visibleTilesX * _state.TileSize - (int)_state.ViewportCenter.X, + visibleTilesY * _state.TileSize - 20 - (int)_state.ViewportCenter.Y); + var tileTopLeft = new Point(screenPositionTopLeft.X / _state.TileSize, + screenPositionTopLeft.Y / _state.TileSize); + var tileBottomRight = new Point(screenPositionBottomRight.X / _state.TileSize, + screenPositionBottomRight.Y / _state.TileSize); + + if (start.X < tileTopLeft.X && start.Y < tileTopLeft.Y && start.X > tileBottomRight.X && + start.Y > tileBottomRight.Y && + end.X < tileTopLeft.X && end.Y < tileTopLeft.Y && end.X > tileBottomRight.X && end.Y > tileBottomRight.Y + ) + return true; + return false; + } + + private bool IsOffscreen(Tile position) + { + var boxTL = new Point(200 - _state.TileSize / 2, 75 - _state.TileSize / 2); + var boxBR = new Point(GraphicsDevice.Viewport.Width + _state.TileSize / 2, + GraphicsDevice.Viewport.Height - 25 + _state.TileSize / 2); + + var tileTL = new Point(position.X * _state.TileSize + (int)_state.ViewportCenter.X, + position.Y * _state.TileSize + (int)_state.ViewportCenter.Y); + var tileBR = new Point(position.X * _state.TileSize + (int)_state.ViewportCenter.X + _state.TileSize, + position.Y * _state.TileSize + (int)_state.ViewportCenter.Y + _state.TileSize); + + return tileTL.X <= boxTL.X || tileTL.Y <= boxTL.Y || tileBR.X >= boxBR.X || tileBR.Y >= boxBR.Y; + } + + private void OnClientSizeChanged(object sender, EventArgs e) + { + _renderTarget?.Dispose(); + try + { + ResetRenderTarget(); + } + catch + { + Console.WriteLine("rendertarget dispose exception"); + } } private void OnContextMenuDeleteNoteClick(object sender, EventArgs e) @@ -1722,28 +1703,95 @@ namespace Sledgemapper _sessionData.DeleteNote(_state.SelectedNote); } + private void OnContextMenuNewNoteClick(object sender, EventArgs e) + { + _desktop.HideContextMenu(); + new NoteWindow(_communicationManager, new Note()).ShowInModalWindow(_desktop, + $" Note on {_state.HoveredTile.X}:{_state.HoveredTile.Y}"); + } + + private void OnContextMenuPingClick(object sender, EventArgs e, Tile location) + { + _desktop.HideContextMenu(); + _communicationManager.Ping(location).SafeFireAndForget(); + } + private void OnContextMenuViewNoteClick(object sender, EventArgs e) { _desktop.HideContextMenu(); EditNote(_state.SelectedNote); } + private async Task OnHubDisconnected(Exception arg) + { + // ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Hub disconnected", Type = "SignalR Client Events", Source = _settings.MachineName }); + _mainWidget.lblConnectionStatus.Text = "Disconnected"; + await Task.Yield(); + } + + private async Task OnHubReconnected(string arg) + { + // ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Hub reconnected", Type = "SignalR Client Events", Source = _settings.MachineName }); + _mainWidget.lblConnectionStatus.Text = "Connected"; + await Task.Yield(); + } + + private async Task OnHubReconnecting(Exception arg) + { + // ExceptionlessClient.Default.SubmitEvent(new Event { Message = "Reconnecting Hub", Type = "SignalR Client Events", Source = _settings.MachineName }); + _mainWidget.lblConnectionStatus.Text = "Reconnecting"; + await Task.Yield(); + } + private void OnOverlayButtonClicked(object sender, EventArgs e) { _state.CurrentOverlayId = ((ImageButton)sender).Id; _mainWidget.ClearSelection(); ((ImageButton)sender).Border = new SolidBrush(Color.Red); - ((ImageButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2); + ((ImageButton)sender).BorderThickness = new Thickness(2); _state.InsertMode = InsertMode.Overlay; } + private void OnTileButtonTouchEntered(object sender, EventArgs e) + { + var mouseState = Mouse.GetState().Position; + mouseState.X += 10; + mouseState.Y += 10; + _lblOverlayName.Visible = true; + _lblOverlayName.Text = ((ImageButton)sender).Id; + _desktop.ShowContextMenu(_lblOverlayName, mouseState); + } + + private void OnTileButtonTouchLeft(object sender, EventArgs e) + { + _desktop.HideContextMenu(); + _lblOverlayName.Visible = false; + } + + private void OnTxtOverlaySearchChange(object sender, ValueChangedEventArgs e) + { + AddItemToToolGrid(_mainWidget.GridOverlays, OnOverlayButtonClicked, _spriteSheet, e.NewValue); + } + private void OnWallButtonClicked(object sender, EventArgs e) { _state.CurrentWallId = ((ImageButton)sender).Id; _mainWidget.ClearSelection(); ((ImageButton)sender).Border = new SolidBrush(Color.Red); - ((ImageButton)sender).BorderThickness = new Myra.Graphics2D.Thickness(2); + ((ImageButton)sender).BorderThickness = new Thickness(2); _state.InsertMode = InsertMode.Wall; } + + private void ResetRenderTarget() + { + _renderTarget = new RenderTarget2D(GraphicsDevice, + GraphicsDevice.Viewport.Width, + GraphicsDevice.Viewport.Height, + false, + SurfaceFormat.Color, + DepthFormat.None, + 0, + RenderTargetUsage.DiscardContents); + } } -} +} \ No newline at end of file diff --git a/Sledgemapper/State.cs b/Sledgemapper/State.cs index 91a9f40..c5aa3ac 100644 --- a/Sledgemapper/State.cs +++ b/Sledgemapper/State.cs @@ -6,7 +6,7 @@ namespace Sledgemapper { public sealed class State { - private static readonly State instance = new State(); + private static readonly State instance = new (); public Tile SelectedTile { get; set; } public Tile HoveredTile { get; set; } diff --git a/Sledgemapper/UI/CampaignWindow.Custom.cs b/Sledgemapper/UI/CampaignWindow.Custom.cs index 6b4b313..0689349 100644 --- a/Sledgemapper/UI/CampaignWindow.Custom.cs +++ b/Sledgemapper/UI/CampaignWindow.Custom.cs @@ -1,4 +1,3 @@ -using Myra.Graphics2D.UI; using Sentry; using System; using TinyMessenger; diff --git a/Sledgemapper/UI/MainWidget.Custom.cs b/Sledgemapper/UI/MainWidget.Custom.cs index 258770f..2ab6d0d 100644 --- a/Sledgemapper/UI/MainWidget.Custom.cs +++ b/Sledgemapper/UI/MainWidget.Custom.cs @@ -5,7 +5,6 @@ using Myra.Graphics2D.UI; using Myra.Graphics2D.UI.File; using Myra.Graphics2D.UI.Properties; using Newtonsoft.Json; -using Sentry; using Sledgemapper.Messages; using Sledgemapper.Shared.Entities; using System; diff --git a/Sledgemapper/UI/MapList.Custom.cs b/Sledgemapper/UI/MapList.Custom.cs index aee9fd5..5bda61e 100644 --- a/Sledgemapper/UI/MapList.Custom.cs +++ b/Sledgemapper/UI/MapList.Custom.cs @@ -2,7 +2,6 @@ using Myra.Graphics2D.Brushes; using Myra.Graphics2D.UI; using Sledgemapper.Messages; -using Sledgemapper.Shared.Entities; using System; using System.Threading.Tasks; using TinyMessenger; diff --git a/Sledgemapper/UI/MapWindow.cs b/Sledgemapper/UI/MapWindow.cs index a386270..e94fa07 100644 --- a/Sledgemapper/UI/MapWindow.cs +++ b/Sledgemapper/UI/MapWindow.cs @@ -1,7 +1,4 @@ /* Generated by MyraPad at 02/09/2021 16:26:04 */ -using Myra.Graphics2D.UI; -using Sentry; -using System; namespace Sledgemapper.UI { diff --git a/Sledgemapper/UI/NoteList.Custom.cs b/Sledgemapper/UI/NoteList.Custom.cs index 919cc33..2905ea3 100644 --- a/Sledgemapper/UI/NoteList.Custom.cs +++ b/Sledgemapper/UI/NoteList.Custom.cs @@ -1,7 +1,6 @@ /* Generated by MyraPad at 01/12/2020 11:46:54 */ using System.Linq; using Myra.Graphics2D.TextureAtlases; -using Myra.Graphics2D.UI; using Sledgemapper.Messages; using Sledgemapper.Shared.Entities; using TinyMessenger; @@ -22,7 +21,7 @@ namespace Sledgemapper.UI { var note = CommunicationManager.SessionData.Notes.Values.ElementAt(i); var item = new NoteListItem(); - item.LblNoteText.Text = $"{note.ToString()} - {note.Text}"; + item.LblNoteText.Text = $"{note} - {note.Text}"; item.BtnNoteCenter.Image = new TextureRegion(CachedContent.Instance.Location); item.BtnNoteView.Image = new TextureRegion(CachedContent.Instance.Eye); item.BtnNoteCenter.Click += (s, e) => diff --git a/Sledgemapper/UI/PlayerList.Custom.cs b/Sledgemapper/UI/PlayerList.Custom.cs index 8389fea..2c6e72e 100644 --- a/Sledgemapper/UI/PlayerList.Custom.cs +++ b/Sledgemapper/UI/PlayerList.Custom.cs @@ -1,5 +1,5 @@ /* Generated by MyraPad at 28/08/2021 19:49:08 */ -using Myra.Graphics2D.UI; + using System.Threading.Tasks; namespace Sledgemapper.UI