/// <summary>
        ///     Sends a create item spawn event to the supplied net connection.
        /// </summary>
        /// <param name="netConnection">The net connection that the event is going to.</param>
        /// <param name="itemSpawn">The item spawn that was created.</param>
        /// <remarks>
        ///     Events have the form:
        ///     Byte 1: Data Type - Event
        ///     Byte 2: ServerEventCode
        ///     Byte 3-n: Data
        /// </remarks>
        private void SendCreateItemSpawnEvent(NetConnection netConnection, ItemSpawn itemSpawn)
        {
            CreateItemSpawnEvent createitemspawnevent = new CreateItemSpawnEvent(itemSpawn);
            NetOutgoingMessage msg = LidgrenServer.CreateMessage();

            msg.Write((byte)DataTypes.Event);
            msg.Write((byte)ServerEventCodes.CreateItemSpawn);
            msg.Write(Serialize(createitemspawnevent));

            LidgrenServer.SendMessage(msg, netConnection, NetDeliveryMethod.ReliableUnordered);
        }
        /// <summary>
        ///     Sends a drop item broadcast to the master server at netConnection (userd to be setnt to many master server connections).
        /// </summary>
        /// <param name="netConnection">The master server connection.</param>
        /// <param name="receivinguserids">The ids that are recieving this broadcast on the master server.</param>
        /// <param name="newitemspawn">The item spawn that was created by the item drop.</param>
        private void SendDropItemBroadcast(NetConnection netConnection, List<Guid> receivinguserids, ItemSpawn newitemspawn)
        {
            DropItemBroadcast dropitembroadcast = new DropItemBroadcast(receivinguserids, newitemspawn);

            Console.WriteLine("Sending drop item broadcast");
            NetOutgoingMessage broadcastmessage = LidgrenServer.CreateMessage();
            broadcastmessage.Write((byte)RegionMessages.DropItemBroadcast);
            broadcastmessage.Write(Serialize(dropitembroadcast));
            LidgrenServer.SendMessage(broadcastmessage, netConnection, NetDeliveryMethod.ReliableUnordered);
        }
        /// <summary>
        ///     The behemoth process function. This handles all data (Lidgren internal messages or Data from Master servers).
        /// </summary>
        public void Process()
        {
            NetIncomingMessage msg;

            //See if we have messages waiting in the queue
            while ((msg = LidgrenServer.ReadMessage()) != null)
            {
                switch (msg.MessageType)
                {
                    //It's a debug message. For now, just print to console.
                    case NetIncomingMessageType.DebugMessage:
                        Console.WriteLine("Debug: " + msg.ReadString());
                        break;
                    //Same for Warning
                    case NetIncomingMessageType.WarningMessage:
                        Console.WriteLine("Warning: " + msg.ReadString());
                        break;
                    //This is Data that we are recieving from a master server
                    case NetIncomingMessageType.Data:
                        //See what kind of message it is
                        RegionMessages messagetype = (RegionMessages)msg.ReadByte();
                        //It's an add character to the region message
                        if (messagetype == RegionMessages.AddCharacter)
                        {
                            //Deserialize it (it should be the rest of the byte stream, so it's safe to use msg.LengthBytes - msg.PositionInBytes
                            AddCharacterMessage message = Serializer.Deserialize<AddCharacterMessage>(new MemoryStream(msg.ReadBytes(msg.LengthBytes - msg.PositionInBytes)));

                            Console.WriteLine("Add character: " + message.AddingCharacter.Name);
                            Vector3 location;
                            Console.WriteLine(message.UseExitOrLocation);
                            if (message.UseExitOrLocation == ExitOrLocation.Exit)
                            {
                                location = TeleportExits.Find(delegate(TeleportExit e) { return e.TeleportId == message.TeleportExitId; }).Location;
                                Console.WriteLine("Exit " + message.TeleportExitId + ": " + location.X + " " + location.Y + " " + location.Z);
                            }
                            else
                            {
                                location = message.Location;
                                Console.WriteLine("Location: " + location.X + " " + location.Y + " " + location.Z);
                            }

                            SendAddCharacterResponseMessage(msg.SenderConnection, this.RegionId, location, this.Characters, this.ItemSpawns, message.UserId);

                            message.AddingCharacter.Position = location;

                            //Then we send the broadcast out to all of the clients connected to this region
                            //to tell them that someone entered this region. So we will collect what
                            //master servers we need to communicate with, and give them a list of clients to send
                            //this broadcast to.

                            //This ties master server connections to enter region broadcasts
                            Dictionary<NetConnection, List<Guid>> broadcastrecipients = new Dictionary<NetConnection,List<Guid>>();

                            HashSet<NetConnection> connections = new HashSet<NetConnection>(UserIdToMasterServer.Values);
                            //Get all the master servers that we should update and give them a new enter region broadcast
                            foreach (NetConnection conn in connections)
                            {
                                broadcastrecipients.Add(conn, new List<Guid>());
                            }

                            //Then go through all of the users in this region, and add their Id to the broadcast
                            //so they will recieve it from the master server.
                            foreach (KeyValuePair<Guid, NetConnection> pair in UserIdToMasterServer)
                            {
                                if(message.UserId != pair.Key)
                                    broadcastrecipients[pair.Value].Add(pair.Key); ;
                            }

                            foreach (KeyValuePair<NetConnection, List<Guid>> pair in broadcastrecipients)
                            {
                                SendAddCharacterBroadcast(pair.Key, message.AddingCharacter, message.UserId, pair.Value);
                            }

                            //Here is where we actually add the character to the region
                            Characters.Add(message.UserId, message.AddingCharacter);

                            //And we add the user id and the master server it is associated with currently.
                            UserIdToMasterServer.Add(message.UserId, msg.SenderConnection);
                        }
                        //We could remove a character
                        else if (messagetype == RegionMessages.RemoveCharacter)
                        {
                            //Deserialize the message
                            RemoveCharacterMessage message = Serializer.Deserialize<RemoveCharacterMessage>(new MemoryStream(msg.ReadBytes(msg.LengthBytes - msg.PositionInBytes)));

                            Console.WriteLine("Removing character: " + Characters[message.UserId].Name);
                            //Go ahead and remove the character's information from this region server
                            //so we don't send messages to it about it leaving. That would be redundant.
                            Characters.Remove(message.UserId);
                            UserIdToMasterServer.Remove(message.UserId);

                            //This ties master server connections to enter region broadcasts
                            Dictionary<NetConnection, List<Guid>> broadcastrecipients = new Dictionary<NetConnection, List<Guid>>();

                            HashSet<NetConnection> connections = new HashSet<NetConnection>(UserIdToMasterServer.Values);
                            //Get all the master servers that we should update and give them a new enter region broadcast
                            foreach (NetConnection conn in connections)
                            {
                                broadcastrecipients.Add(conn, new List<Guid>());
                            }

                            //Then go through all of the users in this region, and add their Id to the broadcast
                            //so they will recieve it from the master server.
                            foreach (KeyValuePair<Guid, NetConnection> pair in UserIdToMasterServer)
                            {
                                if(message.UserId != pair.Key)
                                    broadcastrecipients[pair.Value].Add(pair.Key); ;
                            }

                            foreach (KeyValuePair<NetConnection, List<Guid>> pair in broadcastrecipients)
                            {
                                SendRemoveCharacterBroadcast(pair.Key, message.UserId, pair.Value);
                            }
                        }
                        //Or we got a character snapshot
                        else if (messagetype == RegionMessages.CharacterSnapshot)
                        {
                            //Deserialize that message
                            CharacterSnapshotMessage message = Serializer.Deserialize<CharacterSnapshotMessage>(new MemoryStream(msg.ReadBytes(msg.LengthBytes - msg.PositionInBytes)));

                            Console.WriteLine("Snapshot: " + Characters[message.Snapshot.UserId].Name);
                            //HERE WE VALIATE THE POSITION

                            //TODO: VALIDATE VALIDATE VALIDATE
                            Characters[message.Snapshot.UserId].Position = message.Snapshot.Position;

                            //HERE WE VALIDATE THE ROTATION

                            //TODO: VALIDATE VALIDATE VALIDATE
                            Characters[message.Snapshot.UserId].Rotation = message.Snapshot.Rotation;

                            //TODO: VALIDATE AND USE VELOCITY IN SOME WAY :D
                            Vector3 dummy = message.Snapshot.Velocity;

                            //This ties master server connections to enter region broadcasts
                            Dictionary<NetConnection, List<Guid>> broadcastrecipients = new Dictionary<NetConnection, List<Guid>>();

                            HashSet<NetConnection> connections = new HashSet<NetConnection>(UserIdToMasterServer.Values);
                            //Get all the master servers that we should update and give them a new enter region broadcast
                            foreach (NetConnection conn in connections)
                            {
                                broadcastrecipients.Add(conn, new List<Guid>());
                            }

                            //Then go through all of the users in this region, and add their Id to the broadcast
                            //so they will recieve it from the master server.
                            foreach (KeyValuePair<Guid, NetConnection> pair in UserIdToMasterServer)
                            {
                                if(pair.Key != message.Snapshot.UserId)
                                    broadcastrecipients[pair.Value].Add(pair.Key);
                            }

                            foreach (KeyValuePair<NetConnection, List<Guid>> pair in broadcastrecipients)
                            {
                                if (pair.Value.Count > 0)
                                {
                                    Console.WriteLine("Calling send snapshot broadcast");
                                    SendSnapshotBroadcast(pair.Key, message.Snapshot, pair.Value);
                                }
                            }
                        }
                        else if (messagetype == RegionMessages.TeleportCharacter)
                        {
                            TeleportCharacterMessage message = Serializer.Deserialize<TeleportCharacterMessage>(new MemoryStream(msg.ReadBytes(msg.LengthBytes - msg.PositionInBytes)));

                            Console.WriteLine("Teleporting: " + Characters[message.UserId].Name);

                            ushort teleportexitid = TeleportEnters.Find(delegate(TeleportEnter enter) { return enter.TeleportId == message.TeleportEnterId; }).ConnectedTeleportExitId;
                            ushort regionid = TeleportEnters.Find(delegate(TeleportEnter enter) { return enter.TeleportId == message.TeleportEnterId; }).ConnectedTeleportRegionId;
                            SendTeleportResponseMessage(msg.SenderConnection, message.UserId, regionid, teleportexitid);

                            //Go ahead and remove the character's information from this region server
                            //so we don't send messages to it about it leaving. That would be redundant.
                            Characters.Remove(message.UserId);
                            UserIdToMasterServer.Remove(message.UserId);

                            //This ties master server connections to enter region broadcasts
                            Dictionary<NetConnection, List<Guid>> broadcastrecipients = new Dictionary<NetConnection, List<Guid>>();

                            HashSet<NetConnection> connections = new HashSet<NetConnection>(UserIdToMasterServer.Values);
                            //Get all the master servers that we should update and give them a new enter region broadcast
                            foreach (NetConnection conn in connections)
                            {
                                broadcastrecipients.Add(conn, new List<Guid>());
                            }

                            //Then go through all of the users in this region, and add their Id to the broadcast
                            //so they will recieve it from the master server.
                            foreach (KeyValuePair<Guid, NetConnection> pair in UserIdToMasterServer)
                            {
                                if(message.UserId != pair.Key)
                                    broadcastrecipients[pair.Value].Add(pair.Key); ;
                            }

                            foreach (KeyValuePair<NetConnection, List<Guid>> pair in broadcastrecipients)
                            {
                                SendRemoveCharacterBroadcast(pair.Key, message.UserId, pair.Value);
                            }
                        }
                        else if (messagetype == RegionMessages.DropItem)
                        {
                            DropItemMessage message = Serializer.Deserialize<DropItemMessage>(new MemoryStream(msg.ReadBytes(msg.LengthBytes - msg.PositionInBytes)));

                            if (Characters[message.UserId].Inventory.ContainsKey(message.ItemId))
                            {
                                ItemSpawn newitemspawn = new ItemSpawn() { ItemId = message.ItemId, Location = Characters[message.UserId].Position, RespawnTime = new TimeSpan(0, 0, 0), Id = ItemSpawnIdGenerator.GetNewId(), HasItem = true};
                                ItemSpawns.Add(newitemspawn);
                                Characters[message.UserId].Inventory.Remove(message.ItemId);
                                SendDropItemResponseMessage(msg.SenderConnection, message.UserId, message.ItemId);
                                //This ties master server connections to enter region broadcasts
                                Dictionary<NetConnection, List<Guid>> broadcastrecipients = new Dictionary<NetConnection, List<Guid>>();

                                HashSet<NetConnection> connections = new HashSet<NetConnection>(UserIdToMasterServer.Values);
                                //Get all the master servers that we should update and give them a new enter region broadcast
                                foreach (NetConnection conn in connections)
                                {
                                    broadcastrecipients.Add(conn, new List<Guid>());
                                }

                                //Then go through all of the users in this region, and add their Id to the broadcast
                                //so they will recieve it from the master server.
                                foreach (KeyValuePair<Guid, NetConnection> pair in UserIdToMasterServer)
                                {
                                    broadcastrecipients[pair.Value].Add(pair.Key); ;
                                }

                                foreach (KeyValuePair<NetConnection, List<Guid>> pair in broadcastrecipients)
                                {
                                    SendDropItemBroadcast(pair.Key, pair.Value, newitemspawn);
                                }
                            }
                            else
                            {
                                //Log this, because they are trying to drop items they don't own
                                SendDropItemResponseMessage(msg.SenderConnection, message.UserId, null);
                            }
                        }
                        else if (messagetype == RegionMessages.PickupItem)
                        {
                            PickupItemMessage message = Serializer.Deserialize<PickupItemMessage>(new MemoryStream(msg.ReadBytes(msg.LengthBytes - msg.PositionInBytes)));
                            //Make sure the character is actually somewhere around the item spawn, and that it exists.

                            ItemSpawn spawn = ItemSpawns.Find(delegate(ItemSpawn s) { return s.Id == message.ItemSpawnId; });
                            if (spawn != null && spawn.HasItem && Vector3.Distance(Characters[message.UserId].Position, spawn.Location) < 5.0)
                            {
                                SendPickupItemResponse(msg.SenderConnection, message.UserId, spawn.ItemId);

                                //This ties master server connections to enter region broadcasts
                                Dictionary<NetConnection, List<Guid>> broadcastrecipients = new Dictionary<NetConnection, List<Guid>>();

                                HashSet<NetConnection> connections = new HashSet<NetConnection>(UserIdToMasterServer.Values);
                                //Get all the master servers that we should update and give them a new enter region broadcast
                                foreach (NetConnection conn in connections)
                                {
                                    broadcastrecipients.Add(conn, new List<Guid>());
                                }

                                //Then go through all of the users in this region, and add their Id to the broadcast
                                //so they will recieve it from the master server.
                                foreach (KeyValuePair<Guid, NetConnection> pair in UserIdToMasterServer)
                                {
                                    broadcastrecipients[pair.Value].Add(pair.Key); ;
                                }

                                foreach (KeyValuePair<NetConnection, List<Guid>> pair in broadcastrecipients)
                                {
                                    SendPickupItemBroadcast(pair.Key, pair.Value, spawn.Id);
                                }

                                if (spawn.RespawnTime == new TimeSpan(0,0,0))
                                {
                                    ItemSpawns.Remove(spawn);
                                }
                                else
                                {
                                    spawn.HasItem = false;
                                    ItemSpawnsWaitingForSpawn.Add(spawn, DateTime.Now);
                                }
                            }
                        }
                        break;
                }
            }
        }
 /// <summary>
 ///     Constructor specifying the reciving user ids and the new item spawn.
 /// </summary>
 /// <param name="receivinguserids">The recipients of this broadcst.</param>
 /// <param name="newitemspawn">The item spawn that was created.</param>
 public DropItemBroadcast(List<Guid> receivinguserids, ItemSpawn newitemspawn)
 {
     this.ReceivingUserIds = receivinguserids;
     this.NewItemSpawn = newitemspawn;
 }
 /// <summary>
 ///     Constructor that lets you specify the new ItemSpawn.
 /// </summary>
 /// <param name="itemspawn">The new item spawn that was created.</param>
 public CreateItemSpawnEvent(ItemSpawn itemspawn)
 {
     NewItemSpawn = itemspawn;
 }
 /// <summary>
 ///     Default Constructor.
 /// </summary>
 public CreateItemSpawnEvent()
 {
     NewItemSpawn = new ItemSpawn();
 }