using RBG_Server;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace RBG_Server_WPF
{
///
/// Interaction logic for ConnectionPage.xaml
///
public partial class ConnectionPage : Page
{
public ConnectionPage()
{
InitializeComponent();
}
private void HostButton_Click(object sender, RoutedEventArgs e)
{
// Draw host window
ServerGrid.Visibility = Visibility.Visible;
ServerSelectPanel.Visibility = Visibility.Collapsed;
}
private void ConnectButton_Click(object sender, RoutedEventArgs e)
{
// Draw client window
ClientGrid.Visibility = Visibility.Visible;
ServerSelectPanel.Visibility = Visibility.Collapsed;
}
private void BackButton_Click(object sender, RoutedEventArgs e)
{
// Hide host view, show connect view
ServerGrid.Visibility = Visibility.Collapsed;
ServerSelectPanel.Visibility = Visibility.Visible;
}
private void ClientBackButton_Click(object sender, RoutedEventArgs e)
{
ClientGrid.Visibility = Visibility.Collapsed;
ServerSelectPanel.Visibility = Visibility.Visible;
}
private void ClientServerConnectButton_Click(object sender, RoutedEventArgs e)
{
// Run an async connection task
// This task establishes a connection, then
Task clientConnect = new Task( async () =>
{
TcpClient client = new TcpClient();
try
{
await client.ConnectAsync(ServerAddressConnectBox.Text, int.Parse(ServerPortConnectBox.Text));
if (client.Connected)
{
// Invoke the display to update
Dispatcher.Invoke(() =>
{
StatusTextBlock.Text = "Connected!";
StatusTextBlock.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
});
// Run image downloading for the sprite
// This task is contained in the CommunicationHandler class
Progress progress = new Progress();
Task t = App.Context.GameCommunicationHandler.InitDataLoader(client.GetStream(), progress);
progress.ProgressChanged += Progress_ProgressChanged;
t.Start(); // t is asynchronous; we don't need to monitor/await progress as it fires its progress through the assigned handler
// We should, however, ensure that we don't make requests on client until progress is completed
}
else
{
Dispatcher.Invoke(() =>
{
StatusTextBlock.Text = "Connection Failed";
StatusTextBlock.Foreground = new SolidColorBrush(Color.FromRgb(255, 0, 0));
});
}
}
catch (Exception ex)
{
Dispatcher.Invoke(() =>
{
StatusTextBlock.Text = ex.Message[..(128 < ex.Message.Length ? 128 : ex.Message.Length)];
StatusTextBlock.Foreground = new SolidColorBrush(Color.FromRgb(255, 0, 0));
});
client?.Dispose();
}
});
}
///
/// Callback that updates the UI with the new images, once downloaded
///
///
///
///
private void Progress_ProgressChanged(object sender, CommunicationHandler.ProgressData e)
{
// Load sprites as they arrive
if (e.CurrentActivity == CommunicationHandler.ProgressData.Activity.ImageDownloaded)
{
Dispatcher.Invoke(() => StatusTextBlock.Text = $"Downloaded {e.Progress} of {App.Context.GameCommunicationHandler.ImageList.Count} images.");
App.Context.GameCommunicationHandler.ImageCollection.TryGetValue(e.Message, out CachedByteArray cachedByteArray);
BitmapImage image = new();
image.BeginInit();
image.StreamSource = new MemoryStream(cachedByteArray, false);
image.EndInit();
Image spriteImage = new()
{
Source = image
};
if (e.Message == App.Context.GameCommunicationHandler.BoardName)
{
// Image is the board image
Dispatcher.Invoke(() =>BoardPreviewImage.Source = image);
}
else
{
// Image is a sprite, load it
LoadedSpriteGrid loadedSprite = null;
foreach (LoadedSpriteGrid item in ClientLoadedSprites.Children)
{
if (item.Equals(e.Message))
{
loadedSprite = item;
break;
}
}
if (loadedSprite == null) loadedSprite = new LoadedSpriteGrid(spriteImage, e.Message);
// Add the loaded image into the view
Dispatcher.Invoke(() => ClientLoadedSprites.Children.Add(loadedSprite));
}
}
}
internal class LoadedSpriteGrid : Grid
{
string imageName;
public LoadedSpriteGrid(Image spriteImage, string imageName)
{
Children.Add(spriteImage);
this.imageName = imageName;
}
public new bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return imageName.Equals(((LoadedSpriteGrid)obj).imageName);
}
}
}
}