diff --git a/Client/Client.cs b/Client/Client.cs index 6ba9b16..5346d92 100644 --- a/Client/Client.cs +++ b/Client/Client.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Net.Sockets; using System.Text; +using static SharedClientServer.JSONConvert; namespace Client { + public delegate void OnLobbyCreated(int id); class Client : ObservableObject { private TcpClient tcpClient; @@ -18,6 +20,11 @@ namespace Client public bool Connected = false; private string username; public Callback OnSuccessfullConnect; + public Callback OnLobbiesListReceived; + public Callback OnLobbyJoinSuccess; + public Callback OnLobbiesReceivedAndWaitingForHost; + public OnLobbyCreated OnLobbyCreated; + public Lobby[] Lobbies { get; set; } public Client(string username) { @@ -65,14 +72,15 @@ namespace Client } stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(OnReadComplete), null); - } private void handleData(byte[] message) { - byte id = message[0]; - byte[] payload = new byte[message.Length - 1]; - Array.Copy(message, 1, payload, 0, message.Length - 1); + byte id = message[4]; + + byte[] payload = new byte[message.Length - 5]; + Array.Copy(message, 5, payload, 0, message.Length - 5); + switch (id) { case JSONConvert.LOGIN: @@ -83,17 +91,41 @@ namespace Client (string, string) combo = JSONConvert.GetUsernameAndMessage(payload); string textUsername = combo.Item1; string textMsg = combo.Item2; - //TODO display username and message in chat window + //TODO display username and message in chat window + Debug.WriteLine("[CLIENT] INCOMING MESSAGE!"); + Debug.WriteLine("[CLIENT] User name: {0}\t User message: {1}", textUsername, textMsg); break; case JSONConvert.LOBBY: // lobby data + LobbyIdentifier lobbyIdentifier = JSONConvert.GetLobbyIdentifier(payload); + switch (lobbyIdentifier) + { + case LobbyIdentifier.LIST: + Debug.WriteLine("got lobbies list"); + Lobbies = JSONConvert.GetLobbiesFromMessage(payload); + OnLobbiesListReceived?.Invoke(); + OnLobbiesReceivedAndWaitingForHost?.Invoke(); + break; + case LobbyIdentifier.HOST: + // we receive this when the server has made us a host of a new lobby + // TODO get lobby id + Debug.WriteLine("[CLIENT] got lobby object"); + int lobbyCreatedID = JSONConvert.GetLobbyID(payload); + OnLobbyCreated?.Invoke(lobbyCreatedID); + break; + case LobbyIdentifier.JOIN_SUCCESS: + OnLobbyJoinSuccess?.Invoke(); + break; + } //TODO fill lobby with the data received break; + case JSONConvert.CANVAS: // canvas data break; + default: Debug.WriteLine("[CLIENT] Received weird identifier: " + id); break; diff --git a/Client/ClientData.cs b/Client/ClientData.cs index 9442e8d..8a217a0 100644 --- a/Client/ClientData.cs +++ b/Client/ClientData.cs @@ -30,6 +30,7 @@ namespace Client private User _user; private Client _client; private Lobby _lobby; + private string _message; private ClientData() { @@ -55,5 +56,17 @@ namespace Client set { _lobby = value; } } + public String Message + { + get + { + return _message; + } + set + { + _message = value; + } + } + } } diff --git a/Client/ViewModels/ViewModel.cs b/Client/ViewModels/ViewModel.cs index be55690..bbb9843 100644 --- a/Client/ViewModels/ViewModel.cs +++ b/Client/ViewModels/ViewModel.cs @@ -9,6 +9,8 @@ using System.Diagnostics; using System.Windows; using System.Collections.ObjectModel; using Client.Views; +using System.Linq; +using System.Windows.Data; namespace Client { @@ -21,21 +23,101 @@ namespace Client public Lobby SelectedLobby { get; set; } + private Client client; + + private bool wantToBeHost = false; + private int wantToBeHostId = 0; + public ViewModel() { _model = new Model(); _lobbies = new ObservableCollection(); + client = ClientData.Instance.Client; + client.OnLobbiesListReceived = updateLobbies; + - _lobbies.Add(new Lobby(50, 3, 8)); - _lobbies.Add(new Lobby(69, 1, 9)); - _lobbies.Add(new Lobby(420, 7, 7)); + OnHostButtonClick = new RelayCommand(hostGame); - OnHostButtonClick = new RelayCommand(() => + JoinSelectedLobby = new RelayCommand(joinLobby, true); + } + + private void hostGame() + { + Debug.WriteLine("attempting to host game for " + ClientData.Instance.User.Username); + client.SendMessage(JSONConvert.ConstructLobbyHostMessage()); + client.OnLobbyCreated = becomeHostForLobby; + } + + private void becomeHostForLobby(int id) + { + + Debug.WriteLine($"got host succes with data {id} "); + wantToBeHost = true; + wantToBeHostId = id; + client.OnLobbiesReceivedAndWaitingForHost = hostLobbiesReceived; + + } + + private void hostLobbiesReceived() + { + if (wantToBeHost) + foreach (Lobby l in Lobbies) + { + if (l.ID == wantToBeHostId) + { + Debug.WriteLine("found lobby that we want to be host of: " + l.ID + ", joining.."); + SelectedLobby = l; + startGameInLobby(); + wantToBeHost = false; + client.OnLobbiesReceivedAndWaitingForHost = null; + break; + } + } + } + + private void joinLobby() + { + // lobby die je wilt joinen verwijderen + // nieuwe binnengekregen lobby toevoegen + client.OnLobbyJoinSuccess = OnLobbyJoinSuccess; + client.SendMessage(JSONConvert.ConstructLobbyJoinMessage(SelectedLobby.ID)); + } + + private void OnLobbyJoinSuccess() + { + startGameInLobby(); + } + + + + private void updateLobbies() + { + Debug.WriteLine("updating lobbies..."); + Lobby[] lobbiesArr = client.Lobbies; + Application.Current.Dispatcher.Invoke(delegate { - Debug.WriteLine("Host button clicked"); - }); + + //for (int i = 0; i < lobbiesArr.Length; i++) + //{ + // Lobby lobby = lobbiesArr[i]; + // Debug.WriteLine(lobby.PlayersIn); + // if (i < _lobbies.Count && _lobbies[i].ID == lobby.ID) + // { + // _lobbies[i].Set(lobby); + // } else + // { + // _lobbies.Add(lobbiesArr[i]); + // } + //} - JoinSelectedLobby = new RelayCommand(startGameInLobby, true); + _lobbies.Clear(); + + foreach (Lobby l in lobbiesArr) + { + _lobbies.Add(l); + } + + }); } private void startGameInLobby() @@ -43,11 +125,18 @@ namespace Client if (SelectedLobby != null) { ClientData.Instance.Lobby = SelectedLobby; - - _model.CanStartGame = false; + startGameWindow(); + } + } + + private void startGameWindow() + { + _model.CanStartGame = false; + Application.Current.Dispatcher.Invoke(delegate + { GameWindow window = new GameWindow(); window.Show(); - } + }); } private void ClickCheck() diff --git a/Client/ViewModels/ViewModelGame.cs b/Client/ViewModels/ViewModelGame.cs index 672cc5f..65fd353 100644 --- a/Client/ViewModels/ViewModelGame.cs +++ b/Client/ViewModels/ViewModelGame.cs @@ -1,4 +1,6 @@ + using Client.Views; +using GalaSoft.MvvmLight.Command; using SharedClientServer; using System.Collections.ObjectModel; using System.ComponentModel; @@ -18,6 +20,26 @@ namespace Client.ViewModels private Point currentPoint = new Point(); private Color color; + public ObservableCollection Messages { get; } = new ObservableCollection(); + + private dynamic _payload; + + private string _username; + + private string _message; + public string Message + { + get + { + return _message; + } + set + { + _message = value; + } + } + public ICommand OnKeyDown { get; set; } + public void Canvas_MouseDown(MouseButtonEventArgs e, GameWindow window) { if (e.ButtonState == MouseButtonState.Pressed) @@ -59,9 +81,46 @@ namespace Client.ViewModels colorSelected.B = window.ClrPcker_Background.SelectedColor.Value.B; color = colorSelected; } + + public ViewModelGame() + { + if (_payload == null) + { + _message = ""; + } + else + { + //_message = data.Message; + //_username = data.User.Username; + //Messages.Add($"{data.User.Username}: {Message}"); + } + OnKeyDown = new RelayCommand(ChatBox_KeyDown); + } + + private void ChatBox_KeyDown() + { + //if enter then clear textbox and send message. + if (Message != string.Empty) AddMessage(Message); + Message = string.Empty; + } + + internal void AddMessage(string message) + { + Messages.Add($"{data.User.Username}: {message}"); + + _payload = new + { + username = data.User.Username, + message = message + }; + + //Broadcast the message after adding it to the list! + data.Client.SendMessage(JSONConvert.GetMessageToSend(JSONConvert.MESSAGE, _payload)); + } } } + diff --git a/Client/Views/GameWindow.xaml b/Client/Views/GameWindow.xaml index e896679..6614197 100644 --- a/Client/Views/GameWindow.xaml +++ b/Client/Views/GameWindow.xaml @@ -48,8 +48,13 @@ - - + + + + + + + diff --git a/Client/Views/GameWindow.xaml.cs b/Client/Views/GameWindow.xaml.cs index 70e6c63..9d90635 100644 --- a/Client/Views/GameWindow.xaml.cs +++ b/Client/Views/GameWindow.xaml.cs @@ -52,31 +52,11 @@ namespace Client.Views // var deepCopy = System.Windows.Markup.XamlReader.Parse(xaml) as UIElement; // TEST.Children.Add(deepCopy); //} - } private void ClrPcker_Background_SelectedColorChanged_1(object sender, RoutedPropertyChangedEventArgs e) { viewModel.Color_Picker(e, this); } - - private void ChatBox_KeyDown(object sender, KeyEventArgs e) - { - //if enter then clear textbox and send message. - if (e.Key.Equals(Key.Enter)) - { - WriteToChat(ChatBox.Text); - ChatBox.Clear(); - } - } - - /* - * Writes the current client's message to the chatbox. - */ - private void WriteToChat(string message) - { - string user = data.User.Username; - SentMessage.AppendText($"{user}: {message}\n"); - } } } diff --git a/Client/Views/LoginScreen.xaml.cs b/Client/Views/LoginScreen.xaml.cs index 780b619..5b742d2 100644 --- a/Client/Views/LoginScreen.xaml.cs +++ b/Client/Views/LoginScreen.xaml.cs @@ -34,6 +34,7 @@ namespace Client.Views Application.Current.Dispatcher.Invoke(delegate { data.User = user; data.Client = client; + client.SendMessage(JSONConvert.ConstructLobbyRequestMessage()); MainWindow startWindow = new MainWindow(); startWindow.Show(); this.Close(); diff --git a/Client/Views/MainWindow.xaml.cs b/Client/Views/MainWindow.xaml.cs index aa9cf2f..fbcf18a 100644 --- a/Client/Views/MainWindow.xaml.cs +++ b/Client/Views/MainWindow.xaml.cs @@ -32,19 +32,6 @@ namespace Client private void Button_Click(object sender, RoutedEventArgs e) { - - Lobby lobbySelected = LobbyList.SelectedItem as Lobby; - if(lobbySelected != null) - { - testLabel.Content = lobbySelected.ID; - colorSelection.IsEnabled = false; - joinButton.IsEnabled = false; - hostButton.IsEnabled = false; - - GameWindow window = new GameWindow(); - window.Show(); - Close(); - } } } } diff --git a/Server/Models/ServerClient.cs b/Server/Models/ServerClient.cs index 9b07b52..90eab73 100644 --- a/Server/Models/ServerClient.cs +++ b/Server/Models/ServerClient.cs @@ -1,10 +1,14 @@  + +using Client; +using Newtonsoft.Json.Linq; using SharedClientServer; using System; using System.Collections.Generic; using System.Diagnostics; using System.Net.Sockets; using System.Text; +using static SharedClientServer.JSONConvert; namespace Server.Models { @@ -16,6 +20,7 @@ namespace Server.Models private byte[] totalBuffer = new byte[1024]; private int totalBufferReceived = 0; public User User { get; set; } + private ServerCommunication serverCom = ServerCommunication.INSTANCE; /// @@ -117,11 +122,17 @@ namespace Server.Models string textUsername = combo.Item1; string textMsg = combo.Item2; + Debug.WriteLine("[SERVERCLIENT] User name: {0}\t User message: {1}", textUsername, textMsg); + // todo handle sending to all except this user the username and message to display in chat + serverCom.SendToLobby(ServerCommunication.INSTANCE.GetLobbyForUser(User),payload); + Debug.WriteLine("Payload has been sent!"); break; case JSONConvert.LOBBY: // lobby data + LobbyIdentifier l = JSONConvert.GetLobbyIdentifier(payload); + handleLobbyMessage(payload,l); break; case JSONConvert.CANVAS: Debug.WriteLine("GOT A MESSAGE FROM THE CLIENT ABOUT THE CANVAS!!!"); @@ -132,7 +143,30 @@ namespace Server.Models Debug.WriteLine("[SERVER] Received weird identifier: " + id); break; } - //TODO implement ways to handle the message + } + + private void handleLobbyMessage(byte[] payload, LobbyIdentifier l) + { + switch (l) + { + case LobbyIdentifier.REQUEST: + Debug.WriteLine("[SERVERCLIENT] got lobby request message, sending lobbies..."); + sendMessage(JSONConvert.ConstructLobbyListMessage(ServerCommunication.INSTANCE.lobbies.ToArray())); + break; + case LobbyIdentifier.HOST: + // add new lobby and add this serverclient to it + int createdLobbyID = ServerCommunication.INSTANCE.HostForLobby(this.User); + Debug.WriteLine("[SERVERCLIENT] created lobby"); + sendMessage(JSONConvert.ConstructLobbyHostCreatedMessage(createdLobbyID)); + ServerCommunication.INSTANCE.sendToAll(JSONConvert.ConstructLobbyListMessage(ServerCommunication.INSTANCE.lobbies.ToArray())); + break; + case LobbyIdentifier.JOIN: + int id = JSONConvert.GetLobbyID(payload); + ServerCommunication.INSTANCE.JoinLobby(this.User,id); + sendMessage(JSONConvert.ConstructLobbyJoinSuccessMessage()); + ServerCommunication.INSTANCE.sendToAll(JSONConvert.ConstructLobbyListMessage(ServerCommunication.INSTANCE.lobbies.ToArray())); + break; + } } /// diff --git a/Server/Models/ServerCommunication.cs b/Server/Models/ServerCommunication.cs index 5507103..497f901 100644 --- a/Server/Models/ServerCommunication.cs +++ b/Server/Models/ServerCommunication.cs @@ -1,5 +1,4 @@ - -using Client; +using Client; using SharedClientServer; using System; using System.Collections.Generic; @@ -33,7 +32,10 @@ namespace Server.Models listener = new TcpListener(IPAddress.Any, port); serverClients = new List(); lobbies = new List(); + Lobby temp = new Lobby(1, 7, 8); + lobbies.Add(temp); serverClientsInlobbies = new Dictionary>(); + serverClientsInlobbies.Add(temp, new List()); } /// @@ -118,6 +120,18 @@ namespace Server.Models } } + public Lobby GetLobbyForUser(User user) + { + foreach (Lobby l in lobbies) + { + if (l.Users.Contains(user)) + { + return l; + } + } + return null; + } + public void AddToLobby(Lobby lobby, User user) { foreach (Lobby l in lobbies) @@ -126,6 +140,7 @@ namespace Server.Models { bool succ; l.AddUser(user, out succ); + Debug.WriteLine("[SERVERCOMM] added user to lobby, now contains " + l.PlayersIn); if (!succ) { // TODO send lobby full message @@ -145,5 +160,28 @@ namespace Server.Models } } } + + public int HostForLobby(User user) + { + Lobby lobby = new Lobby( lobbies.Count + 1,0, 8); + lobbies.Add(lobby); + serverClientsInlobbies.Add(lobby, new List()); + user.Host = true; + AddToLobby(lobby, user); + return lobby.ID; + } + + public void JoinLobby(User user, int id) + { + foreach (Lobby l in lobbies) + { + if (l.ID == id) + { + AddToLobby(l, user); + Debug.WriteLine($"{user.Username} joined lobby with id {id}"); + break; + } + } + } } } diff --git a/SharedClientServer/ClientServerUtil.cs b/SharedClientServer/ClientServerUtil.cs index f79c448..d9d30fe 100644 --- a/SharedClientServer/ClientServerUtil.cs +++ b/SharedClientServer/ClientServerUtil.cs @@ -18,6 +18,5 @@ namespace SharedClientServer Array.Copy(stringAsBytes, 0, res, 1, stringAsBytes.Length); return res; } - } } diff --git a/SharedClientServer/JSONConvert.cs b/SharedClientServer/JSONConvert.cs index b0d83cb..dd967e8 100644 --- a/SharedClientServer/JSONConvert.cs +++ b/SharedClientServer/JSONConvert.cs @@ -1,8 +1,10 @@ using Client; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Text; namespace SharedClientServer @@ -14,11 +16,13 @@ namespace SharedClientServer public const byte LOBBY = 0x03; public const byte CANVAS = 0x04; - enum LobbyIdentifier + public enum LobbyIdentifier { HOST, - ADD, + JOIN, + JOIN_SUCCESS, LEAVE, + LIST, REQUEST } public static (string,string) GetUsernameAndMessage(byte[] json) @@ -43,12 +47,98 @@ namespace SharedClientServer }); } - public static byte[] ConstructLobbyDataMessage(Lobby lobby) + #region lobby messages + + public static byte[] ConstructLobbyHostMessage() { - return null; + return GetMessageToSend(LOBBY, new + { + identifier = LobbyIdentifier.HOST + }); } + public static byte[] ConstructLobbyHostCreatedMessage(int lobbyID) + { + return GetMessageToSend(LOBBY, new + { + identifier = LobbyIdentifier.HOST, + id = lobbyID + }) ; + } + public static byte[] ConstructLobbyRequestMessage() + { + return GetMessageToSend(LOBBY, new + { + identifier = LobbyIdentifier.REQUEST + }); + } + + public static byte[] ConstructLobbyListMessage(Lobby[] lobbiesList) + { + return GetMessageToSend(LOBBY, new + { + identifier = LobbyIdentifier.LIST, + lobbies = lobbiesList + }); + } + + public static byte[] ConstructLobbyJoinMessage(int lobbyID) + { + return GetMessageToSend(LOBBY, new + { + identifier = LobbyIdentifier.JOIN, + id = lobbyID + }); + } + + public static byte[] ConstructLobbyLeaveMessage(int lobbyID) + { + return GetMessageToSend(LOBBY, new + { + identifier = LobbyIdentifier.LEAVE, + id = lobbyID + }); + } + public static LobbyIdentifier GetLobbyIdentifier(byte[] json) + { + dynamic payload = JsonConvert.DeserializeObject(Encoding.ASCII.GetString(json)); + return payload.identifier; + } + + public static Lobby[] GetLobbiesFromMessage(byte[] json) + { + dynamic payload = JsonConvert.DeserializeObject(Encoding.ASCII.GetString(json)); + JArray lobbiesArray = payload.lobbies; + Debug.WriteLine("[JSONCONVERT] got lobbies from message" + lobbiesArray.ToString()); + Lobby[] lobbiesTemp = lobbiesArray.ToObject(); + Debug.WriteLine("lobbies in array: "); + foreach (Lobby l in lobbiesTemp) + { + Debug.WriteLine("players: " + l.PlayersIn); + } + return lobbiesTemp; + } + + public static int GetLobbyID(byte[] json) + { + dynamic payload = JsonConvert.DeserializeObject(Encoding.ASCII.GetString(json)); + return payload.id; + } + + public static Lobby GetLobby(byte[] json) + { + dynamic payload = JsonConvert.DeserializeObject(Encoding.ASCII.GetString(json)); + JObject dynamicAsObject = payload.lobby; + return dynamicAsObject.ToObject(); + } + + public static byte[] ConstructLobbyJoinSuccessMessage() + { + return GetMessageToSend(LOBBY, new { identifier = LobbyIdentifier.JOIN_SUCCESS}); + } + + #endregion /// /// constructs a message that can be sent to the clients or server @@ -70,5 +160,7 @@ namespace SharedClientServer Array.Copy(BitConverter.GetBytes(payloadBytes.Length+5),0,res,0,4); return res; } + + } } diff --git a/SharedClientServer/Lobby.cs b/SharedClientServer/Lobby.cs index 5a69627..2ddf501 100644 --- a/SharedClientServer/Lobby.cs +++ b/SharedClientServer/Lobby.cs @@ -64,16 +64,29 @@ namespace Client public int PlayersIn { - get { return _playersIn; } + get { return _users.Count; } set { _playersIn = value; } } + public void Set(Lobby lobby) + { + this._id = lobby._id; + this._users = lobby._users; + this._maxPlayers = lobby._maxPlayers; + } + public int MaxPlayers { get { return _maxPlayers; } set { _maxPlayers = value; } } + public List Users + { + get { return _users; } + set { _users = value; } + } + } } diff --git a/SharedClientServer/User.cs b/SharedClientServer/User.cs index 6e95f64..e504418 100644 --- a/SharedClientServer/User.cs +++ b/SharedClientServer/User.cs @@ -1,4 +1,5 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.Text; @@ -9,7 +10,9 @@ namespace SharedClientServer private string _username; private int _score; private bool _host; + private string _message; + [JsonConstructor] public User(string username, int score, bool host) { _username = username;