diff --git a/Sledgemapper.Api/Hubs/SledgemapperHub.cs b/Sledgemapper.Api/Hubs/SledgemapperHub.cs index d8a5134..3fd5f67 100644 --- a/Sledgemapper.Api/Hubs/SledgemapperHub.cs +++ b/Sledgemapper.Api/Hubs/SledgemapperHub.cs @@ -15,12 +15,8 @@ namespace SignalRChat.Hubs { public class SledgemapperHub : Hub { - private readonly IMediator _mediator; - private readonly MyDbContext _dbcontext; - - // public SledgemapperHub(IMediator mediator) => _mediator = mediator; - public SledgemapperHub(MyDbContext dbcontext, IMediator mediator) { _dbcontext = dbcontext; _mediator = mediator; } - private static Dictionary _sessions = new Dictionary(); + public SledgemapperHub() { } + private static Dictionary _sessions = new Dictionary(); public List Colors = new List{"CC0000", "CC3300", "FFCC00", @@ -33,86 +29,86 @@ namespace SignalRChat.Hubs public async Task NewTile(string sessionName, Tile tile) { - var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + // var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - var existingTile = _sessions[sessionName].Map.TryGetValue(tile.ToString(), out var t); - if (existingTile) - { - _sessions[sessionName].Map.TryRemove(t.ToString(), out var rtile); - } - _sessions[sessionName].Map.TryAdd(tile.ToString(), tile); + // var existingTile = _sessions[sessionName].Map.TryGetValue(tile.ToString(), out var t); + // if (existingTile) + // { + // _sessions[sessionName].Map.TryRemove(t.ToString(), out var rtile); + // } + // _sessions[sessionName].Map.TryAdd(tile.ToString(), tile); - var jsonString = JsonSerializer.Serialize(tile); + // var jsonString = JsonSerializer.Serialize(tile); - _dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog - { - Operation = "N", - SessionName = sessionName, - Type = "T", - Timestamp = timestamp, - Object = jsonString - }); - await _dbcontext.SaveChangesAsync(); + // _dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog + // { + // Operation = "N", + // SessionName = sessionName, + // Type = "T", + // Timestamp = timestamp, + // Object = jsonString + // }); + // await _dbcontext.SaveChangesAsync(); await Clients.Group(sessionName).NewTile(tile); } public async Task NewWall(string sessionName, Wall tile) { - var existingTile = _sessions[sessionName].Walls.TryGetValue(tile.ToString(), out var t); - if (existingTile) - { - _sessions[sessionName].Walls.TryRemove(t.ToString(), out var rtile); - } - _sessions[sessionName].Walls.TryAdd(tile.ToString(), tile); + // var existingTile = _sessions[sessionName].Walls.TryGetValue(tile.ToString(), out var t); + // if (existingTile) + // { + // _sessions[sessionName].Walls.TryRemove(t.ToString(), out var rtile); + // } + // _sessions[sessionName].Walls.TryAdd(tile.ToString(), tile); await Clients.Group(sessionName).NewWall(tile); } public async Task NewOverlay(string sessionName, Overlay tile) { - var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - var existingTile = _sessions[sessionName].Overlays.TryGetValue(tile.ToString(), out var t); - if (existingTile) - { - _sessions[sessionName].Overlays.TryRemove(t.ToString(), out var rtile); - } - _sessions[sessionName].Overlays.TryAdd(tile.ToString(), tile); - var jsonString = JsonSerializer.Serialize(tile); + // var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + // var existingTile = _sessions[sessionName].Overlays.TryGetValue(tile.ToString(), out var t); + // if (existingTile) + // { + // _sessions[sessionName].Overlays.TryRemove(t.ToString(), out var rtile); + // } + // _sessions[sessionName].Overlays.TryAdd(tile.ToString(), tile); + // var jsonString = JsonSerializer.Serialize(tile); - _dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog - { - Operation = "N", - SessionName = sessionName, - Type = "O", - Timestamp = timestamp, - Object = jsonString - }); - await _dbcontext.SaveChangesAsync(); + // _dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog + // { + // Operation = "N", + // SessionName = sessionName, + // Type = "O", + // Timestamp = timestamp, + // Object = jsonString + // }); + // await _dbcontext.SaveChangesAsync(); await Clients.Group(sessionName).NewOverlay(tile); } public async Task DeleteTile(string sessionName, Tile tile) { - _sessions[sessionName].Map.TryRemove(tile.ToString(), out var rtile); + // _sessions[sessionName].Map.TryRemove(tile.ToString(), out var rtile); await Clients.Group(sessionName).DeleteTile(tile); } public async Task DeleteWall(string sessionName, Wall tile) { - _sessions[sessionName].Walls.TryRemove(tile.ToString(), out var rtile); + //_sessions[sessionName].Walls.TryRemove(tile.ToString(), out var rtile); await Clients.Group(sessionName).DeleteWall(tile); } public async Task DeleteOverlay(string sessionName, Overlay tile) { - _sessions[sessionName].Overlays.TryRemove(tile.ToString(), out var rtile); + //_sessions[sessionName].Overlays.TryRemove(tile.ToString(), out var rtile); await Clients.Group(sessionName).DeleteOverlay(tile); } - public async Task NewSession(string sessionName, string initials) + public async Task NewSession(string sessionName, string initials) { - var session = new SessionData(); + var session = new Session(); session.Colors = new List(Colors); session.Colors.Shuffle(); var player = new Player { Position = new Tile { X = 0, Y = 0 }, ConnectionId = Context.ConnectionId, Color = session.Colors[0], Initials = initials }; @@ -124,7 +120,7 @@ namespace SignalRChat.Hubs return session; } - public async Task JoinSession(string sessionName, string initials) + public async Task JoinSession(string sessionName, string initials) { if (_sessions.ContainsKey(sessionName)) { @@ -148,12 +144,12 @@ namespace SignalRChat.Hubs await Clients.Group(sessionName).PlayerUpdate(player); } - public async Task Refresh(string sessionName) + public async Task Refresh(string sessionName) { return _sessions[sessionName]; } - public async Task Sync(string sessionName, SessionData map) + public async Task Sync(string sessionName, Session map) { _sessions[sessionName].Map = map.Map; _sessions[sessionName].Overlays = map.Overlays; diff --git a/Sledgemapper.Shared/Clients/ISledgemapperClient.cs b/Sledgemapper.Shared/Clients/ISledgemapperClient.cs index dc78f9e..f9d56b7 100644 --- a/Sledgemapper.Shared/Clients/ISledgemapperClient.cs +++ b/Sledgemapper.Shared/Clients/ISledgemapperClient.cs @@ -14,6 +14,6 @@ namespace Sledgemapper.Clients Task DeleteOverlay(Overlay overlay); Task NewPlayer(Player player); Task PlayerUpdate(Player player); - Task UpdateMap(SessionData player); + Task UpdateMap(Session player); } } diff --git a/Sledgemapper.Shared/Entities/Overlay.cs b/Sledgemapper.Shared/Entities/Overlay.cs index ffe2171..f15213b 100644 --- a/Sledgemapper.Shared/Entities/Overlay.cs +++ b/Sledgemapper.Shared/Entities/Overlay.cs @@ -1,12 +1,8 @@ namespace Sledgemapper.Shared.Entities { - public class Overlay + public class Overlay :BaseMapEntity { - public int X { get; set; } - public int Y { get; set; } - public string ID { get; set; } public bool Intersection { get; set; } - public int Rotation { get; set; } public override string ToString() { diff --git a/Sledgemapper.Shared/Entities/SessionData.cs b/Sledgemapper.Shared/Entities/Session.cs similarity index 55% rename from Sledgemapper.Shared/Entities/SessionData.cs rename to Sledgemapper.Shared/Entities/Session.cs index 5df2ec2..9f3924d 100644 --- a/Sledgemapper.Shared/Entities/SessionData.cs +++ b/Sledgemapper.Shared/Entities/Session.cs @@ -4,52 +4,24 @@ using System; namespace Sledgemapper.Shared.Entities { - public class TileAddedEventArgs : EventArgs + public class MapEntityAddedEventArgs : EventArgs { - public Tile Tile { get; set; } - public TileAddedEventArgs(Tile tile) => Tile = tile; + public BaseMapEntity MapEntity { get; private set; } + public MapEntityAddedEventArgs(BaseMapEntity mapEntity) => MapEntity = mapEntity; } - public class OverlayAddedEventArgs : EventArgs + public class MapEntityDeletedEventArgs : EventArgs { - public Overlay Overlay { get; set; } - public OverlayAddedEventArgs(Overlay overlay) => Overlay = overlay; + public BaseMapEntity MapEntity { get; private set; } + public MapEntityDeletedEventArgs(BaseMapEntity mapEntity) => MapEntity = mapEntity; } - public class WallAddedEventArgs : EventArgs + public class Session { - public Wall Wall { get; set; } - public WallAddedEventArgs(Wall wall) => Wall = wall; - } + public event EventHandler MapEntityAdded; + public event EventHandler MapEntityDeleted; - public class WallDeletedEventArgs : EventArgs - { - public Wall Wall { get; set; } - public WallDeletedEventArgs(Wall wall) => Wall = wall; - } - - public class OverlayDeletedEventArgs : EventArgs - { - public Overlay Overlay { get; set; } - public OverlayDeletedEventArgs(Overlay overlay) => Overlay = overlay; - } - - public class TileDeletedEventArgs : EventArgs - { - public Tile Tile { get; set; } - public TileDeletedEventArgs(Tile tile) => Tile = tile; - } - - public class SessionData - { - public event EventHandler TileAdded; - public event EventHandler OverlayAdded; - public event EventHandler WallAdded; - public event EventHandler WallDeleted; - public event EventHandler OverlayDeleted; - public event EventHandler TileDeleted; - - public SessionData() + public Session() { Map = new ConcurrentDictionary(); Overlays = new ConcurrentDictionary(); @@ -64,6 +36,7 @@ namespace Sledgemapper.Shared.Entities public bool IsValid { get; set; } public List Players { get; set; } public List Colors; + public string SessionName { get; set; } public void NewTile(Tile selectedTile, string tileId) { @@ -84,7 +57,7 @@ namespace Sledgemapper.Shared.Entities } Map.TryAdd(newTile.ToString(), newTile); - OnRaiseTileAddedEvent(new TileAddedEventArgs(newTile)); + OnRaiseMapEntityAddedEvent(new MapEntityAddedEventArgs(newTile)); } public void NewOverlay(Overlay selectedOverlay, string overlayId) @@ -105,7 +78,7 @@ namespace Sledgemapper.Shared.Entities } Overlays.TryAdd(newOverlay.ToString(), newOverlay); - OnRaiseOverlayAddedEvent(new OverlayAddedEventArgs(newOverlay)); + OnRaiseMapEntityAddedEvent(new MapEntityAddedEventArgs(newOverlay)); } public void NewWall(Wall selectedWall, string wallId) @@ -122,7 +95,7 @@ namespace Sledgemapper.Shared.Entities } Walls.TryAdd(newWall.ToString(), newWall); - OnRaiseWallAddedEvent(new WallAddedEventArgs(newWall)); + OnRaiseMapEntityAddedEvent(new MapEntityAddedEventArgs(newWall)); } public void DeleteWall(Wall wall) @@ -134,82 +107,48 @@ namespace Sledgemapper.Shared.Entities var removed = Walls.TryRemove(wall.ToString(), out var _); if (removed) { - OnRaiseWallDeletedEvent(new WallDeletedEventArgs(wall)); + OnRaiseMapEntityDeletedEvent(new MapEntityDeletedEventArgs(wall)); } } public void DeleteOverlay(Overlay overlay) { - if (overlay is null) + if (overlay is null) { return; } var removed = Overlays.TryRemove(overlay.ToString(), out var _); if (removed) { - OnRaiseOverlayDeletedEvent(new OverlayDeletedEventArgs(overlay)); + OnRaiseMapEntityDeletedEvent(new MapEntityDeletedEventArgs(overlay)); } } public void DeleteTile(Tile tile) { - if (tile is null) + if (tile is null) { return; } var removed = Map.TryRemove(tile.ToString(), out var _); if (removed) { - OnRaiseTileDeletedEvent(new TileDeletedEventArgs(tile)); + OnRaiseMapEntityDeletedEvent(new MapEntityDeletedEventArgs(tile)); } } - protected virtual void OnRaiseTileAddedEvent(TileAddedEventArgs e) + protected virtual void OnRaiseMapEntityAddedEvent(MapEntityAddedEventArgs e) { - var raiseEvent = TileAdded; + var raiseEvent = MapEntityAdded; if (raiseEvent != null) { raiseEvent(this, e); } } - protected virtual void OnRaiseOverlayAddedEvent(OverlayAddedEventArgs e) + protected virtual void OnRaiseMapEntityDeletedEvent(MapEntityDeletedEventArgs e) { - var raiseEvent = OverlayAdded; - if (raiseEvent != null) - { - raiseEvent(this, e); - } - } - - protected virtual void OnRaiseWallAddedEvent(WallAddedEventArgs e) - { - var raiseEvent = WallAdded - ; - if (raiseEvent != null) - { - raiseEvent(this, e); - } - } - protected virtual void OnRaiseWallDeletedEvent(WallDeletedEventArgs e) - { - var raiseEvent = WallDeleted; - if (raiseEvent != null) - { - raiseEvent(this, e); - } - } - protected virtual void OnRaiseOverlayDeletedEvent(OverlayDeletedEventArgs e) - { - var raiseEvent = OverlayDeleted; - if (raiseEvent != null) - { - raiseEvent(this, e); - } - } - protected virtual void OnRaiseTileDeletedEvent(TileDeletedEventArgs e) - { - var raiseEvent = TileDeleted; + var raiseEvent = MapEntityDeleted; if (raiseEvent != null) { raiseEvent(this, e); diff --git a/Sledgemapper.Shared/Entities/Tile.cs b/Sledgemapper.Shared/Entities/Tile.cs index 4e17c1e..5c43114 100644 --- a/Sledgemapper.Shared/Entities/Tile.cs +++ b/Sledgemapper.Shared/Entities/Tile.cs @@ -1,18 +1,19 @@ namespace Sledgemapper.Shared.Entities { - - - public class Tile - { - public int X { get; set; } + public abstract class BaseMapEntity + { + public int X { get; set; } public int Y { get; set; } public string ID { get; set; } - public int Rotation { get; set; } - - public override string ToString() + public int Rotation { get; set; } + public override string ToString() { return $"{X}_{Y}"; } + } + + public class Tile :BaseMapEntity + { } diff --git a/Sledgemapper.Shared/Entities/Wall.cs b/Sledgemapper.Shared/Entities/Wall.cs index 5949a46..9f671a3 100644 --- a/Sledgemapper.Shared/Entities/Wall.cs +++ b/Sledgemapper.Shared/Entities/Wall.cs @@ -2,15 +2,10 @@ { - public class Wall + public class Wall :BaseMapEntity { - public int X { get; set; } - public int Y { get; set; } - public string ID { get; set; } - public int Rotation { get; set; } - public override string ToString() - { - return $"{X}_{Y}"; - } + + + } } diff --git a/Sledgemapper/ChannelsQueue.cs b/Sledgemapper/ChannelsQueue.cs new file mode 100644 index 0000000..a830fe3 --- /dev/null +++ b/Sledgemapper/ChannelsQueue.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using System.Threading.Channels; + +namespace Sledgemapper +{ + public class ChannelsQueue +{ + private readonly ChannelWriter _writer; + + public ChannelsQueue() + { + var channel = Channel.CreateUnbounded(new UnboundedChannelOptions() { SingleReader = true }); + var reader = channel.Reader; + _writer = channel.Writer; + + Task.Run(async () => + { + while (await reader.WaitToReadAsync()) + { + // Fast loop around available jobs + while (reader.TryRead(out var job)) + { + job.Invoke(); + } + } + }); + } + + public void Enqueue(Action job) + { + _writer.TryWrite(job); + } + + public void Stop() + { + _writer.Complete(); + } +} +} diff --git a/Sledgemapper/CommunicationManager.cs b/Sledgemapper/CommunicationManager.cs new file mode 100644 index 0000000..041aa38 --- /dev/null +++ b/Sledgemapper/CommunicationManager.cs @@ -0,0 +1,160 @@ +using Microsoft.AspNetCore.SignalR.Client; +using Polly; +using Refit; +using Sledgemapper.Shared.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Sledgemapper +{ + public class CommunicationManager + { + public IMapApi Api { get; private set; } + public HubConnection Connection { get; private set; } + public Session SessionData; + private ChannelsQueue Queue = new ChannelsQueue(); + + public CommunicationManager(Session sessionData) + { + SessionData = sessionData; + Connection = new HubConnectionBuilder() + .WithAutomaticReconnect() + + .WithUrl("http://localhost:5000/SledgemapperHub") + + // .WithUrl("http://hub.michelescandura.com:5000/SledgemapperHub") + .Build(); + + + + var httpClientHandler = new HttpClientHandler(); + + //if (myConfigurationService.VerifySslCertificate == false) + //{ + httpClientHandler.ServerCertificateCustomValidationCallback = + (message, certificate, chain, sslPolicyErrors) => true; + //} + + Api = RestService.For( + new HttpClient(httpClientHandler) + { + BaseAddress = new Uri("http://localhost:5000") + } + ); + + Connection.On("UpdateMap", (map) => + { + SessionData.Map = map.Map; + SessionData.Walls = map.Walls; + SessionData.Overlays = map.Overlays; + }); + + Connection.On("PlayerUpdate", (player) => + { + var p = SessionData.Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId); + if (p != null) + { + p.Position = player.Position; + } + }); + + Connection.On("DeleteTile", (tile) => + { + SessionData.Map.Remove(tile.ToString(), out var _); + }); + + Connection.On("DeleteWall", (tile) => + { + SessionData.Walls.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("NewWall", (tile) => + { + SessionData.Walls.Remove(tile.ToString(), out var _); + SessionData.Walls.TryAdd(tile.ToString(), tile); + }); + + Connection.On("NewOverlay", (tile) => + { + SessionData.Overlays.Remove(tile.ToString(), out var _); + SessionData.Overlays.TryAdd(tile.ToString(), tile); + }); + + Connection.On("NewPlayer", (player) => + { + var p = SessionData.Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId); + if (p is null) + { + SessionData.Players.Add(player); + } + else + { + p.Color = player.Color; + p.Position = player.Position; + } + }); + } + + 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 void Enqueue(BaseMapEntity entity, TileAction action) + { + switch (action) + { + case TileAction.Add: + switch (entity) + { + case Tile tile: + Queue.Enqueue(async () => await Execute(async () => await Api.NewTile(tile, SessionData.SessionName))); + break; + case Overlay overlay: + Queue.Enqueue(async () => await Execute(async () => await Api.NewOverlay(overlay, SessionData.SessionName))); + break; + case Wall wall: + Queue.Enqueue(async () => await Execute(async () => await Api.NewWall(wall, SessionData.SessionName))); + break; + } + break; + + case TileAction.Delete: + switch (entity) + { + case Tile tile: + Queue.Enqueue(async () => await Execute(async () => await Api.DeleteTile(tile, SessionData.SessionName))); + break; + case Overlay overlay: + Queue.Enqueue(async () => await Execute(async () => await Api.DeleteOverlay(overlay, SessionData.SessionName))); + break; + case Wall wall: + Queue.Enqueue(async () => await Execute(async () => await Api.DeleteWall(wall, SessionData.SessionName))); + break; + } + break; + } + + } + } +} diff --git a/Sledgemapper/MyDatabase.db b/Sledgemapper/MyDatabase.db index f50d871..ca53fb4 100644 Binary files a/Sledgemapper/MyDatabase.db and b/Sledgemapper/MyDatabase.db differ diff --git a/Sledgemapper/Sledgemapper.cs b/Sledgemapper/Sledgemapper.cs index 8a0893c..7821992 100644 --- a/Sledgemapper/Sledgemapper.cs +++ b/Sledgemapper/Sledgemapper.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.SignalR.Client; +using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; @@ -12,44 +12,23 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System; -using System.Collections.Concurrent; using Sledgemapper.Shared.Entities; -using Refit; -using System.Net.Http; -using Polly.Retry; -using Polly.Timeout; -using Polly; -using Polly.Extensions.Http; -using System.Threading.Tasks; -using System.Net; namespace Sledgemapper { public class Sledgemapper : Game { + private CommunicationManager _communicationManager; + private State _state; private GraphicsDeviceManager _graphics; private SpriteBatch _spriteBatch; - private Tile _selectedTile = new Tile { X = 1, Y = 1 }; - private Tile _hoveredTile = new Tile { X = 1, Y = 1 }; - private Wall _selectedWall = new Wall { X = 1, Y = 1 }; - private Overlay _selectedOverlay = new Overlay { X = 1, Y = 1 }; - private int _tileSize = 30; - private HubConnection connection; - private AsyncRetryPolicy retryPolicy; - private AsyncTimeoutPolicy timeoutPolicy; private readonly Desktop _desktop; - private string _currentTileId = ""; - private string _currentWallId = ""; - private string _currentOverlayId = ""; - private InsertMode _insertMode; - private string _session; private KeyboardState oldState; private MouseState oldMouseState; private Vector3 _viewportCenter = new Vector3(0, 0, 0); private SpriteFont font; private Dictionary _fonts; - private SessionData _sessionData; - private IMapApi _api; + private Session _sessionData; public Sledgemapper() { @@ -57,118 +36,19 @@ namespace Sledgemapper Content.RootDirectory = "Content"; _desktop = new Desktop(); MyraEnvironment.Game = this; - _sessionData = new SessionData(); + _sessionData = new Session(); IsFixedTimeStep = false; + _communicationManager = new CommunicationManager(_sessionData); + _state = new State(); } - - protected override void Initialize() { - // TODO: Add your initialization logic here IsMouseVisible = true; Window.AllowUserResizing = true; - Players = new List(); - connection = new HubConnectionBuilder() - .WithAutomaticReconnect() - - .WithUrl("http://localhost:5000/SledgemapperHub") - - // .WithUrl("http://hub.michelescandura.com:5000/SledgemapperHub") - .Build(); - - retryPolicy = HttpPolicyExtensions - .HandleTransientHttpError() - .Or() // Thrown by Polly's TimeoutPolicy if the inner call gets timeout. - .WaitAndRetryAsync(2, _ => TimeSpan.FromMilliseconds(500)); - - timeoutPolicy = Policy - .TimeoutAsync(TimeSpan.FromMilliseconds(500)); - - var httpClientHandler = new HttpClientHandler(); - - //if (myConfigurationService.VerifySslCertificate == false) - //{ - httpClientHandler.ServerCertificateCustomValidationCallback = - (message, certificate, chain, sslPolicyErrors) => true; - //} - - _api = RestService.For( - new HttpClient(httpClientHandler) - { - BaseAddress = new Uri("http://localhost:5000") - } - - ); - - connection.On("UpdateMap", (map) => - { - _sessionData.Map = map.Map; - _sessionData.Walls = map.Walls; - _sessionData.Overlays = map.Overlays; - }); - - connection.On("PlayerUpdate", (player) => - { - var p = Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId); - if (p != null) - { - p.Position = player.Position; - } - }); - - connection.On("DeleteTile", (tile) => - { - _sessionData.Map.Remove(tile.ToString(), out var _); - }); - - connection.On("DeleteWall", (tile) => - { - _sessionData.Walls.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("NewWall", (tile) => - { - _sessionData.Walls.Remove(tile.ToString(), out var _); - _sessionData.Walls.TryAdd(tile.ToString(), tile); - }); - - connection.On("NewOverlay", (tile) => - { - _sessionData.Overlays.Remove(tile.ToString(), out var _); - _sessionData.Overlays.TryAdd(tile.ToString(), tile); - }); - - connection.On("NewPlayer", (player) => - { - var p = Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId); - if (p is null) - { - Players.Add(player); - } - else - { - p.Color = player.Color; - p.Position = player.Position; - } - }); - base.Initialize(); } - public List Players { get; set; } - private HorizontalMenu BuildMenu() { var menu = new HorizontalMenu(); @@ -240,25 +120,27 @@ namespace Sledgemapper { return; } - if (connection.State != HubConnectionState.Connected) - { await connection.StartAsync(); } + if (_communicationManager.Connection.State != HubConnectionState.Connected) + { await _communicationManager.Connection.StartAsync(); } var successful = false; try { - var result = await connection?.InvokeAsync("JoinSession", textbox.Text, initialsTextbox.Text); + var result = await _communicationManager.Connection?.InvokeAsync("JoinSession", textbox.Text, initialsTextbox.Text); if (result != null) { _sessionData.Map = result.Map; _sessionData.Walls = result.Walls; _sessionData.Overlays = result.Overlays; - Players = result.Players; + _sessionData.Players = result.Players; + _sessionData.MapEntityAdded += OnMapEntityAdded; + } successful = result != null; ; } catch { } if (successful) { - _session = textbox.Text; + _sessionData.SessionName = textbox.Text; window.Close(); } }; @@ -311,34 +193,30 @@ namespace Sledgemapper { return; } - if (connection.State != HubConnectionState.Connected) - { await connection.StartAsync(); } + if (_communicationManager.Connection.State != HubConnectionState.Connected) + { await _communicationManager.Connection.StartAsync(); } var successful = false; try { - var session = await connection?.InvokeAsync("NewSession", textbox.Text, initialsTextbox.Text); + var session = await _communicationManager.Connection?.InvokeAsync("NewSession", textbox.Text, initialsTextbox.Text); if (session != null) { _sessionData = session; - session.TileAdded += OnTileAdded; - session.OverlayAdded += OnOverlayAdded; - session.WallAdded += OnWallAdded; - session.TileDeleted += OnTileDeleted; - session.WallDeleted += OnWallDeleted; - session.OverlayDeleted += OnOverlayDeleted; - Players = session.Players; + _sessionData.SessionName = textbox.Text; + session.MapEntityAdded += OnMapEntityAdded; + session.Players = session.Players; } successful = session != null; } catch (Exception ex) - { } if (successful) { - _session = textbox.Text; + _sessionData.SessionName = textbox.Text; + _communicationManager.SessionData = _sessionData; window.Close(); } }; @@ -395,7 +273,7 @@ namespace Sledgemapper using (StreamReader file = File.OpenText(dialog.FilePath)) { JsonSerializer serializer = new JsonSerializer(); - _sessionData = (SessionData)serializer.Deserialize(file, typeof(SessionData)); + _sessionData = (Session)serializer.Deserialize(file, typeof(Session)); } }; @@ -404,7 +282,7 @@ namespace Sledgemapper private async void OnMenuConnectSyncSelected(object sender, EventArgs e) { - await connection?.InvokeAsync("Sync", _session, _sessionData); + await _communicationManager.Connection?.InvokeAsync("Sync", _sessionData.SessionName, _sessionData); } protected override void LoadContent() @@ -445,7 +323,7 @@ namespace Sledgemapper var tileButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 }; tileButton.Click += (s, e) => { - _currentTileId = ((ImageButton)s).Id; + _state._currentTileId = ((ImageButton)s).Id; ClearSelection(wallGrid); ClearSelection(tileGrid); @@ -453,7 +331,7 @@ namespace Sledgemapper ((ImageButton)s).Border = new SolidBrush(Color.Red); ((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2); - _insertMode = InsertMode.Tile; + _state._insertMode = InsertMode.Tile; }; tileGrid.Widgets.Add(tileButton); indexY++; @@ -473,7 +351,7 @@ namespace Sledgemapper var wallButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 }; wallButton.Click += (s, e) => { - _currentWallId = ((ImageButton)s).Id; + _state._currentWallId = ((ImageButton)s).Id; ClearSelection(wallGrid); ClearSelection(tileGrid); ClearSelection(overlayGrid); @@ -481,7 +359,7 @@ namespace Sledgemapper ((ImageButton)s).Border = new SolidBrush(Color.Red); ((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2); - _insertMode = InsertMode.Wall; + _state._insertMode = InsertMode.Wall; }; wallGrid.Widgets.Add(wallButton); @@ -502,16 +380,14 @@ namespace Sledgemapper var overlayButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 }; overlayButton.Click += (s, e) => { - _currentOverlayId = ((ImageButton)s).Id; + _state._currentOverlayId = ((ImageButton)s).Id; ClearSelection(wallGrid); ClearSelection(tileGrid); ClearSelection(overlayGrid); - ((ImageButton)s).Border = new SolidBrush(Color.Red); ((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2); - _insertMode = InsertMode.Overlay; - + _state._insertMode = InsertMode.Overlay; }; overlayGrid.Widgets.Add(overlayButton); indexY++; @@ -529,7 +405,7 @@ namespace Sledgemapper _desktop.Root = mainPanel; // TODO: use this.Content to load your game content here } - bool _draw; + protected override void Update(GameTime gameTime) { // if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) @@ -542,55 +418,55 @@ namespace Sledgemapper var screenPosition = new Point((mouseState.Position.X - (int)_viewportCenter.X), (mouseState.Position.Y - (int)_viewportCenter.Y)); - _hoveredTile.X = screenPosition.X / _tileSize; - _hoveredTile.Y = screenPosition.Y / _tileSize; + _state._hoveredTile.X = screenPosition.X / _state._tileSize; + _state._hoveredTile.Y = screenPosition.Y / _state._tileSize; if (screenPosition.X < 0) { - _hoveredTile.X--; + _state._hoveredTile.X--; } if (screenPosition.Y < 0) { - _hoveredTile.Y--; + _state._hoveredTile.Y--; } - if (_insertMode == InsertMode.Wall) + if (_state._insertMode == InsertMode.Wall) { - SelectClosestWall(screenPosition); + _state.SelectClosestWall(screenPosition); } - if (_insertMode == InsertMode.Overlay) + if (_state._insertMode == InsertMode.Overlay) { - SelectOverlay(screenPosition); + _state.SelectOverlay(screenPosition); } if (mouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton != oldMouseState.LeftButton) { - _selectedTile.X = _hoveredTile.X; - _selectedTile.Y = _hoveredTile.Y; - connection?.SendAsync("UpdatePosition", _session, _selectedTile); + _state._selectedTile.X = _state._hoveredTile.X; + _state._selectedTile.Y = _state._hoveredTile.Y; + _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _state._selectedTile); } if (newState.IsKeyDown(Keys.LeftControl) && mouseState.LeftButton == ButtonState.Pressed - && ((mouseState.LeftButton != oldMouseState.LeftButton) || (_selectedTile.X != _hoveredTile.X && _selectedTile.Y != _hoveredTile.Y))) + && ((mouseState.LeftButton != oldMouseState.LeftButton) || (_state._selectedTile.X != _state._hoveredTile.X && _state._selectedTile.Y != _state._hoveredTile.Y))) { - switch (_insertMode) + switch (_state._insertMode) { case InsertMode.Tile: - _selectedTile.X = _hoveredTile.X; - _selectedTile.Y = _hoveredTile.Y; - connection?.SendAsync("UpdatePosition", _session, _selectedTile); + _state._selectedTile.X = _state._hoveredTile.X; + _state._selectedTile.Y = _state._hoveredTile.Y; + _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _state._selectedTile); - _sessionData.NewTile(_selectedTile, _currentTileId); + _sessionData.NewTile(_state._selectedTile, _state._currentTileId); break; case InsertMode.Wall: - _sessionData.NewWall(_selectedWall, _currentWallId); + _sessionData.NewWall(_state._selectedWall, _state._currentWallId); break; case InsertMode.Overlay: - _sessionData.NewOverlay(_selectedOverlay, _currentOverlayId); + _sessionData.NewOverlay(_state._selectedOverlay, _state._currentOverlayId); break; } } @@ -604,12 +480,12 @@ namespace Sledgemapper { if (mouseState.ScrollWheelValue > oldMouseState.ScrollWheelValue) { - _tileSize = System.Math.Min(120, _tileSize + 10); + _state._tileSize = Math.Min(120, _state._tileSize + 10); } else if (mouseState.ScrollWheelValue < oldMouseState.ScrollWheelValue) { - _tileSize = System.Math.Max(10, _tileSize - 10); + _state._tileSize = Math.Max(10, _state._tileSize - 10); } } @@ -619,18 +495,18 @@ namespace Sledgemapper if (newState.IsKeyDown(Keys.Delete)) { - switch (_insertMode) + switch (_state._insertMode) { case InsertMode.Tile: - _selectedTile.X = _hoveredTile.X; - _selectedTile.Y = _hoveredTile.Y; - _sessionData.DeleteTile(_selectedTile); + _state._selectedTile.X = _state._hoveredTile.X; + _state._selectedTile.Y = _state._hoveredTile.Y; + _sessionData.DeleteTile(_state._selectedTile); break; case InsertMode.Wall: - _sessionData.DeleteWall(_selectedWall); + _sessionData.DeleteWall(_state._selectedWall); break; case InsertMode.Overlay: - _sessionData.DeleteOverlay(_selectedOverlay); + _sessionData.DeleteOverlay(_state._selectedOverlay); break; } } @@ -641,22 +517,22 @@ namespace Sledgemapper { case Keys.Left: if (oldState.IsKeyUp(Keys.Left) && newState.IsKeyDown(Keys.Left)) - { _selectedTile.X--; } + { _state._selectedTile.X--; } break; case Keys.Right: if (oldState.IsKeyUp(Keys.Right) && newState.IsKeyDown(Keys.Right)) - { _selectedTile.X++; } + { _state._selectedTile.X++; } break; case Keys.Up: if (oldState.IsKeyUp(Keys.Up) && newState.IsKeyDown(Keys.Up)) - { _selectedTile.Y--; } + { _state._selectedTile.Y--; } break; case Keys.Down: if (oldState.IsKeyUp(Keys.Down) && newState.IsKeyDown(Keys.Down)) - { _selectedTile.Y++; } + { _state._selectedTile.Y++; } break; } - connection?.SendAsync("UpdatePosition", _session, _selectedTile); + _communicationManager.Connection?.SendAsync("UpdatePosition", _sessionData.SessionName, _state._selectedTile); } @@ -672,24 +548,57 @@ namespace Sledgemapper return; } GraphicsDevice.Clear(Color.DarkGray); - var sessionData = _sessionData; // TODO: Add your drawing code here - var visibleTilesX = GraphicsDevice.Viewport.Width / _tileSize + 1; - var visibleTilesY = GraphicsDevice.Viewport.Height / _tileSize + 1; + var visibleTilesX = GraphicsDevice.Viewport.Width / _state._tileSize + 1; + var visibleTilesY = GraphicsDevice.Viewport.Height / _state._tileSize + 1; _spriteBatch.Begin(transformMatrix: Matrix.CreateTranslation(_viewportCenter)); + DrawGrid(visibleTilesX, visibleTilesY); + DrawTiles(); + DrawWalls(); + DrawOverlays(); + + if (string.IsNullOrWhiteSpace(_sessionData.SessionName)) + { + _spriteBatch.DrawRectangle(new Rectangle(_state._selectedTile.X * _state._tileSize, _state._selectedTile.Y * _state._tileSize, _state._tileSize - 1, _state._tileSize - 1), Color.Red, 2); + } + + DrawPlayers(); + + var startWall = new Vector2(_state._selectedWall.X * _state._tileSize, _state._selectedWall.Y * _state._tileSize); + if (_state._insertMode == InsertMode.Wall) + { + _spriteBatch.DrawLine(startWall, _state._tileSize, MathHelper.ToRadians(90 * _state._selectedWall.Rotation), Color.Red, 2); + } + var overlay = new Vector2(_state._selectedOverlay.X * _state._tileSize, _state._selectedOverlay.Y * _state._tileSize); + if (_state._insertMode == InsertMode.Overlay) + { + if (_state._selectedOverlay.Intersection) + { + _spriteBatch.DrawCircle(overlay, _state._tileSize / 3, 100, Color.Red, 2); + } + } + + _spriteBatch.End(); + + _desktop?.Render(); + base.Draw(gameTime); + } + + private void DrawGrid(int visibleTilesX, int visibleTilesY) + { for (var i = -1; i < visibleTilesX + 2; i++) { - var posX1 = i * _tileSize - _viewportCenter.X; + var posX1 = i * _state._tileSize - _viewportCenter.X; var posY1 = -_viewportCenter.Y; - posX1 = posX1 - posX1 % _tileSize; - posY1 = posY1 - posY1 % _tileSize; - var posX2 = i * _tileSize - _viewportCenter.X; + posX1 = posX1 - posX1 % _state._tileSize; + posY1 = posY1 - posY1 % _state._tileSize; + var posX2 = i * _state._tileSize - _viewportCenter.X; var posY2 = GraphicsDevice.Viewport.Height - _viewportCenter.Y; - posX2 = posX2 - posX2 % _tileSize; - posY2 = posY2 - posY2 % _tileSize; + posX2 = posX2 - posX2 % _state._tileSize; + posY2 = posY2 - posY2 % _state._tileSize; _spriteBatch.DrawLine( posX1, posY1, @@ -701,41 +610,93 @@ namespace Sledgemapper for (var i = -1; i < visibleTilesY + 2; i++) { var posX1 = -_viewportCenter.X; - var posY1 = i * _tileSize - _viewportCenter.Y; - posX1 = posX1 - posX1 % _tileSize; - posY1 = posY1 - posY1 % _tileSize; + var posY1 = i * _state._tileSize - _viewportCenter.Y; + posX1 = posX1 - posX1 % _state._tileSize; + posY1 = posY1 - posY1 % _state._tileSize; var posX2 = GraphicsDevice.Viewport.Width - _viewportCenter.X; - var posY2 = i * _tileSize - _viewportCenter.Y; - posX2 = posX2 - posX2 % _tileSize; - posY2 = posY2 - posY2 % _tileSize; + var posY2 = i * _state._tileSize - _viewportCenter.Y; + posX2 = posX2 - posX2 % _state._tileSize; + posY2 = posY2 - posY2 % _state._tileSize; _spriteBatch.DrawLine(posX1, posY1, posX2, posY2, Color.Black); } + } - foreach (var tile in sessionData.Map.Values) + private void DrawTiles() + { + foreach (var tile in _sessionData.Map.Values) { - var content = Content.Load($"tiles/{tile.ID}"); - var destinationRectangle = new Rectangle(tile.X * _tileSize, tile.Y * _tileSize, _tileSize, _tileSize); - var posX = tile.X * _tileSize + _tileSize / 2f; - var posY = tile.Y * _tileSize + _tileSize / 2f; + 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)_tileSize - 1) / content.Width, SpriteEffects.None, 0); + null, Color.White, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_state._tileSize - 1) / content.Width, SpriteEffects.None, 0); } + } - foreach (var wall in sessionData.Walls.Values) + private void DrawPlayers() + { + foreach (var player in _sessionData.Players.Copy>()) { + var hexs = player.Color.Split(2).ToArray(); + var color = new Color(int.Parse(hexs[0], System.Globalization.NumberStyles.HexNumber), + int.Parse(hexs[1], System.Globalization.NumberStyles.HexNumber), + int.Parse(hexs[2], System.Globalization.NumberStyles.HexNumber)); + _spriteBatch.DrawRectangle(new Rectangle(player.Position.X * _state._tileSize, player.Position.Y * _state._tileSize, _state._tileSize - 1, _state._tileSize - 1), color, 2); + var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _state._tileSize).Value ?? _fonts.Last().Value; + + var fscale = (float)_state._tileSize / ((float)ffont.LineSpacing * 2); + _spriteBatch.DrawString(ffont, + player.Initials, + new Vector2(player.Position.X * _state._tileSize + 2, player.Position.Y * _state._tileSize + _state._tileSize - 2 - ffont.LineSpacing * fscale), + color, + 0, + Vector2.Zero, + fscale, + SpriteEffects.None, + 0); + } + } + + private void DrawOverlays() + { + foreach (var tile in _sessionData.Overlays.Values) + { + var content = Content.Load($"overlays/{tile.ID}"); + if (tile.Intersection) + { + var posX = tile.X * _state._tileSize; + var posY = tile.Y * _state._tileSize; + + _spriteBatch.Draw(content, new Vector2(posX, posY), + null, new Color(24, 118, 157), MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_state._tileSize - 10) / content.Width, SpriteEffects.None, 0); + } + else + { + 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, new Color(24, 118, 157), MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_state._tileSize - 10) / content.Width, SpriteEffects.None, 0); + } + } + } + + private void DrawWalls() + { + foreach (var wall in _sessionData.Walls.Values) + { var content = Content.Load($"walls/{wall.ID}"); - var scale = _tileSize / (float)content.Height; + var scale = _state._tileSize / (float)content.Height; var offset = scale * content.Width / 2f; - var posX = wall.X * _tileSize; - var posY = wall.Y * _tileSize; + var posX = wall.X * _state._tileSize; + var posY = wall.Y * _state._tileSize; if (wall.Rotation == 1) { posX -= (int)offset; @@ -744,82 +705,8 @@ namespace Sledgemapper { posY += (int)offset; } - // _spriteBatch.Draw(content, new Vector2(posX, posY),null, Color.White, MathHelper.ToRadians(90 * (wall.Rotation - 1)), new Vector2(offset, 0), scale, SpriteEffects.None, 0); _spriteBatch.Draw(content, new Vector2(posX, posY), null, Color.White, MathHelper.ToRadians(90 * (wall.Rotation - 1)), new Vector2(0, 0), scale, SpriteEffects.None, 0); - - } - - foreach (var tile in sessionData.Overlays.Values) - { - - var content = Content.Load($"overlays/{tile.ID}"); - // System.Console.WriteLine(tile.Rotation); - if (tile.Intersection) - { - var posX = tile.X * _tileSize; - var posY = tile.Y * _tileSize; - - _spriteBatch.Draw(content, new Vector2(posX, posY), - null, new Color(24, 118, 157), MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_tileSize - 10) / content.Width, SpriteEffects.None, 0); - - } - else - { - var posX = tile.X * _tileSize + _tileSize / 2f; - var posY = tile.Y * _tileSize + _tileSize / 2f; - - _spriteBatch.Draw(content, new Vector2(posX, posY), - null, new Color(24, 118, 157), MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_tileSize - 10) / content.Width, SpriteEffects.None, 0); - } - } - - if (string.IsNullOrWhiteSpace(_session)) - { - _spriteBatch.DrawRectangle(new Rectangle(_selectedTile.X * _tileSize, _selectedTile.Y * _tileSize, _tileSize - 1, _tileSize - 1), Color.Red, 2); - } - - foreach (var player in Players.Copy>()) - { - - var hexs = player.Color.Split(2).ToArray(); - var color = new Color(int.Parse(hexs[0], System.Globalization.NumberStyles.HexNumber), - int.Parse(hexs[1], System.Globalization.NumberStyles.HexNumber), - int.Parse(hexs[2], System.Globalization.NumberStyles.HexNumber)); - _spriteBatch.DrawRectangle(new Rectangle(player.Position.X * _tileSize, player.Position.Y * _tileSize, _tileSize - 1, _tileSize - 1), color, 2); - - var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _tileSize).Value ?? _fonts.Last().Value; - - var fscale = (float)_tileSize / ((float)ffont.LineSpacing * 2); - _spriteBatch.DrawString(ffont, - player.Initials, - new Vector2(player.Position.X * _tileSize + 2, player.Position.Y * _tileSize + _tileSize - 2 - ffont.LineSpacing * fscale), - color, - 0, - Vector2.Zero, - fscale, - SpriteEffects.None, - 0); - } - - var startWall = new Vector2(_selectedWall.X * _tileSize, _selectedWall.Y * _tileSize); - if (_insertMode == InsertMode.Wall) - { - _spriteBatch.DrawLine(startWall, _tileSize, MathHelper.ToRadians(90 * _selectedWall.Rotation), Color.Red, 2); - } - var overlay = new Vector2(_selectedOverlay.X * _tileSize, _selectedOverlay.Y * _tileSize); - if (_insertMode == InsertMode.Overlay) - { - if (_selectedOverlay.Intersection) - { - _spriteBatch.DrawCircle(overlay, _tileSize / 3, 100, Color.Red, 2); - } - } - - _spriteBatch.End(); - - _desktop?.Render(); - base.Draw(gameTime); } private void ClearSelection(Grid grid) @@ -830,136 +717,20 @@ namespace Sledgemapper } } - private float Sign(Point p1, Point p2, Point p3) { return (p1.X - p3.X) * (p2.Y - p3.Y) - (p2.X - p3.X) * (p1.Y - p3.Y); } - - private bool PointInTri(Point pt, Point v1, Point v2, Point v3) + private void OnMapEntityAdded(object sender, MapEntityAddedEventArgs e) { - bool b1, b2, b3; - b1 = Sign(pt, v1, v2) < 0.0f; - b2 = Sign(pt, v2, v3) < 0.0f; - b3 = Sign(pt, v3, v1) < 0.0f; - return ((b1 == b2) && (b2 == b3)); + _communicationManager.Enqueue(e.MapEntity, TileAction.Add); } - private void SelectClosestWall(Point mousePosition) + private void OnMapEntityDeleted(object sender, MapEntityDeletedEventArgs e) { - var topLeft = new Point(_hoveredTile.X * _tileSize, _hoveredTile.Y * _tileSize); - var bottomLeft = new Point(_hoveredTile.X * _tileSize, _hoveredTile.Y * _tileSize + _tileSize); - var topRight = new Point(_hoveredTile.X * _tileSize + _tileSize, _hoveredTile.Y * _tileSize); - var bottomRight = new Point(_hoveredTile.X * _tileSize + _tileSize, _hoveredTile.Y * _tileSize + _tileSize); - var center = new Point(_hoveredTile.X * _tileSize + _tileSize / 2, _hoveredTile.Y * _tileSize + _tileSize / 2); - var leftWall = PointInTri(mousePosition, topLeft, center, bottomLeft); - var rightWall = PointInTri(mousePosition, topRight, bottomRight, center); - var topWall = PointInTri(mousePosition, topLeft, topRight, center); - var bottomtWall = PointInTri(mousePosition, bottomLeft, center, bottomRight); - - if (leftWall) - { - _selectedWall.X = _hoveredTile.X; - _selectedWall.Y = _hoveredTile.Y; - _selectedWall.Rotation = 1; - } - else if (rightWall) - { - _selectedWall.X = _hoveredTile.X + 1; - _selectedWall.Y = _hoveredTile.Y; - _selectedWall.Rotation = 1; - } - else if (topWall) - { - _selectedWall.X = _hoveredTile.X; - _selectedWall.Y = _hoveredTile.Y; - _selectedWall.Rotation = 0; - } - else if (bottomtWall) - { - _selectedWall.X = _hoveredTile.X; - _selectedWall.Y = _hoveredTile.Y + 1; - _selectedWall.Rotation = 0; - } - } - - private void SelectOverlay(Point mousePosition) - { - _selectedOverlay.X = _hoveredTile.X; - _selectedOverlay.Y = _hoveredTile.Y; - var q1 = System.Math.Pow(mousePosition.X - _hoveredTile.X * _tileSize, 2); - var q2 = System.Math.Pow((_hoveredTile.Y * _tileSize - mousePosition.Y), 2); - var s = System.Math.Sqrt(q1 + q2); - - if (s < _tileSize / 3) - { - _selectedOverlay.Intersection = true; - return; - } - - q1 = System.Math.Pow(mousePosition.X - (_hoveredTile.X + 1) * _tileSize, 2); - // var q2 = System.Math.Pow((_hoveredTile.Y * _tileSize - mousePosition.Y), 2); - s = System.Math.Sqrt(q1 + q2); - if (s < _tileSize / 3) - { - _selectedOverlay.X = _selectedOverlay.X + 1; - _selectedOverlay.Intersection = true; - return; - } - - //q1 = System.Math.Pow(mousePosition.X - (_hoveredTile.X + 1) * _tileSize, 2); - q2 = System.Math.Pow(((_hoveredTile.Y + 1) * _tileSize - mousePosition.Y), 2); - s = System.Math.Sqrt(q1 + q2); - if (s < _tileSize / 3) - { - _selectedOverlay.X = _selectedOverlay.X + 1; - _selectedOverlay.Y = _selectedOverlay.Y + 1; - _selectedOverlay.Intersection = true; - return; - } - - q1 = System.Math.Pow(mousePosition.X - _hoveredTile.X * _tileSize, 2); - q2 = System.Math.Pow(((_hoveredTile.Y + 1) * _tileSize - mousePosition.Y), 2); - s = System.Math.Sqrt(q1 + q2); - if (s < _tileSize / 3) - { - _selectedOverlay.X = _selectedOverlay.X; - _selectedOverlay.Y = _selectedOverlay.Y + 1; - _selectedOverlay.Intersection = true; - return; - } - - _selectedOverlay.Intersection = false; - } - - private async Task Execute(Func call) - { - await Policy - .Handle(ex => ex.StatusCode == HttpStatusCode.RequestTimeout) - .RetryAsync(5, async (exception, retryCount) => await Task.Delay(500)) - .ExecuteAsync(async () => await call().ConfigureAwait(false)) - .ConfigureAwait(false); - } - - private async void OnOverlayAdded(object sender, OverlayAddedEventArgs e) - { - await Execute(() => _api.NewOverlay(e.Overlay, _session)); - } - private void OnTileAdded(object sender, TileAddedEventArgs e) - { - _api.NewTile(e.Tile, _session); - } - private void OnWallAdded(object sender, WallAddedEventArgs e) - { - _api.NewWall(e.Wall, _session); - } - private void OnOverlayDeleted(object sender, OverlayDeletedEventArgs e) - { - _api.DeleteOverlay(e.Overlay, _session); - } - private void OnTileDeleted(object sender, TileDeletedEventArgs e) - { - _api.DeleteTile(e.Tile, _session); - } - private void OnWallDeleted(object sender, WallDeletedEventArgs e) - { - _api.DeleteWall(e.Wall, _session); + _communicationManager.Enqueue(e.MapEntity, TileAction.Delete); } } + + public enum TileAction + { + Add, + Delete + } } diff --git a/Sledgemapper/Sledgemapper.csproj b/Sledgemapper/Sledgemapper.csproj index 7e542df..6b2424c 100644 --- a/Sledgemapper/Sledgemapper.csproj +++ b/Sledgemapper/Sledgemapper.csproj @@ -35,6 +35,7 @@ + diff --git a/Sledgemapper/State.cs b/Sledgemapper/State.cs new file mode 100644 index 0000000..c8e372c --- /dev/null +++ b/Sledgemapper/State.cs @@ -0,0 +1,100 @@ +using Microsoft.Xna.Framework; +using System; +using Sledgemapper.Shared.Entities; + +namespace Sledgemapper +{ + public class State + { + public Tile _selectedTile = new Tile { X = 1, Y = 1 }; + public Tile _hoveredTile = new Tile { X = 1, Y = 1 }; + public Wall _selectedWall = new Wall { X = 1, Y = 1 }; + public Overlay _selectedOverlay = new Overlay { X = 1, Y = 1 }; + public int _tileSize = 30; + public string _currentTileId = ""; + public string _currentWallId = ""; + public string _currentOverlayId = ""; + public InsertMode _insertMode; + + public void SelectClosestWall(Point mousePosition) + { + var topLeft = new Point(_hoveredTile.X * _tileSize, _hoveredTile.Y * _tileSize); + var bottomLeft = new Point(_hoveredTile.X * _tileSize, _hoveredTile.Y * _tileSize + _tileSize); + var topRight = new Point(_hoveredTile.X * _tileSize + _tileSize, _hoveredTile.Y * _tileSize); + var bottomRight = new Point(_hoveredTile.X * _tileSize + _tileSize, _hoveredTile.Y * _tileSize + _tileSize); + var center = new Point(_hoveredTile.X * _tileSize + _tileSize / 2, _hoveredTile.Y * _tileSize + _tileSize / 2); + + if (Utils.PointInTri(mousePosition, topLeft, center, bottomLeft)) //left wall + { + _selectedWall.X = _hoveredTile.X; + _selectedWall.Y = _hoveredTile.Y; + _selectedWall.Rotation = 1; + } + else if (Utils.PointInTri(mousePosition, topRight, bottomRight, center)) //right wall + { + _selectedWall.X = _hoveredTile.X + 1; + _selectedWall.Y = _hoveredTile.Y; + _selectedWall.Rotation = 1; + } + else if (Utils.PointInTri(mousePosition, topLeft, topRight, center)) //top wall + { + _selectedWall.X = _hoveredTile.X; + _selectedWall.Y = _hoveredTile.Y; + _selectedWall.Rotation = 0; + } + else if (Utils.PointInTri(mousePosition, bottomLeft, center, bottomRight)) //bottom wall + { + _selectedWall.X = _hoveredTile.X; + _selectedWall.Y = _hoveredTile.Y + 1; + _selectedWall.Rotation = 0; + } + } + public void SelectOverlay(Point mousePosition) + { + _selectedOverlay.X = _hoveredTile.X; + _selectedOverlay.Y = _hoveredTile.Y; + var q1 = Math.Pow(mousePosition.X - _hoveredTile.X * _tileSize, 2); + var q2 = Math.Pow((_hoveredTile.Y * _tileSize - mousePosition.Y), 2); + var s = Math.Sqrt(q1 + q2); + + if (s < _tileSize / 3) + { + _selectedOverlay.Intersection = true; + return; + } + + q1 = Math.Pow(mousePosition.X - (_hoveredTile.X + 1) * _tileSize, 2); + s = Math.Sqrt(q1 + q2); + if (s < _tileSize / 3) + { + _selectedOverlay.X = _selectedOverlay.X + 1; + _selectedOverlay.Intersection = true; + return; + } + + //q1 = System.Math.Pow(mousePosition.X - (_hoveredTile.X + 1) * _tileSize, 2); + q2 = Math.Pow(((_hoveredTile.Y + 1) * _tileSize - mousePosition.Y), 2); + s = Math.Sqrt(q1 + q2); + if (s < _tileSize / 3) + { + _selectedOverlay.X = _selectedOverlay.X + 1; + _selectedOverlay.Y = _selectedOverlay.Y + 1; + _selectedOverlay.Intersection = true; + return; + } + + q1 = Math.Pow(mousePosition.X - _hoveredTile.X * _tileSize, 2); + q2 = Math.Pow(((_hoveredTile.Y + 1) * _tileSize - mousePosition.Y), 2); + s = Math.Sqrt(q1 + q2); + if (s < _tileSize / 3) + { + _selectedOverlay.X = _selectedOverlay.X; + _selectedOverlay.Y = _selectedOverlay.Y + 1; + _selectedOverlay.Intersection = true; + return; + } + + _selectedOverlay.Intersection = false; + } + } +} diff --git a/Sledgemapper/Utils.cs b/Sledgemapper/Utils.cs new file mode 100644 index 0000000..36b8dd8 --- /dev/null +++ b/Sledgemapper/Utils.cs @@ -0,0 +1,20 @@ +using Microsoft.Xna.Framework; +using Sledgemapper.Shared.Entities; +using System; + +namespace Sledgemapper +{ + public static class Utils + { + private static float Sign(Point p1, Point p2, Point p3) { return (p1.X - p3.X) * (p2.Y - p3.Y) - (p2.X - p3.X) * (p1.Y - p3.Y); } + + public static bool PointInTri(Point pt, Point v1, Point v2, Point v3) + { + bool b1, b2, b3; + b1 = Sign(pt, v1, v2) < 0.0f; + b2 = Sign(pt, v2, v3) < 0.0f; + b3 = Sign(pt, v3, v1) < 0.0f; + return ((b1 == b2) && (b2 == b3)); + } + } +} \ No newline at end of file