diff --git a/Sledgemapper.Shared/Entities/AuthenticateResponse.cs b/Sledgemapper.Shared/Entities/AuthenticateResponse.cs index 9390fbf..710db3f 100644 --- a/Sledgemapper.Shared/Entities/AuthenticateResponse.cs +++ b/Sledgemapper.Shared/Entities/AuthenticateResponse.cs @@ -7,5 +7,6 @@ namespace Sledgemapper.Shared.Entities public string Firstname { get; set; } public string LastName { get; set; } public string Token { get; set; } + public string Initials { get; set; } } } \ No newline at end of file diff --git a/Sledgemapper.Shared/Entities/Session.cs b/Sledgemapper.Shared/Entities/Session.cs index 9f3924d..5cb5537 100644 --- a/Sledgemapper.Shared/Entities/Session.cs +++ b/Sledgemapper.Shared/Entities/Session.cs @@ -35,7 +35,7 @@ namespace Sledgemapper.Shared.Entities public ConcurrentDictionary Overlays { get; set; } public bool IsValid { get; set; } public List Players { get; set; } - public List Colors; + public List Colors { get; set; } public string SessionName { get; set; } public void NewTile(Tile selectedTile, string tileId) @@ -67,10 +67,10 @@ namespace Sledgemapper.Shared.Entities return; } var overlayExist = Overlays.TryGetValue(selectedOverlay.ToString(), out var overlay); - var newOverlay = new Overlay { X = selectedOverlay.X, Y = selectedOverlay.Y, ID = overlayId, Intersection = selectedOverlay.Intersection }; ; + var newOverlay = new Overlay { X = selectedOverlay.X, Y = selectedOverlay.Y, ID = overlayId, Intersection = selectedOverlay.Intersection }; if (overlayExist) { - Overlays.TryRemove(overlay.ToString(), out var rrtile); + Overlays.TryRemove(overlay.ToString(), out var _); if (overlay.ID == overlayId) { newOverlay.Rotation = (overlay.Rotation + 1) % 4; @@ -139,20 +139,12 @@ namespace Sledgemapper.Shared.Entities protected virtual void OnRaiseMapEntityAddedEvent(MapEntityAddedEventArgs e) { - var raiseEvent = MapEntityAdded; - if (raiseEvent != null) - { - raiseEvent(this, e); - } + MapEntityAdded?.Invoke(this, e); } protected virtual void OnRaiseMapEntityDeletedEvent(MapEntityDeletedEventArgs e) { - var raiseEvent = MapEntityDeleted; - if (raiseEvent != null) - { - raiseEvent(this, e); - } + MapEntityDeleted?.Invoke(this, e); } } } diff --git a/Sledgemapper/Sledgemapper.cs b/Sledgemapper/Sledgemapper.cs index 431c07d..2f9b41a 100644 --- a/Sledgemapper/Sledgemapper.cs +++ b/Sledgemapper/Sledgemapper.cs @@ -7,32 +7,32 @@ using Myra.Graphics2D.Brushes; using Myra.Graphics2D.TextureAtlases; using Myra.Graphics2D.UI; using Myra.Graphics2D.UI.File; +using Myra.Graphics2D.UI.Properties; using Newtonsoft.Json; +using Refit; +using Sledgemapper.Shared.Entities; +using Sledgemapper.UI; +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System; -using Sledgemapper.Shared.Entities; -using Sledgemapper.UI; -using System.Net; using System.Net.Http; -using Refit; namespace Sledgemapper { public class Sledgemapper : Game { - private CommunicationManager _communicationManager; - private State _state; - private GraphicsDeviceManager _graphics; + private readonly CommunicationManager _communicationManager; + private readonly State _state; + private readonly GraphicsDeviceManager _graphics; private SpriteBatch _spriteBatch; private readonly Desktop _desktop; private KeyboardState oldState; private MouseState oldMouseState; private Vector3 _viewportCenter = new Vector3(0, 0, 0); - private SpriteFont font; private Dictionary _fonts; private Session _sessionData; + private AuthenticateResponse _authResponse; public Sledgemapper() { @@ -53,379 +53,6 @@ namespace Sledgemapper base.Initialize(); } - private HorizontalMenu BuildMenu() - { - var menu = new HorizontalMenu(); - var menuFile = new MenuItem("_file", "File"); - var menuFileLoad = new MenuItem("_file_load", "Load"); - var menuFileSave = new MenuItem("_file_save", "Save"); - var menuConnect = new MenuItem("_connect", "Connect"); - var menuConnectLogin = new MenuItem("_connect_login", "Login"); - var menuConnectNew = new MenuItem("_connect_new", "New"); - var menuConnectJoin = new MenuItem("_connect_join", "Join"); - var menuConnectSync = new MenuItem("_connect_sync", "Sync"); - - menuConnectSync.Selected += OnMenuConnectSyncSelected; - menuFileLoad.Selected += OnMenuFileLoadSelected; - menuFileSave.Selected += OnMenuFileSaveSelected; - menuConnectLogin.Selected += OnMenuConnectLoginSelected; - menuConnectNew.Selected += OnMenuConnectNewSelected; - menuConnectJoin.Selected += OnMenuConnectJoinSelected; - - menuConnect.Items.Add(menuConnectLogin); - menuConnect.Items.Add(menuConnectNew); - menuConnect.Items.Add(menuConnectJoin); - menuConnect.Items.Add(menuConnectSync); - menu.Items.Add(menuConnect); - menuFile.Items.Add(menuFileLoad); - menuFile.Items.Add(menuFileSave); - menu.Items.Add(menuFile); - menu.Items.Add(menuConnect); - - return menu; - } - - private void OnMenuConnectJoinSelected(object sender, EventArgs e) - { - Window window = new Window - { - Title = "Join mapping session" - }; - - var content = new SessionWindow(); - content.BtnLogin.Text = "Join"; - content.BtnLogin.Click += OnButtonJoinSessionClicked; - window.Content = content; - - window.ShowModal(_desktop); - } - - private async void OnButtonJoinSessionClicked(object sender, EventArgs e) - { - Container container = ((TextButton)sender).Parent; - while (!(container is Window)) - { - container = container.Parent; - } - var localWindow = (Window)container; - var localContent = localWindow.Content as SessionWindow; - var isValid = ValidateTextbox(localContent.TxtSession); - if (!isValid) - { - return; - } - - if (_communicationManager.Connection.State != HubConnectionState.Connected) - { - await _communicationManager.Connection.StartAsync(); - } - - var successful = false; - try - { - var result = await _communicationManager.Connection?.InvokeAsync("JoinSession", localContent.TxtSession.Text, _authResponse.Initials); - if (result != null) - { - _sessionData.Map = result.Map; - _sessionData.Walls = result.Walls; - _sessionData.Overlays = result.Overlays; - _sessionData.Players = result.Players; - _sessionData.MapEntityAdded += OnMapEntityAdded; - _sessionData.MapEntityDeleted += OnMapEntityDeleted; - } - successful = result != null; ; - } - catch { } - if (successful) - { - _sessionData.SessionName = localContent.TxtSession.Text; - localWindow.Close(); - } - } - - private AuthenticateResponse _authResponse; - - private void OnMenuConnectLoginSelected(object sender, EventArgs e) - { - Window window = new Window - { - Title = "Login" - }; - - var content = new LoginRegisterWindow(); - content.RdoLogin.IsPressed = true; - content.RdoLogin.Click += (s, e) => - { - content.TxtFirstname.Visible = false; - content.TxtLastname.Visible = false; - content.TxtInitials.Visible = false; - content.LblFirstname.Visible = false; - content.LblLastname.Visible = false; - content.LblInitials.Visible = false; - content.BtnLogin.Visible = true; - content.BtnRegister.Visible = false; - window.Title = "Login"; - }; - - content.RdoRegister.Click += (s, e) => - { - content.TxtFirstname.Visible = true; - content.TxtLastname.Visible = true; - content.TxtInitials.Visible = true; - content.LblFirstname.Visible = true; - content.LblLastname.Visible = true; - content.LblInitials.Visible = true; - content.BtnLogin.Visible = false; - content.BtnRegister.Visible = true; - window.Title = "Register"; - }; - - content.BtnRegister.Click += OnButtonRegisterClick; - content.BtnLogin.Click += OnButtonLoginClick; - - window.Content = content; - window.ShowModal(_desktop); - } - - private async void OnButtonLoginClick(object sender, EventArgs e) - { - Container container = ((TextButton)sender).Parent; - while (!(container is Window)) - { - container = container.Parent; - } - - var localWindow = (Window)container; - var localContent = localWindow.Content as LoginRegisterWindow; - var isValid = true; - isValid &= ValidateTextbox(localContent.TxtEmail); - isValid &= ValidateTextbox(localContent.TxtPassword); - - if (!isValid) - { - return; - } - - var successful = false; - try - { - var httpClientHandler = new HttpClientHandler(); - - //if (myConfigurationService.VerifySslCertificate == false) - //{ - httpClientHandler.ServerCertificateCustomValidationCallback = - (message, certificate, chain, sslPolicyErrors) => true; - - var identiyApi = RestService.For( - new HttpClient(httpClientHandler) - { - BaseAddress = new Uri("http://localhost:4000") - }); - - _authResponse = await identiyApi.Authenticate(new AuthenticateModel - { - Username = localContent.TxtEmail.Text, - Password = localContent.TxtPassword.Text - }); - successful = true; - } - catch (Exception ex) - { - - } - if (successful) - { - localWindow.Close(); - }; - } - - private bool ValidateTextbox(TextBox textBox) - { - var valid = !string.IsNullOrWhiteSpace(textBox.Text); - if (!valid) - { - textBox.Background = new SolidBrush(Color.Red); - } - return valid; - } - - private async void OnButtonRegisterClick(object sender, EventArgs e) - { - Container container = ((TextButton)sender).Parent; - while (!(container is Window)) - { - container = container.Parent; - } - - var localWindow = (Window)container; - var localContent = localWindow.Content as LoginRegisterWindow; - var isValid = true; - isValid &= ValidateTextbox(localContent.TxtEmail); - isValid &= ValidateTextbox(localContent.TxtPassword); - isValid &= ValidateTextbox(localContent.TxtFirstname); - isValid &= ValidateTextbox(localContent.TxtLastname); - isValid &= ValidateTextbox(localContent.TxtInitials); - - if (!isValid) - { - return; - } - - var successful = false; - try - { - var httpClientHandler = new HttpClientHandler(); - - //if (myConfigurationService.VerifySslCertificate == false) - //{ - httpClientHandler.ServerCertificateCustomValidationCallback = - (message, certificate, chain, sslPolicyErrors) => true; - - var identiyApi = RestService.For( - new HttpClient(httpClientHandler) - { - BaseAddress = new Uri("http://localhost:4000") - }); - var result = await identiyApi.Register(new RegisterModel - { - Username = localContent.TxtEmail.Text, - Password = localContent.TxtPassword.Text, - FirstName = localContent.TxtFirstname.Text, - LastName = localContent.TxtLastname.Text, - Initials = localContent.TxtInitials.Text - }); - if (result.IsSuccessStatusCode) - { - _authResponse = await identiyApi.Authenticate(new AuthenticateModel - { - Username = localContent.TxtEmail.Text, - Password = localContent.TxtPassword.Text - }); - successful = true; - } - } - catch (Exception ex) - { - - } - if (successful) - { - localWindow.Close(); - }; - } - - private void OnMenuConnectNewSelected(object sender, EventArgs e) - { - Window window = new Window - { - Title = "New mapping session" - }; - - var content = new SessionWindow(); - content.BtnLogin.Text = "Join"; - content.BtnLogin.Click += OnButtonNewSessionClicked; - window.Content = content; - - window.ShowModal(_desktop); - - - } - - private async void OnButtonNewSessionClicked(object sender, EventArgs e) - { - Container container = ((TextButton)sender).Parent; - while (!(container is Window)) - { - container = container.Parent; - } - var localWindow = (Window)container; - var localContent = localWindow.Content as SessionWindow; - var isValid = ValidateTextbox(localContent.TxtSession); - if (!isValid) - { - return; - } - - if (_communicationManager.Connection.State != HubConnectionState.Connected) - { - await _communicationManager.Connection.StartAsync(); - } - - var successful = false; - try - { - var session = await _communicationManager.Connection?.InvokeAsync("NewSession", localContent.TxtSession.Text, _authResponse.Initials); - if (session != null) - { - _sessionData = session; - _sessionData.SessionName = textbox.Text; - session.MapEntityAdded += OnMapEntityAdded; - session.Players = session.Players; - - } - successful = session != null; - } - catch { } - if (successful) - { - _sessionData.SessionName = localContent.TxtSession.Text; - _communicationManager.SessionData = _sessionData; - localWindow.Close(); - } - } - - private void OnMenuFileSaveSelected(object sender, EventArgs e) - { - FileDialog dialog = new FileDialog(FileDialogMode.SaveFile) - { - Filter = "*.map" - }; - - dialog.Closed += (s, a) => - { - if (!dialog.Result) - { - return; - } - - using (StreamWriter file = File.CreateText(dialog.FilePath)) - { - JsonSerializer serializer = new JsonSerializer(); - serializer.Serialize(file, _sessionData); - } - }; - - dialog.ShowModal(_desktop); - } - - private void OnMenuFileLoadSelected(object sender, EventArgs e) - { - FileDialog dialog = new FileDialog(FileDialogMode.OpenFile) - { - Filter = "*.map" - }; - - dialog.Closed += (s, a) => - { - if (!dialog.Result) - { - return; - } - using (StreamReader file = File.OpenText(dialog.FilePath)) - { - JsonSerializer serializer = new JsonSerializer(); - _sessionData = (Session)serializer.Deserialize(file, typeof(Session)); - } - }; - - dialog.ShowModal(_desktop); - } - - private async void OnMenuConnectSyncSelected(object sender, EventArgs e) - { - await _communicationManager.Connection?.InvokeAsync("Sync", _sessionData.SessionName, _sessionData); - } - protected override void LoadContent() { _spriteBatch = new SpriteBatch(GraphicsDevice); @@ -436,20 +63,20 @@ namespace Sledgemapper var menu = BuildMenu(); mainPanel.Widgets.Add(menu); - var sidePanel = new VerticalStackPanel { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h"), Background = new SolidBrush(Color.DarkGray) }; + var sidePanel = new VerticalStackPanel { Layout2d = new Layout2D("this.w=200;this.h=W.h"), Background = new SolidBrush(Color.DarkGray) }; - var tileScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") }; - var tileGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; + var tileScrollView = new ScrollViewer { Layout2d = new Layout2D("this.w=200;this.h=W.h/3") }; + var tileGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; tileScrollView.Content = tileGrid; sidePanel.Widgets.Add(tileScrollView); - var wallScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") }; - var wallGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; + var wallScrollView = new ScrollViewer { Layout2d = new Layout2D("this.w=200;this.h=W.h/3") }; + var wallGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; wallScrollView.Content = wallGrid; sidePanel.Widgets.Add(wallScrollView); - var overlayScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") }; - var overlayGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; + var overlayScrollView = new ScrollViewer { Layout2d = new Layout2D("this.w=200;this.h=W.h/3") }; + var overlayGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) }; overlayScrollView.Content = overlayGrid; sidePanel.Widgets.Add(overlayScrollView); @@ -541,18 +168,13 @@ namespace Sledgemapper _fonts = Content.LoadContentFolder("fonts"); - // Add it to the desktop - // _desktop = new Desktop(); _desktop.Root = mainPanel; - // TODO: use this.Content to load your game content here } protected override void Update(GameTime gameTime) { - // if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) - // Exit(); KeyboardState newState = Keyboard.GetState(); - // TODO: Add your update logic here + if (IsActive && GraphicsDevice.Viewport.Bounds.Contains(Mouse.GetState().Position) && !_desktop.IsMouseOverGUI && !_desktop.HasModalWidget) { var mouseState = Mouse.GetState(); @@ -690,7 +312,6 @@ namespace Sledgemapper } GraphicsDevice.Clear(Color.DarkGray); - // TODO: Add your drawing code here var visibleTilesX = GraphicsDevice.Viewport.Width / _state._tileSize + 1; var visibleTilesY = GraphicsDevice.Viewport.Height / _state._tileSize + 1; @@ -713,13 +334,11 @@ namespace Sledgemapper { _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._insertMode == InsertMode.Overlay && _state._selectedOverlay.Intersection) { - if (_state._selectedOverlay.Intersection) - { - _spriteBatch.DrawCircle(overlay, _state._tileSize / 3, 100, Color.Red, 2); - } + _spriteBatch.DrawCircle(overlay, _state._tileSize / 3f, 100, Color.Red, 2); } _spriteBatch.End(); @@ -728,18 +347,58 @@ namespace Sledgemapper base.Draw(gameTime); } + private HorizontalMenu BuildMenu() + { + var menu = new HorizontalMenu(); + var menuFile = new MenuItem("_file", "File"); + var menuFileLoad = new MenuItem("_file_load", "Load"); + var menuFileSave = new MenuItem("_file_save", "Save"); + var menuConnect = new MenuItem("_connect", "Connect"); + var menuConnectLogin = new MenuItem("_connect_login", "Login"); + var menuConnectNew = new MenuItem("_connect_new", "New"); + var menuConnectJoin = new MenuItem("_connect_join", "Join"); + var menuConnectSync = new MenuItem("_connect_sync", "Sync"); + + menuConnectSync.Selected += OnMenuConnectSyncSelected; + menuFileLoad.Selected += OnMenuFileLoadSelected; + menuFileSave.Selected += OnMenuFileSaveSelected; + menuConnectLogin.Selected += OnMenuConnectLoginSelected; + menuConnectNew.Selected += OnMenuConnectNewSelected; + menuConnectJoin.Selected += OnMenuConnectJoinSelected; + + menuConnect.Items.Add(menuConnectLogin); + menuConnect.Items.Add(menuConnectNew); + menuConnect.Items.Add(menuConnectJoin); + menuConnect.Items.Add(menuConnectSync); + menu.Items.Add(menuConnect); + menuFile.Items.Add(menuFileLoad); + menuFile.Items.Add(menuFileSave); + menu.Items.Add(menuFile); + menu.Items.Add(menuConnect); + + return menu; + } + + private void ClearSelection(Grid grid) + { + foreach (var widget in grid.Widgets) + { + widget.Border = null; + } + } + private void DrawGrid(int visibleTilesX, int visibleTilesY) { for (var i = -1; i < visibleTilesX + 2; i++) { var posX1 = i * _state._tileSize - _viewportCenter.X; var posY1 = -_viewportCenter.Y; - posX1 = posX1 - posX1 % _state._tileSize; - posY1 = posY1 - posY1 % _state._tileSize; + posX1 -= posX1 % _state._tileSize; + posY1 -= posY1 % _state._tileSize; var posX2 = i * _state._tileSize - _viewportCenter.X; var posY2 = GraphicsDevice.Viewport.Height - _viewportCenter.Y; - posX2 = posX2 - posX2 % _state._tileSize; - posY2 = posY2 - posY2 % _state._tileSize; + posX2 -= posX2 % _state._tileSize; + posY2 -= posY2 % _state._tileSize; _spriteBatch.DrawLine( posX1, posY1, @@ -752,12 +411,12 @@ namespace Sledgemapper { var posX1 = -_viewportCenter.X; var posY1 = i * _state._tileSize - _viewportCenter.Y; - posX1 = posX1 - posX1 % _state._tileSize; - posY1 = posY1 - posY1 % _state._tileSize; + posX1 -= posX1 % _state._tileSize; + posY1 -= posY1 % _state._tileSize; var posX2 = GraphicsDevice.Viewport.Width - _viewportCenter.X; var posY2 = i * _state._tileSize - _viewportCenter.Y; - posX2 = posX2 - posX2 % _state._tileSize; - posY2 = posY2 - posY2 % _state._tileSize; + posX2 -= posX2 % _state._tileSize; + posY2 -= posY2 % _state._tileSize; _spriteBatch.DrawLine(posX1, posY1, posX2, @@ -766,45 +425,6 @@ namespace Sledgemapper } } - private void DrawTiles() - { - foreach (var tile in _sessionData.Map.Values) - { - 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 - 1) / content.Width, SpriteEffects.None, 0); - } - } - - 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) @@ -829,6 +449,45 @@ namespace Sledgemapper } } + 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 = _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 DrawTiles() + { + foreach (var tile in _sessionData.Map.Values) + { + 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 - 1) / content.Width, SpriteEffects.None, 0); + } + } + private void DrawWalls() { foreach (var wall in _sessionData.Walls.Values) @@ -850,12 +509,338 @@ namespace Sledgemapper } } - private void ClearSelection(Grid grid) + private async void OnButtonJoinSessionClicked(object sender, EventArgs e) { - foreach (var widget in grid.Widgets) + Container container = ((TextButton)sender).Parent; + while (!(container is Window)) { - widget.Border = null; + container = container.Parent; } + var localWindow = (Window)container; + var localContent = localWindow.Content as SessionWindow; + var isValid = ValidateTextbox(localContent.TxtSession); + if (!isValid) + { + return; + } + + if (_communicationManager.Connection.State != HubConnectionState.Connected) + { + await _communicationManager.Connection.StartAsync(); + } + + var successful = false; + try + { + var result = await _communicationManager.Connection?.InvokeAsync("JoinSession", localContent.TxtSession.Text, _authResponse.Initials); + if (result != null) + { + _sessionData.Map = result.Map; + _sessionData.Walls = result.Walls; + _sessionData.Overlays = result.Overlays; + _sessionData.Players = result.Players; + _sessionData.MapEntityAdded += OnMapEntityAdded; + _sessionData.MapEntityDeleted += OnMapEntityDeleted; + } + successful = result != null; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + if (successful) + { + _sessionData.SessionName = localContent.TxtSession.Text; + localWindow.Close(); + } + } + + private async void OnButtonNewSessionClicked(object sender, EventArgs e) + { + Container container = ((TextButton)sender).Parent; + while (!(container is Window)) + { + container = container.Parent; + } + var localWindow = (Window)container; + var localContent = localWindow.Content as SessionWindow; + var isValid = ValidateTextbox(localContent.TxtSession); + if (!isValid) + { + return; + } + + if (_communicationManager.Connection.State != HubConnectionState.Connected) + { + await _communicationManager.Connection.StartAsync(); + } + + var successful = false; + try + { + var session = await _communicationManager.Connection?.InvokeAsync("NewSession", localContent.TxtSession.Text, _authResponse.Initials); + if (session != null) + { + _sessionData = session; + _sessionData.SessionName = localContent.TxtSession.Text; + _sessionData.MapEntityAdded += OnMapEntityAdded; + _sessionData.Players = session.Players; + + } + successful = session != null; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + if (successful) + { + _sessionData.SessionName = localContent.TxtSession.Text; + _communicationManager.SessionData = _sessionData; + localWindow.Close(); + } + } + + private async void OnButtonLoginClick(object sender, EventArgs e) + { + Container container = ((TextButton)sender).Parent; + while (!(container is Window)) + { + container = container.Parent; + } + + var localWindow = (Window)container; + var localContent = localWindow.Content as LoginRegisterWindow; + var isValid = true; + isValid &= ValidateTextbox(localContent.TxtEmail); + isValid &= ValidateTextbox(localContent.TxtPassword); + + if (!isValid) + { + return; + } + + var successful = false; + try + { + var httpClientHandler = new HttpClientHandler(); + +#if DEBUG + httpClientHandler.ServerCertificateCustomValidationCallback = + (message, certificate, chain, sslPolicyErrors) => true; +#endif + + var identiyApi = RestService.For( + new HttpClient(httpClientHandler) + { + BaseAddress = new Uri("http://localhost:4000") + }); + + _authResponse = await identiyApi.Authenticate(new AuthenticateModel + { + Username = localContent.TxtEmail.Text, + Password = localContent.TxtPassword.Text + }); + successful = _authResponse != null; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + if (successful) + { + localWindow.Close(); + } + } + + private async void OnButtonRegisterClick(object sender, EventArgs e) + { + Container container = ((TextButton)sender).Parent; + while (!(container is Window)) + { + container = container.Parent; + } + + var localWindow = (Window)container; + var localContent = localWindow.Content as LoginRegisterWindow; + var isValid = true; + isValid &= ValidateTextbox(localContent.TxtEmail); + isValid &= ValidateTextbox(localContent.TxtPassword); + isValid &= ValidateTextbox(localContent.TxtFirstname); + isValid &= ValidateTextbox(localContent.TxtLastname); + isValid &= ValidateTextbox(localContent.TxtInitials); + + if (!isValid) + { + return; + } + + var successful = false; + try + { + var httpClientHandler = new HttpClientHandler(); + +#if DEBUG + httpClientHandler.ServerCertificateCustomValidationCallback = + (message, certificate, chain, sslPolicyErrors) => true; +#endif + + var identiyApi = RestService.For( + new HttpClient(httpClientHandler) + { + BaseAddress = new Uri("http://localhost:4000") + }); + var result = await identiyApi.Register(new RegisterModel + { + Username = localContent.TxtEmail.Text, + Password = localContent.TxtPassword.Text, + FirstName = localContent.TxtFirstname.Text, + LastName = localContent.TxtLastname.Text, + Initials = localContent.TxtInitials.Text + }); + if (result.IsSuccessStatusCode) + { + _authResponse = await identiyApi.Authenticate(new AuthenticateModel + { + Username = localContent.TxtEmail.Text, + Password = localContent.TxtPassword.Text + }); + successful = true; + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + if (successful) + { + localWindow.Close(); + } + } + + private void OnMenuConnectJoinSelected(object sender, EventArgs e) + { + Window window = new Window + { + Title = "Join mapping session" + }; + + var content = new SessionWindow(); + content.BtnLogin.Text = "Join"; + content.BtnLogin.Click += OnButtonJoinSessionClicked; + window.Content = content; + + window.ShowModal(_desktop); + } + + private void OnMenuConnectLoginSelected(object sender, EventArgs e) + { + Window window = new Window + { + Title = "Login" + }; + + var content = new LoginRegisterWindow(); + content.RdoLogin.IsPressed = true; + content.RdoLogin.Click += (s, e) => + { + content.TxtFirstname.Visible = false; + content.TxtLastname.Visible = false; + content.TxtInitials.Visible = false; + content.LblFirstname.Visible = false; + content.LblLastname.Visible = false; + content.LblInitials.Visible = false; + content.BtnLogin.Visible = true; + content.BtnRegister.Visible = false; + window.Title = "Login"; + }; + + content.RdoRegister.Click += (s, e) => + { + content.TxtFirstname.Visible = true; + content.TxtLastname.Visible = true; + content.TxtInitials.Visible = true; + content.LblFirstname.Visible = true; + content.LblLastname.Visible = true; + content.LblInitials.Visible = true; + content.BtnLogin.Visible = false; + content.BtnRegister.Visible = true; + window.Title = "Register"; + }; + + content.BtnRegister.Click += OnButtonRegisterClick; + content.BtnLogin.Click += OnButtonLoginClick; + + window.Content = content; + window.ShowModal(_desktop); + } + + private async void OnMenuConnectSyncSelected(object sender, EventArgs e) + { + await _communicationManager.Connection?.InvokeAsync("Sync", _sessionData.SessionName, _sessionData); + } + + private void OnMenuConnectNewSelected(object sender, EventArgs e) + { + Window window = new Window + { + Title = "New mapping session" + }; + + var content = new SessionWindow(); + content.BtnLogin.Text = "Join"; + content.BtnLogin.Click += OnButtonNewSessionClicked; + window.Content = content; + + window.ShowModal(_desktop); + + + } + + private void OnMenuFileSaveSelected(object sender, EventArgs e) + { + FileDialog dialog = new FileDialog(FileDialogMode.SaveFile) + { + Filter = "*.map" + }; + + dialog.Closed += (s, a) => + { + if (!dialog.Result) + { + return; + } + + using StreamWriter file = File.CreateText(dialog.FilePath); + JsonSerializer serializer = new JsonSerializer(); + serializer.Serialize(file, _sessionData); + }; + + dialog.ShowModal(_desktop); + } + + private void OnMenuFileLoadSelected(object sender, EventArgs e) + { + var dialog = new FileDialog(FileDialogMode.OpenFile) + { + Filter = "*.map" + }; + + dialog.Closed += (s, a) => + { + if (!dialog.Result) + { + return; + } + using StreamReader file = File.OpenText(dialog.FilePath); + JsonSerializer serializer = new JsonSerializer(); + _sessionData = (Session)serializer.Deserialize(file, typeof(Session)); + }; + + dialog.ShowModal(_desktop); } private void OnMapEntityAdded(object sender, MapEntityAddedEventArgs e) @@ -867,6 +852,16 @@ namespace Sledgemapper { _communicationManager.Enqueue(e.MapEntity, TileAction.Delete); } + + private bool ValidateTextbox(TextBox textBox) + { + var valid = !string.IsNullOrWhiteSpace(textBox.Text); + if (!valid) + { + textBox.Background = new SolidBrush(Color.Red); + } + return valid; + } } public enum TileAction