diff --git a/zsirozas/Game.cs b/zsirozas/Game.cs index 6801cd2a8119477b4aa74b80431b368064537669..c2e9f4428e813ef80d8134ac7a379d9030f9deca 100644 --- a/zsirozas/Game.cs +++ b/zsirozas/Game.cs @@ -88,6 +88,11 @@ namespace zsirozas NotifyPlayers(GameEvent.NewTurn); } + /// <summary> + /// Executes a CardAction. You shold validate your input, before calling. + /// </summary> + /// <param name="playerID">The player who acted.</param> + /// <param name="cardID">The card they used.</param> public void ValidPlayerMakesCardActionInValidTurnWithValidCard(string playerID, int cardID) { //If said player has started the turn... @@ -127,7 +132,14 @@ namespace zsirozas NotifyPlayers(GameEvent.CardAction); } - + /// <summary> + /// Adjust the game state based on the action. Does basic validation on the sensibility of the attempted action. + /// Throws InvalidActionException when it validation fails. + /// </summary> + /// <returns>The action.</returns> + /// <param name="playerID">Player identifier.</param> + /// <param name="action">Action.</param> + /// <param name="cardID">Card identifier.</param> public string Action(string playerID, PlayerAction action, int cardID) { switch (action) @@ -220,6 +232,7 @@ namespace zsirozas //TODO: ezt majd vagyük ki... return null; } + //TODO: <ezt hogy magyarázom el> public void Complain(string message) { throw new InvalidActionException(message); @@ -230,6 +243,7 @@ namespace zsirozas throw new GameOverException(this.gameID); } + //TODO: </ezt hogy magyarázom el> public MidGameState PublicState() { diff --git a/zsirozas/GameServer.cs b/zsirozas/GameServer.cs index 54d4db28866b0076813671c236f221b6e52b74b7..6e6b7a8f6e2c3e87292c5e7a736aca93f1069bc7 100644 --- a/zsirozas/GameServer.cs +++ b/zsirozas/GameServer.cs @@ -48,32 +48,11 @@ namespace zsirozas public List<string> Rooms; public Dictionary<string, Room> RoomsByID; - //public int ListenPort = 6500; - //public void Loop() - //{ - // if (bigRoom) - // { - // string Room0 = "RoomZero"; - // Rooms.Add(Room0); - // RoomsByID.Add( - // Room0, - // new Room() - // { - // roomID = Room0, - // userList = new List<string>() - // } - // ); - // } - // var requestQueue = new TcpListener(IPAddress.Any, ListenPort); - // requestQueue.Start(); - // while (true) - // { - // var clientRequest = requestQueue.AcceptTcpClient(); - // ParseNextMessage(clientRequest.GetStream(), ((IPEndPoint)clientRequest.Client.RemoteEndPoint).Address); - // clientRequest.Close(); - // } - //} - + /// <summary> + /// Reads a message from the specified stream, tries to execute it, and writes back the result. + /// </summary> + /// <param name="s">The stream to work on.</param> + /// <param name="param">An additonal parameter to consider (e.g.: connection info for validation) </param> public void ParseNextMessage(Stream s, object param) { using (var sr = new StreamReader(s)) @@ -288,10 +267,14 @@ namespace zsirozas } sw.Flush(); } - } - + /// <summary> + /// Checks whether the <paramref name="userID"/> and <paramref name="connInfo"/> look suspicious. (e.g.: forged requests). + /// If it does, an InvalidActionException is thrown. + /// </summary> + /// <param name="userID">User identifier.</param> + /// <param name="connInfo">Conn info.</param> private void validateConn(string userID, object connInfo) { if (Users.Contains(userID) && UsersByID[userID].client.ValidateConnection(connInfo)) @@ -304,6 +287,9 @@ namespace zsirozas } } + /// <summary> + /// Shuts down the game server from the inside. + /// </summary> private void Shutdown() { Console.WriteLine("Server shut down succesfully."); @@ -376,6 +362,7 @@ namespace zsirozas return U.userID; } + public void RemoveUser(string userID) { LeaveRoom(userID); @@ -384,6 +371,7 @@ namespace zsirozas Users.Remove(userID); Console.WriteLine("[LOG] " + userID + " logged out"); } + public void LeaveRoom(string userID) { if (bigRoom) throw new InvalidActionException(nameof(bigRoom) + " is set, therefore you can't leave this room."); @@ -402,6 +390,7 @@ namespace zsirozas UsersByID[userID].roomID = null; } } + public void JoinRoom(string userID, string roomID) { if (UsersByID[userID].roomID == null) @@ -417,6 +406,7 @@ namespace zsirozas } else throw new InvalidActionException("You are already in a room!"); } + public string NewGame(string roomID) { if (!Rooms.Contains(roomID)) throw new InvalidActionException("Objection! You cant start a game with a non-existing room."); diff --git a/zsirozas/Program.cs b/zsirozas/Program.cs index 8b8182d8caf138ff15590fd55170ecc7ccf6f086..4a7e416ca32579a85e19518e3c0d146624741c7c 100644 --- a/zsirozas/Program.cs +++ b/zsirozas/Program.cs @@ -9,16 +9,6 @@ namespace zsirozas { public static void Main(string[] args) { - ////teszt a paklihoz - //Console.WriteLine("Hello World!"); - //var deck = new Deck(); - //Console.WriteLine(deck.ToString()); - //Console.WriteLine(string.Join("\n", deck.Deal(2,3).Select(x=>string.Join(" ",x)))); - //Console.WriteLine(deck.cardsDealtSoFar); - //Console.WriteLine(); - //Console.WriteLine(deck.ToString()); - - //args = new string[]{ "--server" }; if (args.Contains("--server")) { new ServerWrapper(new GameServer()).Run(); diff --git a/zsirozas/RawTcpTransport.cs b/zsirozas/RawTcpTransport.cs index cbe77bf9d730e02e05ca0086e7393d59bb354e36..19eca1f66766cf13322090ede28518c2552ace13 100644 --- a/zsirozas/RawTcpTransport.cs +++ b/zsirozas/RawTcpTransport.cs @@ -18,12 +18,6 @@ namespace zsirozas public TcpClient msgConn; public StreamWriter messageStreamW; - public void SendMessage(string message) - { - messageStreamW.WriteLine(message); - messageStreamW.Flush(); - } - public AppClientWithTcp(IPEndPoint backTalk) { msgConn = new TcpClient(); @@ -31,6 +25,16 @@ namespace zsirozas messageStreamW = new StreamWriter(msgConn.GetStream()); } + // + // Implementation of the server API + // + + public void SendMessage(string message) + { + messageStreamW.WriteLine(message); + messageStreamW.Flush(); + } + public void InGameNotify(GameEvent @event, string param0) { messageStreamW.WriteLine(ServerEvent.GameEvent); @@ -262,36 +266,40 @@ namespace zsirozas } } } - //TODO: ezen ronda a control-flow + public object GameAction(string gameID, string userID, PlayerAction action, int cardID) { - var tempConn = new TcpClient(); - tempConn.Connect(server); - using (var sw = new StreamWriter(tempConn.GetStream())) - using (var sr = new StreamReader(tempConn.GetStream())) + using (var tempConn = new TcpClient()) { - sw.WriteLine(); - string status = null; - sw.WriteLine(ServerAction.GameAction); - sw.WriteLine(gameID); - sw.WriteLine(userID); - sw.WriteLine(action); - sw.WriteLine(cardID); - sw.Flush(); - if ((status = sr.ReadLine()) != "OK") - { - status = sr.ReadLine(); - throw new ServerErrorException(status); - } - else if (action == PlayerAction.GetCards) + tempConn.Connect(server); + using (var sw = new StreamWriter(tempConn.GetStream())) + using (var sr = new StreamReader(tempConn.GetStream())) { - status = sr.ReadLine(); - return new JavaScriptSerializer().Deserialize<IEnumerable<Card>>(status).ToArray(); + sw.WriteLine(); + string status = null; + sw.WriteLine(ServerAction.GameAction); + sw.WriteLine(gameID); + sw.WriteLine(userID); + sw.WriteLine(action); + sw.WriteLine(cardID); + sw.Flush(); + if ((status = sr.ReadLine()) != "OK") + { + status = sr.ReadLine(); + throw new ServerErrorException(status); + } + + if (action == PlayerAction.GetCards) + { + status = sr.ReadLine(); + return new JavaScriptSerializer().Deserialize<IEnumerable<Card>>(status).ToArray(); + } + else + { + return null; + } } } - tempConn.Close(); - //TODO: akarom-e ezt? - return true; } public ServerInfo ServerInfo() diff --git a/zsirozas/Rooms.cs b/zsirozas/Rooms.cs index d9ff4efe0590f0d1fe3a543a6c8e83533920d9f3..a3ed3c9c549f473d5b7cc2093ba2f540f27e2de0 100644 --- a/zsirozas/Rooms.cs +++ b/zsirozas/Rooms.cs @@ -25,19 +25,18 @@ namespace zsirozas public string roomID; public bool occupied = false; - //public TcpClient msgConn; - //public StreamWriter messageStreamW; - //public void SendMessage(string message) - //{ - // messageStreamW.WriteLine(message); - // messageStreamW.Flush(); - //} - - //absztraháltuk a kapcsolat típusát public IAppClient client; - //de diagnosztikai célból azért számon tarjuk + + /// <summary> + /// For diagnostic purposes. Use this with reflection to access connection details. + /// </summary> + /// <value>The type of the connection.</value> public ConnectionType connectionType { get; protected set; } } + + /// <summary> + /// Basic information regarding a user. + /// </summary> struct UserInfo { public string nickname; @@ -60,6 +59,10 @@ namespace zsirozas return new JavaScriptSerializer().Deserialize<UserInfo>(s); } } + + /// <summary> + /// Basic information regarding the game server. + /// </summary> struct ServerInfo { public bool bigRoom; @@ -73,6 +76,10 @@ namespace zsirozas return new JavaScriptSerializer().Deserialize<ServerInfo>(s); } } + + /// <summary> + /// Basic information regarding a room. + /// </summary> struct RoomInfo { public string[] players; @@ -85,6 +92,8 @@ namespace zsirozas return new JavaScriptSerializer().Deserialize<RoomInfo>(input); } } + + //TODO: maradjon struct vagy legyen class? struct Room { public string roomID; diff --git a/zsirozas/Round.cs b/zsirozas/Round.cs index bf4c5960165bc15dbb259dcc4fc85609632ee9dd..93b501f54e013e2802765fa8febb55ae76152725 100644 --- a/zsirozas/Round.cs +++ b/zsirozas/Round.cs @@ -14,6 +14,9 @@ namespace zsirozas } class Player { + /// <summary> + /// Uniquely identifies a player in a given game. + /// </summary> public string playerID; //public PlayerState state; @@ -34,6 +37,9 @@ namespace zsirozas } } + /// <summary> + /// Complex datatype representing the state specific to a round of the game. + /// </summary> struct Round { public Round(int _startingPlayer, int Mplayers) @@ -71,6 +77,10 @@ namespace zsirozas /// </summary> public bool[] givenUpThisRound; } + + /// <summary> + /// A "public" representation of the state of the game. Players will receive these as updates. + /// </summary> struct MidGameState { public CardValue[] cardsOnTable; @@ -91,11 +101,17 @@ namespace zsirozas public string[] playersByOrder; } + /// <summary> + /// Invalid action exception. Thrown when a player/user attepmts something they sholdn't. + /// </summary> public class InvalidActionException : Exception { public InvalidActionException(string message) : base(message) { } } + /// <summary> + /// When the game is over, the Game object will throw this. + /// </summary> public class GameOverException : Exception { public GameOverException(string message) : base(message) { } diff --git a/zsirozas/ServerWrapper.cs b/zsirozas/ServerWrapper.cs index 01472a6dfb5be189babe3b6e4b2097ee27cc9f19..b557d0d34d562c3439e62d8689c05d374411baf9 100644 --- a/zsirozas/ServerWrapper.cs +++ b/zsirozas/ServerWrapper.cs @@ -5,9 +5,12 @@ using System.Threading; namespace zsirozas { - //a kommunikációs és vezérlési feladatot megvalósító környezet + //TODO: utánanézni, hogy SignalR-nél hogy megy a párhuzamosság //TODO: biztosítani a szerver adatkonzisztenciáját + /// <summary> + /// A wrapper orchestrating the game server. Most importantly, initializes communication. + /// </summary> class ServerWrapper { public IServerApiProvider serverInstance; @@ -48,12 +51,12 @@ namespace zsirozas controlThread.Abort(); } - //private ezúttal indokolt + //should stay private private void loop_func() { while (true) { - //ha TCP-zek + //when RawTCP is enabled. if (requestQueue != null) { //listen for connections and invoke parseNextMessage @@ -61,7 +64,7 @@ namespace zsirozas serverInstance.ParseNextMessage(clientRequest.GetStream(), ((IPEndPoint)clientRequest.Client.RemoteEndPoint).Address); clientRequest.Close(); } - //ha bármi mást csinálok (SignalR, közvetlen API birizgálás, stb.) + //todo --recomment: ha bármi mást csinálok (SignalR, közvetlen API birizgálás, stb.) else { Thread.Sleep(10000);