// Write a theft request. public static void WriteTheftRequest(NetOutgoingMessage outmsg, ActionData.TheftRequest request) { outmsg.Write(request.ThiefName); outmsg.Write(request.VictimName); outmsg.Write(request.ActionID.ToString()); WriteCards(outmsg, new List <Card>() { request.PropertyToGive }); WriteCards(outmsg, request.PropertiesToTake); }
static void Main(string[] args) { // Attempt to load the game configuration from a config file. if (File.Exists(GameObjectsResourceList.FilePathLocalServerSettings)) { Profile = new tvProfile(GameObjectsResourceList.FilePathLocalServerSettings, false); } // If it doesn't exist locally, use the embedded one. else { Profile = ServerUtilities.GetEmbeddedServerSettings(); } // 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."); } break; } // All messages manually sent from clients are considered "Data" messages. // ( Approval is an automated process ) case NetIncomingMessageType.Data: { Datatype messageType = (Datatype)inc.ReadByte(); // Exclude the sender from the fanout. long idOfSender = inc.SenderConnection.RemoteUniqueIdentifier; switch (messageType) { // Receive an updated Deck from a client. case Datatype.UpdateDeck: { Deck = (Deck)ServerUtilities.ReceiveMessage(inc, messageType); ServerUtilities.SendMessage(Server, Datatype.UpdateDeck, Deck); break; } // Receive an updated DiscardPile from a client. case Datatype.UpdateDiscardPile: { DiscardPile = (List <Card>)ServerUtilities.ReceiveMessage(inc, messageType); 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. 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); ServerUtilities.SendMessage(Server, Datatype.UpdatePlayerList, PlayerList); break; } // Send the updated turn to all players. case Datatype.UpdateTurn: { Turn = (Turn)ServerUtilities.ReceiveMessage(inc, messageType); 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); } // 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. 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. ServerUtilities.SendMessage(Server, Datatype.TimeToConnect, playerToConnect); break; } case Datatype.RequestRent: { ActionData.RentRequest request = (ActionData.RentRequest)ServerUtilities.ReadRentRequest(inc); ServerUtilities.SendMessage(Server, Datatype.RequestRent, request, idOfClientToExclude: idOfSender); break; } case Datatype.GiveRent: { ActionData.RentResponse response = (ActionData.RentResponse)ServerUtilities.ReadRentResponse(inc); ServerUtilities.SendMessage(Server, Datatype.GiveRent, response); break; } case Datatype.RequestTheft: { ActionData.TheftRequest request = (ActionData.TheftRequest)ServerUtilities.ReadTheftRequest(inc); ServerUtilities.SendMessage(Server, Datatype.RequestTheft, request, idOfClientToExclude: idOfSender); break; } case Datatype.ReplyToTheft: { ActionData.TheftResponse response = (ActionData.TheftResponse)ServerUtilities.ReadTheftResponse(inc); ServerUtilities.SendMessage(Server, Datatype.ReplyToTheft, response, idOfClientToExclude: idOfSender); 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: { ServerUtilities.SendMessage(Server, Datatype.UpdateDeck, Deck); break; } // Send the server's PlayerList to all clients. case Datatype.RequestPlayerList: { ServerUtilities.SendMessage(Server, Datatype.UpdatePlayerList, PlayerList); break; } case Datatype.PlaySound: { string soundPath = (string)ServerUtilities.ReceiveMessage(inc, messageType); ServerUtilities.SendMessage(Server, Datatype.PlaySound, soundPath); break; } case Datatype.GameEvent: { string serializedEvent = (string)ServerUtilities.ReceiveMessage(inc, messageType); ServerUtilities.SendMessage(Server, Datatype.GameEvent, serializedEvent); 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) { Console.WriteLine("Client was disconnected."); } break; } default: { Console.WriteLine("Message of type: " + inc.MessageType + " received"); 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); } }