static void Main( string[] args ) { // Generate a Profile object. When this project is near the end of its development, // we will need to remove the leading "..\\"'s from this file path. if ( File.Exists("Profile.txt")) { Profile = new tvProfile("Profile.txt", false); } // If it doesn't exist locally, use the embedded one. else { // Ensure that the pack scheme is known: http://stackoverflow.com/questions/6005398/uriformatexception-invalid-uri-invalid-port-specified string ensurePackSchemeIsKnown = PackUriHelper.UriSchemePack; StreamResourceInfo stream = Application.GetResourceStream(new Uri(PATH_TO_PROFILE, UriKind.Absolute)); StreamReader reader = new StreamReader(stream.Stream); Profile = new tvProfile(reader.ReadToEnd()); } // Create a new deck. Deck = new Deck(Profile); // Create a new list of players. PlayerList = new List<Player>(); // Create a new Dicard Pile. DiscardPile = new List<Card>(); // Create new instance of configs. Parameter is "application Id". It has to be same on client and server. Config = new NetPeerConfiguration("game"); // Set server port Config.Port = ServerUtilities.PORT_NUMBER; // Max client amount Config.MaximumConnections = 200; // Enable New messagetype. Explained later Config.EnableMessageType(NetIncomingMessageType.ConnectionApproval); // Create new server based on the configs just defined Server = new NetServer(Config); // Start it Server.Start(); // Eh.. Console.WriteLine("Server Started"); // Object that can be used to store and read messages NetIncomingMessage inc; // Check time DateTime time = DateTime.Now; // Create timespan of 30ms TimeSpan timetopass = new TimeSpan(0, 0, 0, 0, 30); // Write to con.. Console.WriteLine("Waiting for new connections"); // Main loop // This kind of loop can't be made in XNA. In there, its basically same, but without while // Or maybe it could be while(new messages) while ( true ) { // Server.ReadMessage() Returns new messages, that have not yet been read. // If "inc" is null -> ReadMessage returned null -> Its null, so dont do this :) if ( (inc = Server.ReadMessage()) != null ) { // Theres few different types of messages. To simplify this process, i left only 2 of em here switch ( inc.MessageType ) { // If incoming message is Request for connection approval // This is the very first packet/message that is sent from client // Here you can do new player initialisation stuff case NetIncomingMessageType.ConnectionApproval: { // Read the first byte of the packet // ( Enums can be casted to bytes, so it be used to make bytes human readable ) if ( inc.ReadByte() == (byte)PacketTypes.LOGIN ) { Console.WriteLine("Incoming LOGIN"); // Approve clients connection ( Its sort of agreenment. "You can be my client and i will host you" ) inc.SenderConnection.Approve(); // Debug Console.WriteLine("Approved new connection and updated the world status"); } break; } // All messages manually sent from clients are considered "Data" messages. // ( Approval is an automated process ) case NetIncomingMessageType.Data: { Datatype messageType = (Datatype)inc.ReadByte(); switch ( messageType ) { // Receive an updated Deck from a client. case Datatype.UpdateDeck: { Deck = (Deck)ServerUtilities.ReceiveMessage(inc, messageType); if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.UpdateDeck, Deck); } break; } // Receive an updated DiscardPile from a client. case Datatype.UpdateDiscardPile: { DiscardPile = (List<Card>)ServerUtilities.ReceiveMessage(inc, messageType); // Send the updated DiscardPile to all clients. if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.UpdateDiscardPile, DiscardPile); } break; } // Add or modify a player in the PlayerList. case Datatype.UpdatePlayer: { Player updatedPlayer = (Player)ServerUtilities.ReceiveMessage(inc, messageType); bool isPlayerInList = false; // If the updated Player is already in the server's list, update that's Player's properties. // Note: This search only works if players have unique names. foreach ( Player player in PlayerList ) { if ( updatedPlayer.Name == player.Name ) { player.CardsInHand = updatedPlayer.CardsInHand; player.CardsInPlay = updatedPlayer.CardsInPlay; isPlayerInList = true; break; } } // If the Player is not on the list, add it. if ( !isPlayerInList ) { PlayerList.Add(updatedPlayer); } // Send the updated PlayerList to all clients. if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.UpdatePlayerList, PlayerList); } break; } // Update the server's Player List and send it to the clients. case Datatype.UpdatePlayerList: { PlayerList = (List<Player>)ServerUtilities.ReceiveMessage(inc, messageType); if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.UpdatePlayerList, PlayerList); } break; } // Send the updated turn to all players. case Datatype.UpdateTurn: { Turn = (Turn)ServerUtilities.ReceiveMessage(inc, messageType); if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.UpdateTurn, Turn); } break; } // Set up the players for the game. This case should be hit only when a client launches the game. case Datatype.LaunchGame: { // Deal the initial hands to the players. for ( int i = 0; i < PlayerList.Count; ++i ) { PlayerList[i] = new Player(Deck, PlayerList[i].Name); } //// Send the Player List to the clients. //if ( Server.ConnectionsCount != 0 ) //{ // ServerUtilities.SendMessage(Server, Datatype.UpdatePlayerList, PlayerList); //} // Generate the Turn object to keep track of the current turn. Turn = new Turn(PlayerList.Count); // Tell all clients to launch the game and send them the Turn object. if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.LaunchGame, Turn); } break; } case Datatype.TimeToConnect: { string playerToConnect = (String)ServerUtilities.ReceiveMessage(inc, messageType); // Broadcast a message that tells a specific client to launch the game. if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.TimeToConnect, playerToConnect); } break; } // Send the rent request to all clients. case Datatype.RequestRent: { ActionData.RentRequest request = (ActionData.RentRequest)ServerUtilities.ReadRentRequest(inc); if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.RequestRent, request); } break; } // Send the rent response to all clients. case Datatype.GiveRent: { ActionData.RentResponse response = (ActionData.RentResponse)ServerUtilities.ReadRentResponse(inc); if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.GiveRent, response); } break; } // Send the theft request to all clients. case Datatype.RequestTheft: { ActionData.TheftRequest request = (ActionData.TheftRequest)ServerUtilities.ReadTheftRequest(inc); if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.RequestTheft, request); } break; } // Send the theft response to all clients. case Datatype.ReplyToTheft: { ActionData.TheftResponse response = (ActionData.TheftResponse)ServerUtilities.ReadTheftResponse(inc); if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.ReplyToTheft, response); } break; } case Datatype.EndTurn: { Turn = (Turn)ServerUtilities.ReceiveMessage(inc, Datatype.EndTurn); // Send the updated Turn object to the clients. ServerUtilities.SendMessage(Server, Datatype.EndTurn, Turn); break; } // Send the server's Deck to all clients. case Datatype.RequestDeck: { if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.UpdateDeck, Deck); } break; } // Send the server's PlayerList to all clients. case Datatype.RequestPlayerList: { if ( Server.ConnectionsCount != 0 ) { ServerUtilities.SendMessage(Server, Datatype.UpdatePlayerList, PlayerList); } break; } } break; } case NetIncomingMessageType.StatusChanged: { // In case status changed // It can be one of these // NetConnectionStatus.Connected; // NetConnectionStatus.Connecting; // NetConnectionStatus.Disconnected; // NetConnectionStatus.Disconnecting; // NetConnectionStatus.None; // NOTE: Disconnecting and Disconnected are not instant unless client is shutdown with disconnect() Console.WriteLine(inc.SenderConnection.ToString() + " status changed. " + (NetConnectionStatus)inc.SenderConnection.Status); if ( inc.SenderConnection.Status == NetConnectionStatus.Disconnected || inc.SenderConnection.Status == NetConnectionStatus.Disconnecting ) { } break; } default: { // As i statet previously, theres few other kind of messages also, but i dont cover those in this example // Uncommenting next line, informs you, when ever some other kind of message is received //Console.WriteLine("Not Important Message"); break; } } } // If New messages // if 30ms has passed if ( (time + timetopass) < DateTime.Now ) { time = DateTime.Now; } // While loops run as fast as your computer lets. While(true) can lock your computer up. Even 1ms sleep, lets other programs have piece of your CPU time System.Threading.Thread.Sleep(100); } }
public static Turn ReadTurn( NetIncomingMessage inc ) { int currentTurnOwner = inc.ReadInt32(); int numberOfActions = inc.ReadInt32(); Turn turn = new Turn(currentTurnOwner, numberOfActions); return turn; }
public static void WriteTurn( NetOutgoingMessage outmsg, Turn turn ) { // Write the data related to the current turn. outmsg.Write(turn.CurrentTurnOwner); outmsg.Write(turn.ActionsRemaining); }
// Update the client's window based on messages received from the server. This method is called as soon as the client // receives a message. public void GotMessage( object peer ) { NetIncomingMessage inc; if ( false == this.BeginCommunication ) { // Continue reading messages until the requested update is received. while ( !UpdateReceived && !this.Disconnected ) { Console.WriteLine(this.PlayerName + " stuck in begin"); // Iterate through all of the available messages. while ( (inc = (peer as NetPeer).ReadMessage()) != null ) { if ( inc.MessageType == NetIncomingMessageType.StatusChanged ) { this.BeginCommunication = true; UpdateReceived = true; // Close the wait message if it is open. if ( null != WaitMessage && !WaitMessage.CloseWindow ) { CreateNewThread(new Action<Object>(( sender ) => { WaitMessage.CloseWindow = true; })); } } Thread.Sleep(100); } Thread.Sleep(100); } } else { inc = (peer as NetPeer).ReadMessage(); if ( null != inc && inc.MessageType == NetIncomingMessageType.Data ) { Datatype messageType = (Datatype)inc.ReadByte(); //MessageBox.Show(this.PlayerName + " received " + messageType.ToString()); switch ( messageType ) { case Datatype.UpdatePlayerList: { PlayerList = (List<Player>)ServerUtilities.ReceiveMessage(inc, messageType); if ( null != this.PlayerList && this.PlayerList.Count > 0 ) { CreateNewThread(new Action<Object>(( sender ) => { this.LaunchGameButton.IsEnabled = (this.PlayerList[0].Name == this.PlayerName); })); } //// The parentheses around currentPlayerList are required. See http://bit.ly/19t9NEx. //ThreadStart start = delegate() { Dispatcher.Invoke(DispatcherPriority.Normal, new Action<List<Player>>(UpdatePlayerListBox), (playerList)); }; CreateNewThread(new Action<Object>(UpdatePlayerListBox)); // Close the wait message if it is open. if ( null != WaitMessage && !WaitMessage.CloseWindow ) { CreateNewThread(new Action<Object>(( sender ) => { WaitMessage.CloseWindow = true; })); } break; } case Datatype.LaunchGame: { Console.WriteLine(this.Player.Name + " received Launch"); // Receive the data related to the current turn from the server. this.Turn = (Turn)ServerUtilities.ReceiveMessage(inc, Datatype.LaunchGame); if ( this.PlayerList[0].Name == this.PlayerName ) { CreateNewThread(new Action<Object>(LaunchGame)); } break; } case Datatype.TimeToConnect: { string playerToConnect = (String)ServerUtilities.ReceiveMessage(inc, messageType); if ( this.PlayerName == playerToConnect ) { CreateNewThread(new Action<Object>(LaunchGame)); } break; } } } } }