/// <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(); }