private void AgentAnimationHandler(Packet packet, LLAgent agent) { AgentAnimationPacket animPacket = (AgentAnimationPacket)packet; bool changed = false; for (int i = 0; i < animPacket.AnimationList.Length; i++) { AgentAnimationPacket.AnimationListBlock block = animPacket.AnimationList[i]; if (block.StartAnim) { if (agent.Animations.Add(block.AnimID, ref agent.CurrentAnimSequenceNum)) { changed = true; } } else { if (agent.Animations.Remove(block.AnimID)) { changed = true; } } } if (changed) { m_scene.SendPresenceAnimations(this, agent); } }
public string llAvatarOnSitTarget(IScriptInstance script) { if (script.Host is LLPrimitive) { LLPrimitive prim = (LLPrimitive)script.Host; if (prim.SitPosition != Vector3.Zero) { ILinkable[] children = ((ILinkable)script.Host).GetChildren(); for (int i = 0, len = children.Length; i < len; i++) { if (children[i] is LLAgent) { LLAgent childAgent = (LLAgent)children[i]; if (childAgent.RelativePosition == LLUtil.GetSitTarget(prim.SitPosition, childAgent.Scale)) { return(childAgent.ID.ToString()); } } } } } return(UUID.Zero.ToString()); }
private void AvatarPropertiesUpdateHandler(Packet packet, LLAgent agent) { AvatarPropertiesUpdatePacket update = (AvatarPropertiesUpdatePacket)packet; User user; if (m_userClient != null && m_userClient.TryGetUser(agent.ID, out user)) { OSDMap updates = new OSDMap { { "About", OSD.FromString(Utils.BytesToString(update.PropertiesData.AboutText)) }, { "AllowPublish", OSD.FromBoolean(update.PropertiesData.AllowPublish) }, { "FLAbout", OSD.FromString(Utils.BytesToString(update.PropertiesData.FLAboutText)) }, { "FLImage", OSD.FromUUID(update.PropertiesData.FLImageID) }, { "Image", OSD.FromUUID(update.PropertiesData.ImageID) }, { "AllowMaturePublish", OSD.FromBoolean(update.PropertiesData.MaturePublish) }, { "URL", OSD.FromString(Utils.BytesToString(update.PropertiesData.ProfileURL)) } }; m_userClient.UpdateUserFields(agent.ID, updates); SendAvatarProperties(agent, agent.ID, user); } else { m_log.Warn("Could not find user " + agent.ID + ", not updating profile for " + agent.Name); SendAvatarProperties(agent, agent.ID, null); } }
private void AvatarInterestsUpdateHandler(Packet packet, LLAgent agent) { AvatarInterestsUpdatePacket update = (AvatarInterestsUpdatePacket)packet; User user; if (m_userClient != null && m_userClient.TryGetUser(agent.ID, out user)) { OSDMap map = new OSDMap { { "WantMask", OSD.FromInteger((int)update.PropertiesData.WantToMask) }, { "WantText", OSD.FromString(Utils.BytesToString(update.PropertiesData.WantToText)) }, { "SkillsMask", OSD.FromInteger((int)update.PropertiesData.SkillsMask) }, { "SkillsText", OSD.FromString(Utils.BytesToString(update.PropertiesData.SkillsText)) }, { "Languages", OSD.FromString(Utils.BytesToString(update.PropertiesData.LanguagesText)) } }; m_userClient.UpdateUserFields(agent.ID, new OSDMap { { "LLInterests", map } }); } else { m_log.Warn("Could not find user " + agent.ID + ", not updating profile interests for " + agent.Name); SendAvatarInterests(agent, agent.ID, null); } }
private void ConfirmXferPacketHandler(Packet packet, LLAgent agent) { ConfirmXferPacketPacket confirm = (ConfirmXferPacketPacket)packet; XferDownload download; if (currentDownloads.TryGetValue(confirm.XferID.ID, out download)) { // Send the next packet SendXferPacketPacket xfer = new SendXferPacketPacket(); xfer.XferID.ID = confirm.XferID.ID; int bytesRemaining = (int)(download.AssetData.Length - (download.PacketNum * 1000)); if (bytesRemaining > 1000) { xfer.DataPacket.Data = new byte[1000]; Buffer.BlockCopy(download.AssetData, (int)download.PacketNum * 1000, xfer.DataPacket.Data, 0, 1000); xfer.XferID.Packet = download.PacketNum++; } else { // Last packet xfer.DataPacket.Data = new byte[bytesRemaining]; Buffer.BlockCopy(download.AssetData, (int)download.PacketNum * 1000, xfer.DataPacket.Data, 0, bytesRemaining); xfer.XferID.Packet = download.PacketNum | LAST_PACKET_MARKER; lock (currentDownloads) currentDownloads.Remove(confirm.XferID.ID); m_log.Debug("Completing xfer download for: " + download.Filename); } m_udp.SendPacket(agent, xfer, ThrottleCategory.Asset, false); } }
private void SendAvatarInterests(LLAgent agent, UUID avatarID, User user) { AvatarInterestsReplyPacket reply = new AvatarInterestsReplyPacket(); reply.AgentData.AgentID = agent.ID; reply.AgentData.AvatarID = avatarID; OSDMap interests; if (user != null && (interests = user.GetField("LLInterests") as OSDMap) != null) { reply.PropertiesData.LanguagesText = Utils.StringToBytes(interests["Languages"].AsString()); reply.PropertiesData.SkillsMask = interests["SkillsMask"].AsUInteger(); reply.PropertiesData.SkillsText = Utils.StringToBytes(interests["SkillsText"].AsString()); reply.PropertiesData.WantToMask = interests["WantMask"].AsUInteger(); reply.PropertiesData.WantToText = Utils.StringToBytes(interests["WantText"].AsString()); } else { reply.PropertiesData.LanguagesText = Utils.EmptyBytes; reply.PropertiesData.SkillsText = Utils.EmptyBytes; reply.PropertiesData.WantToText = Utils.EmptyBytes; } m_udp.SendPacket(agent, reply, ThrottleCategory.Task, false); }
private void SendTerrainPacket(QueuedInterestListEvent[] eventDatas, IScenePresence presence) { const int PATCHES_PER_PACKET = 3; if (!(presence is LLAgent) || presence.InterestList == null) { return; } LLAgent agent = (LLAgent)presence; List <int> patches = new List <int>(PATCHES_PER_PACKET); for (int i = 0; i < eventDatas.Length; i++) { int[] state = (int[])eventDatas[i].Event.State; int x = state[0]; int y = state[1]; patches.Add(y * 16 + x); if (patches.Count == PATCHES_PER_PACKET || i == eventDatas.Length - 1) { LayerDataPacket packet = TerrainCompressor.CreateLandPacket(m_terrain.GetHeightmap(), patches.ToArray()); m_udp.SendPacket(agent, packet, ThrottleCategory.Land, false); patches = new List <int>(PATCHES_PER_PACKET); } } }
private void QueueEmptyHandler(LLAgent agent, ThrottleCategoryFlags categories) { if ((categories & ThrottleCategoryFlags.Texture) == ThrottleCategoryFlags.Texture) { ProcessImageQueue(TEXTURE_PACKETS_PER_ROUND); } }
private void SendPreloadSoundsPacket(QueuedInterestListEvent[] eventDatas, IScenePresence presence) { if (!(presence is LLAgent) || presence.InterestList == null) { return; } LLAgent agent = (LLAgent)presence; PreloadSoundPacket preload = new PreloadSoundPacket(); preload.DataBlock = new PreloadSoundPacket.DataBlockBlock[eventDatas.Length]; for (int i = 0; i < eventDatas.Length; i++) { object[] state = (object[])eventDatas[i].Event.State; ISceneEntity source = (ISceneEntity)state[0]; UUID soundID = (UUID)state[1]; preload.DataBlock[i] = new PreloadSoundPacket.DataBlockBlock { ObjectID = source.ID, OwnerID = source.OwnerID, SoundID = soundID }; } m_udp.SendPacket(agent, preload, ThrottleCategory.Task, true); }
private void SetTextureDetail(LLAgent agent, Estate estate, string[] parameters) { for (int i = 0; i < parameters.Length; i++) { byte corner; UUID textureID; string[] args = parameters[i].Split(' '); if (args.Length == 2 && Byte.TryParse(args[0], out corner) && UUID.TryParse(args[1], out textureID)) { switch (corner) { case 0: estate.TerrainDetail0 = textureID; break; case 1: estate.TerrainDetail1 = textureID; break; case 2: estate.TerrainDetail2 = textureID; break; case 3: estate.TerrainDetail3 = textureID; break; } } } BroadcastRegionInfo(); }
private void GodlikeMessageHandler(Packet packet, LLAgent agent) { GodlikeMessagePacket message = (GodlikeMessagePacket)packet; UUID invoiceID = message.MethodData.Invoice; string method = Utils.BytesToString(message.MethodData.Method); string[] parameters = new string[message.ParamList.Length]; for (int i = 0; i < message.ParamList.Length; i++) { parameters[i] = Utils.BytesToString(message.ParamList[i].Parameter); } if (m_permissions != null) { if (!m_permissions.IsGridAdmin(agent)) { m_log.Warn("Ignoring GodlikeMessage " + method + " from non-admin " + agent.Name); return; } } // DEBUG StringBuilder output = new StringBuilder(method + " (" + invoiceID + ")"); for (int i = 0; i < parameters.Length; i++) { output.AppendLine(" " + parameters[i]); } m_log.Warn("Received an unhandled GodlikeMessage from " + agent.Name + ": " + output.ToString()); }
private void AgentCachedTextureHandler(Packet packet, LLAgent agent) { AgentCachedTexturePacket cached = (AgentCachedTexturePacket)packet; AgentCachedTextureResponsePacket response = new AgentCachedTextureResponsePacket(); response.Header.Zerocoded = true; response.AgentData.AgentID = agent.ID; response.AgentData.SerialNum = cached.AgentData.SerialNum; response.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cached.WearableData.Length]; // TODO: Respond back with actual cache entries if we have them for (int i = 0; i < cached.WearableData.Length; i++) { response.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); response.WearableData[i].TextureIndex = cached.WearableData[i].TextureIndex; response.WearableData[i].TextureID = UUID.Zero; response.WearableData[i].HostName = Utils.EmptyBytes; } m_log.DebugFormat("Sending a cached texture response with {0}/{1} cache hits, SerialNum={2}", 0, cached.WearableData.Length, cached.AgentData.SerialNum); m_udp.SendPacket(agent, response, ThrottleCategory.Task, false); }
private void SendTypingPackets(QueuedInterestListEvent[] eventDatas, IScenePresence presence) { if (!(presence is LLAgent) || presence.InterestList == null) { return; } LLAgent agent = (LLAgent)presence; // We can't combine chat blocks together, so send a packet for each typing event // that is pulled off the event queue for (int i = 0; i < eventDatas.Length; i++) { TypingData data = (TypingData)eventDatas[i].Event.State; ChatAudibleLevel audible = GetAudibleLevel(data.Source.ScenePosition, presence.ScenePosition, NORMAL_DIST); ChatFromSimulatorPacket packet = new ChatFromSimulatorPacket(); packet.ChatData.Audible = (byte)audible; packet.ChatData.ChatType = (byte)(data.StartTyping ? ChatType.StartTyping : ChatType.StopTyping); packet.ChatData.FromName = Utils.StringToBytes(data.Source.Name); packet.ChatData.Message = Utils.EmptyBytes; packet.ChatData.OwnerID = data.Source.OwnerID; packet.ChatData.Position = data.Source.ScenePosition; packet.ChatData.SourceID = data.Source.ID; packet.ChatData.SourceType = (byte)ChatSourceType.Agent; m_udp.SendPacket(agent, packet, ThrottleCategory.Task, false); } }
private void UseCircuitCodeHandler(Packet packet, LLAgent agent) { // Add the agent to the scene m_scene.EntityAddOrUpdate(this, agent, UpdateFlags.FullUpdate, 0); Estates.SendRegionHandshake(agent, m_udp, m_scene, m_regionInfo, m_permissions); }
private void AgentHeightWidthHandler(Packet packet, LLAgent agent) { AgentHeightWidthPacket hw = (AgentHeightWidthPacket)packet; agent.CameraHeight = hw.HeightWidthBlock.Height; agent.CameraWidth = hw.HeightWidthBlock.Width; }
private void RequestXferHandler(Packet packet, LLAgent agent) { RequestXferPacket request = (RequestXferPacket)packet; string filename = Utils.BytesToString(request.XferID.Filename); UUID taskInventoryID; if (filename.StartsWith("inventory_") && filename.EndsWith(".tmp") && UUID.TryParse(filename.Substring(10, 36), out taskInventoryID)) { // This is a request for a task inventory listing, which we generate on demand ISceneEntity entity; if (m_scene.TryGetEntity(taskInventoryID, out entity) && entity is LLPrimitive) { LLPrimitive prim = (LLPrimitive)entity; byte[] assetData = Encoding.UTF8.GetBytes(prim.Inventory.GetTaskInventoryAsset()); SendXferPacketPacket xfer = new SendXferPacketPacket(); xfer.XferID.ID = request.XferID.ID; if (assetData.Length < 1000) { xfer.XferID.Packet = 0 | LAST_PACKET_MARKER; xfer.DataPacket.Data = new byte[assetData.Length + 4]; Utils.IntToBytes(assetData.Length, xfer.DataPacket.Data, 0); Buffer.BlockCopy(assetData, 0, xfer.DataPacket.Data, 4, assetData.Length); m_udp.SendPacket(agent, xfer, ThrottleCategory.Asset, false); m_log.Debug("Completed single packet xfer download of " + filename); } else { xfer.XferID.Packet = 0; xfer.DataPacket.Data = new byte[1000 + 4]; Utils.IntToBytes(assetData.Length, xfer.DataPacket.Data, 0); Buffer.BlockCopy(assetData, 0, xfer.DataPacket.Data, 4, 1000); // We don't need the entire XferDownload class, just the asset data and the current packet number XferDownload download = new XferDownload(); download.AssetData = assetData; download.PacketNum = 1; download.Filename = filename; lock (currentDownloads) currentDownloads[request.XferID.ID] = download; m_udp.SendPacket(agent, xfer, ThrottleCategory.Asset, false); } } else { m_log.Warn("Could not find primitive " + taskInventoryID); } } else { m_log.Warn("Got a RequestXfer for an unknown file: " + filename); } }
private void MoveTaskInventoryHandler(Packet packet, LLAgent agent) { MoveTaskInventoryPacket move = (MoveTaskInventoryPacket)packet; if (m_inventory != null) { LLInventoryTaskItem item; ISceneEntity sourceObj; if (m_scene.TryGetEntity(move.InventoryData.LocalID, out sourceObj) && sourceObj is LLPrimitive) { LLPrimitive sourcePrim = (LLPrimitive)sourceObj; if (sourcePrim.Inventory.TryGetItem(move.InventoryData.ItemID, out item)) { InventoryBase obj; if (m_inventory.TryGetInventory(agent.ID, move.AgentData.FolderID, out obj) && obj is InventoryFolder) { LLInventoryItem invItem = new LLInventoryItem { AssetID = item.AssetID, ContentType = item.ContentType, CreationDate = item.CreationDate, CreatorID = item.CreatorID, Description = item.Description, ExtraData = item.ExtraData, ID = UUID.Random(), Name = item.Name, OwnerID = agent.ID, ParentID = move.AgentData.FolderID }; if (m_inventory.TryCreateItem(agent.ID, invItem)) { RemoveTaskInventory(agent, sourcePrim, item.ID); SendItemCreatedPacket(agent, invItem, UUID.Zero, 0); m_log.Debug(agent.Name + " moved task inventory item " + item.Name + " to agent inventory folder " + invItem.ParentID); } else { m_log.Warn(agent.Name + "attempted to move item " + move.InventoryData.ItemID + " to agent inventory folder " + move.AgentData.FolderID + " but item creation failed"); } } else { m_log.Warn(agent.Name + "attempted to move item " + move.InventoryData.ItemID + " to unknown agent inventory folder " + move.AgentData.FolderID); } } } } else { m_log.Warn(agent.Name + "attempted to move item " + move.InventoryData.ItemID + " to agent inventory, but we have no IInventoryClient"); } }
private void RequestImageHandler(Packet packet, LLAgent agent) { RequestImagePacket request = (RequestImagePacket)packet; for (int i = 0; i < request.RequestImage.Length; i++) { RequestImagePacket.RequestImageBlock block = request.RequestImage[i]; EnqueueRequest(agent, block.Image, block.DiscardLevel, block.DownloadPriority, block.Packet, packet.Header.Sequence); } }
private void ParcelObjectOwnersRequestHandler(Packet packet, LLAgent agent) { ParcelObjectOwnersRequestPacket request = (ParcelObjectOwnersRequestPacket)packet; SceneParcel parcel; if (m_parcels.TryGetParcel(request.ParcelData.LocalID, out parcel)) { ParcelObjectOwnersReplyPacket reply = new ParcelObjectOwnersReplyPacket(); Dictionary <UUID, OwnershipInfo> owners = new Dictionary <UUID, OwnershipInfo>(); lock (parcel.ParcelEntities) { foreach (ISceneEntity entity in parcel.ParcelEntities.Values) { // Skip child entities if (entity is ILinkable && ((ILinkable)entity).Parent != null) { continue; } OwnershipInfo count; if (!owners.TryGetValue(entity.OwnerID, out count)) { count = new OwnershipInfo(); count.IsGroupOwned = false; // FIXME: Need to track group ownership count.OnlineStatus = false; // FIXME: m_permissions.IsOnline(agent.ID, entity.OwnerID); owners.Add(entity.OwnerID, count); } ++count.Count; } } reply.Data = new ParcelObjectOwnersReplyPacket.DataBlock[owners.Count]; int i = 0; foreach (KeyValuePair <UUID, OwnershipInfo> kvp in owners) { reply.Data[i++] = new ParcelObjectOwnersReplyPacket.DataBlock { Count = kvp.Value.Count, OwnerID = kvp.Key, IsGroupOwned = kvp.Value.IsGroupOwned, OnlineStatus = kvp.Value.OnlineStatus }; } m_udp.SendPacket(agent, reply, ThrottleCategory.Task, true); } else { m_log.Warn(agent.Name + " requested object owners for unknown parcel " + request.ParcelData.LocalID); } }
private void RegionHandshakeReplyHandler(Packet packet, LLAgent agent) { //FIXME: is this really where this belongs? EconomyDataPacket economy = new EconomyDataPacket(); economy.Info.PriceUpload = 0; //TODO: populate economy.* m_udp.SendPacket(agent, economy, ThrottleCategory.Task, false); }
private void ChatFromViewerHandler(Packet packet, LLAgent agent) { ChatFromViewerPacket chat = (ChatFromViewerPacket)packet; ChatType chatType = (ChatType)chat.ChatData.Type; string message = Utils.BytesToString(chat.ChatData.Message); int channel = chat.ChatData.Channel; // Don't allow clients to chat on negative channels if (channel < 0) { channel = 0; } // Start/stop typing messages are specific to the LLUDP protocol, so we create events // directly that will be processed by this same class. Chat messages are a generic // event that can be supported by multiple protocols, so we call IScene.EntityChat and // hook IScene.OnChat to do the actual processing // Event IDs for start/stop typing are generated with UUID.Combine(agent.ID, TYPING_EVENT_ID) // to create an ID that is unique to each agent in the context of typing. Newer typing // events will overwrite older ones switch (chatType) { case ChatType.StartTyping: m_scene.CreateInterestListEvent(new InterestListEvent(UUID.Combine(agent.ID, TYPING_EVENT_ID), VIEWER_TYPING, agent.ScenePosition, new Vector3(NORMAL_DIST), new TypingData { Source = agent, StartTyping = true })); break; case ChatType.StopTyping: m_scene.CreateInterestListEvent(new InterestListEvent(UUID.Combine(agent.ID, TYPING_EVENT_ID), VIEWER_TYPING, agent.ScenePosition, new Vector3(NORMAL_DIST), new TypingData { Source = agent, StartTyping = false })); break; case ChatType.Whisper: m_scene.EntityChat(this, agent, WHISPER_DIST, message, channel, EntityChatType.Normal); break; case ChatType.Shout: m_scene.EntityChat(this, agent, SHOUT_DIST, message, channel, EntityChatType.Normal); break; case ChatType.Normal: default: m_scene.EntityChat(this, agent, NORMAL_DIST, message, channel, EntityChatType.Normal); break; } }
private void RequestRegionInfoHandler(Packet packet, LLAgent agent) { RegionInfoPacket info = new RegionInfoPacket(); info.AgentData.AgentID = agent.ID; info.RegionInfo.SimName = Utils.StringToBytes(m_scene.Name); info.RegionInfo.ParentEstateID = 1; // Hardcoded to what the viewer considers "mainland" info.RegionInfo.PricePerMeter = 1; // Dummy value if (m_regionInfo != null) { // Region settings info.RegionInfo.MaxAgents = (byte)Math.Min(255, m_regionInfo.MaxAgents); info.RegionInfo.WaterHeight = m_regionInfo.WaterHeight; info.RegionInfo2.HardMaxAgents = m_regionInfo.MaxAgents; info.RegionInfo2.HardMaxObjects = m_regionInfo.ObjectCapacity; info.RegionInfo2.MaxAgents32 = m_regionInfo.MaxAgents; info.RegionInfo2.ProductName = Utils.StringToBytes(PRODUCT_NAME); info.RegionInfo2.ProductSKU = Utils.EmptyBytes; info.RegionInfo.UseEstateSun = m_regionInfo.UseEstateSun; } else { info.RegionInfo2.ProductName = Utils.EmptyBytes; info.RegionInfo2.ProductSKU = Utils.EmptyBytes; } if (m_estate != null) { info.RegionInfo.RegionFlags = (uint)m_estate.EstateFlags; info.RegionInfo.BillableFactor = 0f; info.RegionInfo.EstateID = m_estate.ID; info.RegionInfo.ObjectBonusFactor = m_estate.ObjectBonusFactor; info.RegionInfo.RedirectGridX = 0; // TODO: What is this? info.RegionInfo.RedirectGridY = 0; // info.RegionInfo.SimAccess = (byte)m_estate.AccessFlags; info.RegionInfo.SunHour = m_estate.SunHour; info.RegionInfo.TerrainLowerLimit = m_estate.TerrainLowerLimit; info.RegionInfo.TerrainRaiseLimit = m_estate.TerrainRaiseLimit; } else { if (m_regionInfo != null) { info.RegionInfo.RegionFlags = (uint)m_regionInfo.RegionFlags; info.RegionInfo.SimAccess = (byte)m_regionInfo.SimAccess; } info.RegionInfo.TerrainRaiseLimit = 255f; } m_udp.SendPacket(agent, info, ThrottleCategory.Task, false); }
private void SignalTaskInventoryChange(LLAgent agent, LLPrimitive prim) { // Send an ObjectPropertiesReply to inform the client that inventory has changed ObjectPropertiesPacket props = new ObjectPropertiesPacket(); props.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; props.ObjectData[0] = LLUtil.BuildEntityPropertiesBlock(prim); m_udp.SendPacket(agent, props, ThrottleCategory.Task, false); // Signal this prim for serialization m_scene.EntityAddOrUpdate(this, prim, UpdateFlags.Serialize, 0); }
private void ParcelAccessListUpdateHandler(Packet packet, LLAgent agent) { ParcelAccessListUpdatePacket update = (ParcelAccessListUpdatePacket)packet; ParcelAccessFlags flags = (ParcelAccessFlags)update.Data.Flags; SceneParcel parcel; if (m_parcels.TryGetParcel(update.Data.LocalID, out parcel)) { // Initialize the white/black lists if they are not already if (parcel.AccessWhiteList == null) { parcel.AccessWhiteList = new List <ParcelAccessEntry>(); } if (parcel.AccessBlackList == null) { parcel.AccessBlackList = new List <ParcelAccessEntry>(); } List <ParcelAccessEntry> list = (flags == ParcelAccessFlags.Access) ? parcel.AccessWhiteList : parcel.AccessBlackList; lock (list) { for (int i = 0; i < update.List.Length; i++) { UUID newEntry = update.List[i].ID; bool found = false; foreach (ParcelAccessEntry pae in list) { if (pae.AgentID == newEntry) { found = true; break; } } if (!found) { list.Add(new ParcelAccessEntry { AgentID = newEntry, Created = DateTime.UtcNow }); } } } } else { m_log.Warn(agent.Name + " tried to update access list for unknown parcel" + update.Data.LocalID); } }
private void ParcelDivideHandler(Packet packet, LLAgent agent) { ParcelDividePacket divide = (ParcelDividePacket)packet; int startX = (int)Math.Round(divide.ParcelData.West) / 4; int startY = (int)Math.Round(divide.ParcelData.South) / 4; int endX = ((int)Math.Round(divide.ParcelData.East) / 4) - 1; int endY = ((int)Math.Round(divide.ParcelData.North) / 4) - 1; if (startX < 0 || startY < 0 || endX < startX || endY < startY || endX > 63 || endY > 63 || startX > endX || startY > endY) { m_log.Warn(agent.Name + String.Format(" sent invalid ParcelDivide: West {0} South {1} East {2} North {3}", divide.ParcelData.West, divide.ParcelData.South, divide.ParcelData.East, divide.ParcelData.North)); return; } // Make sure only a single parcel was selected int startParcelID = m_parcels.GetParcelID(startX, startY); for (int y = startY; y <= endY; y++) { for (int x = startX; x <= endX; x++) { int parcelID = m_parcels.GetParcelID(x, y); if (parcelID != startParcelID) { m_scene.PresenceAlert(this, agent, "Only one parcel can be subdivided at a time"); return; } } } SceneParcel parcel; if (!m_parcels.TryGetParcel(startParcelID, out parcel)) { m_log.Warn("Failed to look up parcel " + startParcelID + " during parcel divide"); return; } if (m_permissions != null && !m_permissions.CanEditParcel(agent, parcel)) { m_scene.PresenceAlert(this, agent, "You do not have permission to subdivide this parcel"); return; } m_parcels.SplitParcel(parcel, startX, endX, startY, endY); // Broadcast the new parcel overlay info m_scene.ForEachPresence(SendParcelOverlay); }
private void GodUpdateRegionInfoHandler(Packet packet, LLAgent agent) { GodUpdateRegionInfoPacket update = (GodUpdateRegionInfoPacket)packet; if (m_permissions != null) { if (!m_permissions.IsGridAdmin(agent)) { m_log.Warn("Ignoring GodUpdateRegionInfo from non-admin " + agent.Name); return; } } }
private void GetScriptRunningHandler(Packet packet, LLAgent agent) { GetScriptRunningPacket getRunning = (GetScriptRunningPacket)packet; ScriptRunningReplyMessage reply = new ScriptRunningReplyMessage(); reply.ItemID = getRunning.Script.ItemID;; reply.ObjectID = getRunning.Script.ObjectID; reply.Running = m_scriptEngine.IsScriptRunning(getRunning.Script.ItemID); reply.Mono = true; agent.EventQueue.QueueEvent("ScriptRunningReply", reply.Serialize()); }
private void PresenceAlertHandler(object sender, PresenceAlertArgs e) { if (e.Presence is LLAgent) { LLAgent agent = (LLAgent)e.Presence; AlertMessagePacket alert = new AlertMessagePacket(); alert.AlertData.Message = Utils.StringToBytes(e.Message); alert.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0]; m_udp.SendPacket(agent, alert, ThrottleCategory.Task, false); } }
private void LogoutRequestHandler(Packet packet, LLAgent agent) { LogoutReplyPacket reply = new LogoutReplyPacket(); reply.AgentData.AgentID = agent.ID; reply.AgentData.SessionID = agent.SessionID; reply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1]; reply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); reply.InventoryData[0].ItemID = UUID.Zero; m_udp.SendPacket(agent, reply, ThrottleCategory.Task, false); agent.Shutdown(); }
private bool CanDownloadInventory(LLAgent agent, AssetType type, UUID assetID) { if (m_permissions != null && (type == AssetType.LSLText || type == AssetType.LSLBytecode || type == AssetType.Notecard || type == AssetType.Object)) { PermissionMask perms = m_permissions.GetAssetPermissions(agent, assetID); if (!perms.HasPermission(PermissionMask.Modify)) { m_log.Warn("Denying inventory download from " + agent.Name + " for asset " + assetID + ", perms=" + perms); return(false); } } return(true); }
private void ChatFromViewerHandler(Packet packet, LLAgent agent) { ChatFromViewerPacket chat = (ChatFromViewerPacket)packet; ChatType chatType = (ChatType)chat.ChatData.Type; string message = Utils.BytesToString(chat.ChatData.Message); int channel = chat.ChatData.Channel; // Don't allow clients to chat on negative channels if (channel < 0) channel = 0; // Start/stop typing messages are specific to the LLUDP protocol, so we create events // directly that will be processed by this same class. Chat messages are a generic // event that can be supported by multiple protocols, so we call IScene.EntityChat and // hook IScene.OnChat to do the actual processing // Event IDs for start/stop typing are generated with UUID.Combine(agent.ID, TYPING_EVENT_ID) // to create an ID that is unique to each agent in the context of typing. Newer typing // events will overwrite older ones switch (chatType) { case ChatType.StartTyping: m_scene.CreateInterestListEvent(new InterestListEvent(UUID.Combine(agent.ID, TYPING_EVENT_ID), VIEWER_TYPING, agent.ScenePosition, new Vector3(NORMAL_DIST), new TypingData { Source = agent, StartTyping = true })); break; case ChatType.StopTyping: m_scene.CreateInterestListEvent(new InterestListEvent(UUID.Combine(agent.ID, TYPING_EVENT_ID), VIEWER_TYPING, agent.ScenePosition, new Vector3(NORMAL_DIST), new TypingData { Source = agent, StartTyping = false })); break; case ChatType.Whisper: m_scene.EntityChat(this, agent, WHISPER_DIST, message, channel, EntityChatType.Normal); break; case ChatType.Shout: m_scene.EntityChat(this, agent, SHOUT_DIST, message, channel, EntityChatType.Normal); break; case ChatType.Normal: default: m_scene.EntityChat(this, agent, NORMAL_DIST, message, channel, EntityChatType.Normal); break; } }
private void SendItemCreatedPacket(LLAgent agent, LLInventoryItem item, UUID transactionID, uint callbackID) { UpdateCreateInventoryItemPacket update = new UpdateCreateInventoryItemPacket(); update.AgentData.AgentID = agent.ID; update.AgentData.SimApproved = true; if (transactionID != UUID.Zero) update.AgentData.TransactionID = transactionID; else update.AgentData.TransactionID = UUID.Random(); Permissions perms = item.Permissions; UpdateCreateInventoryItemPacket.InventoryDataBlock invData = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); invData.AssetID = item.AssetID; invData.BaseMask = (uint)perms.BaseMask; invData.CallbackID = callbackID; invData.CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate); invData.CRC = item.CRC(); invData.CreatorID = item.CreatorID; invData.Description = Utils.StringToBytes(item.Description); invData.EveryoneMask = (uint)perms.EveryoneMask; invData.Flags = item.Flags; invData.FolderID = item.ParentID; invData.GroupID = item.GroupID; invData.GroupMask = (uint)perms.GroupMask; invData.GroupOwned = item.GroupOwned; invData.InvType = (sbyte)item.InventoryType; invData.ItemID = item.ID; invData.Name = Utils.StringToBytes(item.Name); invData.NextOwnerMask = (uint)perms.NextOwnerMask; invData.OwnerID = item.OwnerID; invData.OwnerMask = (uint)perms.OwnerMask; invData.SalePrice = item.SalePrice; invData.SaleType = (byte)item.SaleType; invData.Type = (sbyte)item.AssetType; update.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; update.InventoryData[0] = invData; m_log.DebugFormat("Created inventory item {0}. ItemID: {1}, AssetID: {2}, ParentID: {3}, TransactionID: {4}, CallbackID: {5}", item.Name, item.ID, item.AssetID, item.ParentID, transactionID, callbackID); m_udp.SendPacket(agent, update, ThrottleCategory.Task, false); }
private void AgentSetAppearanceHandler(Packet packet, LLAgent agent) { AgentSetAppearancePacket set = (AgentSetAppearancePacket)packet; UpdateFlags updateFlags = 0; LLUpdateFlags llUpdateFlags = 0; m_log.Debug("Updating avatar appearance with " + set.VisualParam.Length + " visual params, texture=" + (set.ObjectData.TextureEntry.Length > 1 ? "yes" : "no")); //TODO: Store this for cached bake responses for (int i = 0; i < set.WearableData.Length; i++) { //AvatarTextureIndex index = (AvatarTextureIndex)set.WearableData[i].TextureIndex; //UUID cacheID = set.WearableData[i].CacheID; //m_log.DebugFormat("WearableData: {0} is now {1}", index, cacheID); } // Create a TextureEntry if (set.ObjectData.TextureEntry.Length > 1) { agent.TextureEntry = new Primitive.TextureEntry(set.ObjectData.TextureEntry, 0, set.ObjectData.TextureEntry.Length); llUpdateFlags |= LLUpdateFlags.Textures; #region Bake Cache Check for (int i = 0; i < BAKE_INDICES.Length; i++) { int j = BAKE_INDICES[i]; Primitive.TextureEntryFace face = agent.TextureEntry.FaceTextures[j]; if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) { m_log.Debug("Baked texture " + (AvatarTextureIndex)j + " set to " + face.TextureID); } } #endregion Bake Cache Check } if (agent.Scale != set.AgentData.Size) { // This will be modified in UpdateHeight() if VisualParams are also sent agent.Scale = set.AgentData.Size; updateFlags |= UpdateFlags.Scale; } // Create a block of VisualParams if (set.VisualParam.Length > 1) { byte[] visualParams = new byte[set.VisualParam.Length]; for (int i = 0; i < set.VisualParam.Length; i++) visualParams[i] = set.VisualParam[i].ParamValue; agent.VisualParams = visualParams; agent.UpdateHeight(); // Create the event that generates an AvatarAppearance packet for this agent m_scene.CreateInterestListEvent(new InterestListEvent ( UUID.Combine(agent.ID, APPEARANCE_EVENT_ID), AVATAR_APPEARANCE, agent.ScenePosition, agent.Scale, agent )); } if (updateFlags != 0 || llUpdateFlags != 0) m_scene.EntityAddOrUpdate(this, agent, updateFlags, (uint)llUpdateFlags); }
private void SendXferPacketHandler(Packet packet, LLAgent agent) { SendXferPacketPacket xfer = (SendXferPacketPacket)packet; uint packetID = xfer.XferID.Packet & ~LAST_PACKET_MARKER; bool lastPacket = (xfer.XferID.Packet & LAST_PACKET_MARKER) != 0; Asset asset; if (currentUploads.TryGetValue(xfer.XferID.ID, out asset)) { if (packetID == 0) { uint size = Utils.BytesToUInt(xfer.DataPacket.Data); asset.Data = new byte[size]; Buffer.BlockCopy(xfer.DataPacket.Data, 4, asset.Data, 0, xfer.DataPacket.Data.Length - 4); // Confirm the first upload packet ConfirmXferPacketPacket confirm = new ConfirmXferPacketPacket(); confirm.XferID.ID = xfer.XferID.ID; confirm.XferID.Packet = xfer.XferID.Packet; m_udp.SendPacket(agent, confirm, ThrottleCategory.Asset, false); } else if (asset.Data != null) { AssetType type = (AssetType)LLUtil.ContentTypeToLLAssetType(asset.ContentType); Buffer.BlockCopy(xfer.DataPacket.Data, 0, asset.Data, (int)packetID * 1000, xfer.DataPacket.Data.Length); // Confirm this upload packet ConfirmXferPacketPacket confirm = new ConfirmXferPacketPacket(); confirm.XferID.ID = xfer.XferID.ID; confirm.XferID.Packet = xfer.XferID.Packet; m_udp.SendPacket(agent, confirm, ThrottleCategory.Asset, false); if (lastPacket) { // Asset upload finished lock (currentUploads) currentUploads.Remove(xfer.XferID.ID); if (type != AssetType.LSLBytecode) { // Store the uploaded asset m_log.DebugFormat("Storing uploaded asset {0} ({1})", asset.ID, asset.ContentType); if (!m_assets.StoreAsset(asset)) m_log.ErrorFormat("Failed to store uploaded asset {0} ({1})", asset.ID, asset.ContentType); } else { m_log.Debug("Ignoring LSL bytecode upload " + asset.ID); } AssetUploadCompletePacket complete = new AssetUploadCompletePacket(); complete.AssetBlock.Success = true; complete.AssetBlock.Type = (sbyte)type; complete.AssetBlock.UUID = asset.ID; m_udp.SendPacket(agent, complete, ThrottleCategory.Asset, false); } } else { m_log.Error("Received SendXferPacket #" + xfer.XferID.Packet + " when asset.AssetData is still null"); } } else { m_log.Debug("Received a SendXferPacket for an unknown upload"); } }
private void TransferNotFound(LLAgent agent, UUID transferID, UUID assetID, AssetType type) { m_log.Info("TransferNotFound for asset " + assetID + " with type " + type); TransferInfoPacket response = new TransferInfoPacket(); response.TransferInfo = new TransferInfoPacket.TransferInfoBlock(); response.TransferInfo.TransferID = transferID; // Set the response channel type response.TransferInfo.ChannelType = (int)ChannelType.Asset; // Params response.TransferInfo.Params = new byte[20]; assetID.ToBytes(response.TransferInfo.Params, 0); Utils.IntToBytes((int)type, response.TransferInfo.Params, 16); response.TransferInfo.Size = 0; response.TransferInfo.Status = (int)StatusCode.UnknownSource; response.TransferInfo.TargetType = (int)TargetType.Unknown; m_udp.SendPacket(agent, response, ThrottleCategory.Asset, false); }
private bool CanDownloadInventory(LLAgent agent, AssetType type, UUID assetID) { if (m_permissions != null && (type == AssetType.LSLText || type == AssetType.LSLBytecode || type == AssetType.Notecard || type == AssetType.Object)) { PermissionMask perms = m_permissions.GetAssetPermissions(agent, assetID); if (!perms.HasPermission(PermissionMask.Modify)) { m_log.Warn("Denying inventory download from " + agent.Name + " for asset " + assetID + ", perms=" + perms); return false; } } return true; }
private void AvatarPropertiesRequestHandler(Packet packet, LLAgent agent) { AvatarPropertiesRequestPacket request = (AvatarPropertiesRequestPacket)packet; User user; if (m_userClient != null && m_userClient.TryGetUser(request.AgentData.AvatarID, out user)) { SendAvatarProperties(agent, request.AgentData.AvatarID, user); SendAvatarInterests(agent, request.AgentData.AvatarID, user); } else { m_log.Warn("Could not find user " + request.AgentData.AvatarID + ", returning empty profile to " + agent.Name); SendAvatarProperties(agent, request.AgentData.AvatarID, null); SendAvatarInterests(agent, request.AgentData.AvatarID, null); } }
private void AgentAnimationHandler(Packet packet, LLAgent agent) { AgentAnimationPacket animPacket = (AgentAnimationPacket)packet; bool changed = false; for (int i = 0; i < animPacket.AnimationList.Length; i++) { AgentAnimationPacket.AnimationListBlock block = animPacket.AnimationList[i]; if (block.StartAnim) { if (agent.Animations.Add(block.AnimID, ref agent.CurrentAnimSequenceNum)) changed = true; } else { if (agent.Animations.Remove(block.AnimID)) changed = true; } } if (changed) m_scene.SendPresenceAnimations(this, agent); }
private void ViewerEffectHandler(Packet packet, LLAgent agent) { ViewerEffectPacket effect = (ViewerEffectPacket)packet; // Broadcast this viewer effect to everyone for (int i = 0; i < effect.Effect.Length; i++) { ViewerEffectPacket.EffectBlock block = effect.Effect[i]; if (block.AgentID == agent.ID) m_scene.CreateInterestListEvent(new InterestListEvent(UUID.Combine(block.ID, EFFECT_EVENT_ID), VIEWER_EFFECT, agent.ScenePosition, Vector3.One, block)); else m_log.Warn("Skipping ViewerEffect block for " + block.AgentID + " from " + agent.ID + " (" + agent.Name + ")"); } }
private void ImprovedInstantMessageHandler(Packet packet, LLAgent agent) { ImprovedInstantMessagePacket im = (ImprovedInstantMessagePacket)packet; // The following fields are unused since we already have this information, plus the // client could forge it: // - im.MessageBlock.FromAgentName // - im.MessageBlock.FromGroup; // - im.MessageBlock.RegionID // - im.MessageBlock.Position // - im.MessageBlock.Timestamp // - im.MessageBlock.ParentEstateID InstantMessageDialog type = (InstantMessageDialog)im.MessageBlock.Dialog; string message = Utils.BytesToString(im.MessageBlock.Message); bool allowOffline = (im.MessageBlock.Offline != 0); switch (type) { case InstantMessageDialog.MessageFromAgent: case InstantMessageDialog.StartTyping: case InstantMessageDialog.StopTyping: SendInstantMessage(im.MessageBlock.ID, im.MessageBlock.ToAgentID, agent.Name, agent.ScenePosition, agent.Scene.ID, false, type, message, allowOffline, DateTime.UtcNow, im.MessageBlock.BinaryBucket); break; case InstantMessageDialog.RequestTeleport: case InstantMessageDialog.GodLikeRequestTeleport: case InstantMessageDialog.Lure911: case InstantMessageDialog.AcceptTeleport: case InstantMessageDialog.DenyTeleport: case InstantMessageDialog.BusyAutoResponse: break; case InstantMessageDialog.FriendshipOffered: case InstantMessageDialog.FriendshipAccepted: case InstantMessageDialog.FriendshipDeclined: break; case InstantMessageDialog.GroupInvitation: case InstantMessageDialog.GroupInvitationAccept: case InstantMessageDialog.GroupInvitationDecline: break; case InstantMessageDialog.GroupNotice: case InstantMessageDialog.GroupNoticeRequested: case InstantMessageDialog.GroupNoticeInventoryAccepted: case InstantMessageDialog.GroupNoticeInventoryDeclined: case InstantMessageDialog.GroupVote: break; case InstantMessageDialog.InventoryOffered: case InstantMessageDialog.InventoryAccepted: case InstantMessageDialog.InventoryDeclined: break; case InstantMessageDialog.TaskInventoryOffered: case InstantMessageDialog.TaskInventoryAccepted: case InstantMessageDialog.TaskInventoryDeclined: break; case InstantMessageDialog.SessionAdd: case InstantMessageDialog.SessionOfflineAdd: case InstantMessageDialog.SessionCardlessStart: case InstantMessageDialog.Session911Start: case InstantMessageDialog.SessionDrop: case InstantMessageDialog.SessionGroupStart: case InstantMessageDialog.SessionSend: break; //case InstantMessageDialog.MessageFromObject: //case InstantMessageDialog.FromTaskAsAlert: //case InstantMessageDialog.MessageBox: //case InstantMessageDialog.GotoUrl: //case InstantMessageDialog.ConsoleAndChatHistory: //case InstantMessageDialog.NewUserDefault: default: m_log.Warn("Received an IM with unhandled type " + type + " from " + agent.Name); return; } }
private void AgentWearablesRequestHandler(Packet packet, LLAgent agent) { AgentWearablesUpdatePacket update = new AgentWearablesUpdatePacket(); update.AgentData.AgentID = agent.ID; User user; if (m_userClient != null && m_userClient.TryGetUser(agent.ID, out user)) { OSDMap appearanceMap = user.GetField("LLAppearance") as OSDMap; if (appearanceMap != null) { Dictionary<WearableType, UUID> items = new Dictionary<WearableType, UUID>(); Dictionary<WearableType, UUID> assets = new Dictionary<WearableType, UUID>(); foreach (KeyValuePair<string, OSD> kvp in appearanceMap) { UUID id = kvp.Value.AsUUID(); if (id != UUID.Zero) { #region LLAppearance Parsing switch (kvp.Key) { case "ShapeItem": items[WearableType.Shape] = id; break; case "SkinItem": items[WearableType.Skin] = id; break; case "HairItem": items[WearableType.Hair] = id; break; case "EyesItem": items[WearableType.Eyes] = id; break; case "ShirtItem": items[WearableType.Shirt] = id; break; case "PantsItem": items[WearableType.Pants] = id; break; case "ShoesItem": items[WearableType.Shoes] = id; break; case "SocksItem": items[WearableType.Socks] = id; break; case "JacketItem": items[WearableType.Jacket] = id; break; case "GlovesItem": items[WearableType.Gloves] = id; break; case "UndershirtItem": items[WearableType.Undershirt] = id; break; case "UnderpantsItem": items[WearableType.Underpants] = id; break; case "SkirtItem": items[WearableType.Skirt] = id; break; case "AlphaItem": items[WearableType.Alpha] = id; break; case "TattooItem": items[WearableType.Tattoo] = id; break; case "ShapeAsset": assets[WearableType.Shape] = id; break; case "SkinAsset": assets[WearableType.Skin] = id; break; case "HairAsset": assets[WearableType.Hair] = id; break; case "EyesAsset": assets[WearableType.Eyes] = id; break; case "ShirtAsset": assets[WearableType.Shirt] = id; break; case "PantsAsset": assets[WearableType.Pants] = id; break; case "ShoesAsset": assets[WearableType.Shoes] = id; break; case "SocksAsset": assets[WearableType.Socks] = id; break; case "JacketAsset": assets[WearableType.Jacket] = id; break; case "GlovesAsset": assets[WearableType.Gloves] = id; break; case "UndershirtAsset": assets[WearableType.Undershirt] = id; break; case "UnderpantsAsset": assets[WearableType.Underpants] = id; break; case "SkirtAsset": assets[WearableType.Skirt] = id; break; case "AlphaAsset": assets[WearableType.Alpha] = id; break; case "TattooAsset": assets[WearableType.Tattoo] = id; break; } #endregion LLAppearance Parsing } } int i = 0; foreach (KeyValuePair<WearableType, UUID> kvp in items) { update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock(); update.WearableData[i].WearableType = (byte)kvp.Key; update.WearableData[i].ItemID = kvp.Value; assets.TryGetValue(kvp.Key, out update.WearableData[i].AssetID); ++i; } } else { m_log.Warn("User record does not contain an LLAppearance entry, appearance will not be set"); } } if (update.WearableData == null) update.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[0]; m_log.DebugFormat("Sending info about {0} wearables to {1}", update.WearableData.Length, agent.Name); update.AgentData.SerialNum = (uint)System.Threading.Interlocked.Increment(ref agent.CurrentWearablesSerialNum); m_udp.SendPacket(agent, update, ThrottleCategory.Asset, false); }
private void AbortXferHandler(Packet packet, LLAgent agent) { AbortXferPacket abort = (AbortXferPacket)packet; lock (currentUploads) { if (currentUploads.ContainsKey(abort.XferID.ID)) { m_log.Debug(String.Format("Aborting Xfer {0}, result: {1}", abort.XferID.ID, (TransferError)abort.XferID.Result)); currentUploads.Remove(abort.XferID.ID); } else { m_log.Debug(String.Format("Received an AbortXfer for an unknown xfer {0}", abort.XferID.ID)); } } }
private void AssetUploadRequestHandler(Packet packet, LLAgent agent) { AssetUploadRequestPacket request = (AssetUploadRequestPacket)packet; UUID assetID = UUID.Combine(request.AssetBlock.TransactionID, agent.SecureSessionID); AssetType type = (AssetType)request.AssetBlock.Type; // Check if the agent is allowed to upload an asset string uploadError; if (m_permissions != null && !m_permissions.TryUploadOneAsset(agent, out uploadError)) { m_scene.PresenceAlert(this, agent, uploadError); return; } bool local = request.AssetBlock.StoreLocal | type == AssetType.LSLBytecode; bool temp = request.AssetBlock.Tempfile; // Check if the asset is small enough to fit in a single packet if (request.AssetBlock.AssetData.Length != 0) { // Create a new asset from the completed upload Asset asset = CreateAsset(type, assetID, DateTime.UtcNow, agent.ID, local, temp, request.AssetBlock.AssetData); if (asset == null) { m_log.Warn("Failed to create asset from uploaded data"); return; } if (type != AssetType.LSLBytecode) { // Store the asset m_log.DebugFormat("Storing uploaded asset {0} ({1})", assetID, asset.ContentType); if (!m_assets.StoreAsset(asset)) m_log.ErrorFormat("Failed to store uploaded asset {0} ({1})", assetID, asset.ContentType); } else { m_log.Debug("Ignoring LSL bytecode upload " + assetID); } // Send a success response AssetUploadCompletePacket complete = new AssetUploadCompletePacket(); complete.AssetBlock.Success = true; complete.AssetBlock.Type = request.AssetBlock.Type; complete.AssetBlock.UUID = assetID; m_udp.SendPacket(agent, complete, ThrottleCategory.Task, false); } else { // Create a new (empty) asset for the upload Asset asset = CreateAsset(type, assetID, DateTime.UtcNow, agent.ID, local, temp, null); if (asset == null) { m_log.Warn("Failed to create asset from uploaded data"); return; } asset.Temporary = (request.AssetBlock.Tempfile | request.AssetBlock.StoreLocal); ulong transferID = request.AssetBlock.TransactionID.GetULong(); // Prevent LSL bytecode transfers from colliding with LSL source transfers, which // use a colliding UUID if (type == AssetType.LSLBytecode) ++transferID; RequestXferPacket xfer = new RequestXferPacket(); xfer.XferID.DeleteOnCompletion = request.AssetBlock.Tempfile; xfer.XferID.FilePath = 0; xfer.XferID.Filename = Utils.EmptyBytes; xfer.XferID.ID = transferID; xfer.XferID.UseBigPackets = false; xfer.XferID.VFileID = asset.ID; xfer.XferID.VFileType = request.AssetBlock.Type; m_log.DebugFormat("Starting upload for {0} / {1} ({2})", assetID, transferID, asset.ContentType); // Add this asset to the current upload list lock (currentUploads) currentUploads[transferID] = asset; m_udp.SendPacket(agent, xfer, ThrottleCategory.Task, false); } }
private bool CanDownloadTaskInventory(LLAgent agent, AssetType type, UUID taskID, UUID itemID) { ISceneEntity entity; if (m_scene.TryGetEntity(taskID, out entity)) { if (entity is LLPrimitive) { LLPrimitive prim = (LLPrimitive)entity; LLInventoryTaskItem item; if (prim.Inventory.TryGetItem(itemID, out item)) { bool success; if (item.OwnerID == agent.ID) success = item.Permissions.OwnerMask.HasPermission(PermissionMask.Modify); else success = item.Permissions.EveryoneMask.HasPermission(PermissionMask.Modify); if (!success) m_log.Warn("Denying task inventory download from " + agent.Name + " for item " + item.Name + " in task " + taskID); return success; } } } return false; }
private void SendAvatarProperties(LLAgent agent, UUID avatarID, User user) { AvatarPropertiesReplyPacket reply = new AvatarPropertiesReplyPacket(); reply.AgentData.AgentID = agent.ID; reply.AgentData.AvatarID = avatarID; // TODO: Check for ProfileFlags.Online (including permission check) ProfileFlags profileFlags = 0; if (user != null) { if (user.AccessLevel > 0) profileFlags |= ProfileFlags.Identified; reply.PropertiesData.AboutText = Utils.StringToBytes(user.GetField("About").AsString()); reply.PropertiesData.BornOn = Utils.StringToBytes(user.GetField("CreationDate").AsDate().ToString("M/d/yyyy", System.Globalization.CultureInfo.InvariantCulture)); reply.PropertiesData.CharterMember = (user.AccessLevel >= 200) ? Utils.StringToBytes("Operator") : Utils.EmptyBytes; reply.PropertiesData.FLAboutText = Utils.StringToBytes(user.GetField("FLAbout").AsString()); reply.PropertiesData.Flags = (uint)profileFlags; reply.PropertiesData.FLImageID = user.GetField("FLImage").AsUUID(); reply.PropertiesData.ImageID = user.GetField("Image").AsUUID(); reply.PropertiesData.PartnerID = user.GetField("Partner").AsUUID(); reply.PropertiesData.ProfileURL = Utils.StringToBytes(user.GetField("URL").AsString()); } else { reply.PropertiesData.AboutText = Utils.EmptyBytes; reply.PropertiesData.BornOn = Utils.EmptyBytes; reply.PropertiesData.CharterMember = Utils.EmptyBytes; reply.PropertiesData.FLAboutText = Utils.EmptyBytes; reply.PropertiesData.ProfileURL = Utils.EmptyBytes; } m_udp.SendPacket(agent, reply, ThrottleCategory.Task, false); }
private void UUIDGroupNameRequestHandler(Packet packet, LLAgent agent) { // TODO: m_log.Warn("Implement UUIDGroupNameRequest handling"); }
private void TransferDownload(LLAgent agent, UUID transferID, UUID assetID, AssetType type, Asset asset) { const int MAX_CHUNK_SIZE = 1000; string contentType = LLUtil.LLAssetTypeToContentType((int)type); if (contentType == asset.ContentType) { m_log.Debug(String.Format("Transferring asset {0} ({1})", asset.ID, asset.ContentType)); TransferInfoPacket response = new TransferInfoPacket(); response.TransferInfo = new TransferInfoPacket.TransferInfoBlock(); response.TransferInfo.TransferID = transferID; // Set the response channel type response.TransferInfo.ChannelType = (int)ChannelType.Asset; // Params response.TransferInfo.Params = new byte[20]; assetID.ToBytes(response.TransferInfo.Params, 0); Utils.IntToBytes((int)type, response.TransferInfo.Params, 16); response.TransferInfo.Size = asset.Data.Length; response.TransferInfo.Status = (int)StatusCode.OK; response.TransferInfo.TargetType = (int)TargetType.Unknown; // Doesn't seem to be used by the client m_udp.SendPacket(agent, response, ThrottleCategory.Asset, false); // Transfer system does not wait for ACKs, just sends all of the // packets for this transfer out int processedLength = 0; int packetNum = 0; while (processedLength < asset.Data.Length) { TransferPacketPacket transfer = new TransferPacketPacket(); transfer.TransferData.ChannelType = (int)ChannelType.Asset; transfer.TransferData.TransferID = transferID; transfer.TransferData.Packet = packetNum++; int chunkSize = Math.Min(asset.Data.Length - processedLength, MAX_CHUNK_SIZE); transfer.TransferData.Data = new byte[chunkSize]; Buffer.BlockCopy(asset.Data, processedLength, transfer.TransferData.Data, 0, chunkSize); processedLength += chunkSize; if (processedLength >= asset.Data.Length) transfer.TransferData.Status = (int)StatusCode.Done; else transfer.TransferData.Status = (int)StatusCode.OK; m_udp.SendPacket(agent, transfer, ThrottleCategory.Asset, false); } } else { m_log.WarnFormat("Request for asset {0} with type {1} does not match actual asset type {2}", assetID, type, asset.ContentType); TransferNotFound(agent, transferID, assetID, type); } }
private void UUIDNameRequestHandler(Packet packet, LLAgent agent) { UUIDNameRequestPacket request = (UUIDNameRequestPacket)packet; List<UUIDNameReplyPacket.UUIDNameBlockBlock> responses = new List<UUIDNameReplyPacket.UUIDNameBlockBlock>(); for (int i = 0; i < request.UUIDNameBlock.Length; i++) { UUID requestID = request.UUIDNameBlock[i].ID; string firstName = null, lastName = null; // See if we can fetch a presence in the local scene with the requested UUID first IScenePresence localPresence; if (m_scene.TryGetPresence(requestID, out localPresence)) { Util.GetFirstLastName(localPresence.Name, out firstName, out lastName); } else if (m_userClient != null) { // TODO: We might want to switch to a batch user service command in the future User user; if (m_userClient.TryGetUser(requestID, out user)) Util.GetFirstLastName(user.Name, out firstName, out lastName); } if (firstName != null && lastName != null) { UUIDNameReplyPacket.UUIDNameBlockBlock block = new UUIDNameReplyPacket.UUIDNameBlockBlock(); block.ID = requestID; block.FirstName = Utils.StringToBytes(firstName); block.LastName = Utils.StringToBytes(lastName); responses.Add(block); } } // Build the response packet UUIDNameReplyPacket response = new UUIDNameReplyPacket(); response.UUIDNameBlock = responses.ToArray(); m_udp.SendPacket(agent, response, ThrottleCategory.Task, true); }
private void TransferRequestHandler(Packet packet, LLAgent agent) { TransferRequestPacket request = (TransferRequestPacket)packet; ChannelType channel = (ChannelType)request.TransferInfo.ChannelType; SourceType source = (SourceType)request.TransferInfo.SourceType; if (channel == ChannelType.Asset) { if (source == SourceType.Asset) { // Parse the request UUID assetID = new UUID(request.TransferInfo.Params, 0); AssetType type = (AssetType)(sbyte)Utils.BytesToInt(request.TransferInfo.Params, 16); string contentType = LLUtil.LLAssetTypeToContentType((int)type); // Permission check if (!CanDownloadInventory(agent, type, assetID)) { TransferNotFound(agent, request.TransferInfo.TransferID, assetID, type); return; } // Check if we have this asset Asset asset; if (m_assets.TryGetAsset(assetID, contentType, out asset)) TransferDownload(agent, request.TransferInfo.TransferID, assetID, type, asset); else TransferNotFound(agent, request.TransferInfo.TransferID, assetID, type); } else if (source == SourceType.SimInventoryItem) { //UUID agentID = new UUID(request.TransferInfo.Params, 0); //UUID sessionID = new UUID(request.TransferInfo.Params, 16); //UUID ownerID = new UUID(request.TransferInfo.Params, 32); UUID taskID = new UUID(request.TransferInfo.Params, 48); UUID itemID = new UUID(request.TransferInfo.Params, 64); UUID assetID = new UUID(request.TransferInfo.Params, 80); AssetType type = (AssetType)(sbyte)Utils.BytesToInt(request.TransferInfo.Params, 96); string contentType = LLUtil.LLAssetTypeToContentType((int)type); if (taskID != UUID.Zero) { // Task (prim) inventory request permission check if (!CanDownloadTaskInventory(agent, type, taskID, itemID)) { TransferNotFound(agent, request.TransferInfo.TransferID, assetID, type); return; } } else { // Agent inventory request permission check if (!CanDownloadInventory(agent, type, assetID)) { TransferNotFound(agent, request.TransferInfo.TransferID, assetID, type); return; } } // Check if we have this asset Asset asset; if (m_assets.TryGetAsset(assetID, contentType, out asset)) TransferDownload(agent, request.TransferInfo.TransferID, assetID, type, asset); else TransferNotFound(agent, request.TransferInfo.TransferID, assetID, type); } else if (source == SourceType.SimEstate) { //UUID agentID = new UUID(request.TransferInfo.Params, 0); //UUID sessionID = new UUID(request.TransferInfo.Params, 16); //EstateAssetType type = (EstateAssetType)Utils.BytesToInt(request.TransferInfo.Params, 32); m_log.Warn("Don't know what to do with an estate asset transfer request"); } else { m_log.WarnFormat( "Received a TransferRequest that we don't know how to handle. Channel: {0}, Source: {1}", channel, source); } } else { m_log.WarnFormat( "Received a TransferRequest that we don't know how to handle. Channel: {0}, Source: {1}", channel, source); } }
private void AgentDataUpdateRequestHandler(Packet packet, LLAgent agent) { string firstName, lastName; Util.GetFirstLastName(agent.Name, out firstName, out lastName); AgentDataUpdatePacket response = new AgentDataUpdatePacket(); response.AgentData.AgentID = agent.ID; response.AgentData.FirstName = Utils.StringToBytes(firstName); response.AgentData.LastName = Utils.StringToBytes(lastName); bool groupFetchSuccess = false; User user; if (m_userClient != null && m_userClient.TryGetUser(agent.ID, out user)) { OSDMap groupMap = user.GetField("active_group") as OSDMap; if (groupMap != null) { response.AgentData.ActiveGroupID = groupMap["id"].AsUUID(); response.AgentData.GroupName = Utils.StringToBytes(groupMap["name"].AsString()); response.AgentData.GroupPowers = groupMap["powers"].AsULong(); response.AgentData.GroupTitle = Utils.StringToBytes(groupMap["title"].AsString()); groupFetchSuccess = true; } } if (!groupFetchSuccess) { response.AgentData.GroupName = Utils.EmptyBytes; response.AgentData.GroupTitle = Utils.EmptyBytes; } m_udp.SendPacket(agent, response, ThrottleCategory.Task, false); }
private void UpdateTaskInventoryHandler(Packet packet, LLAgent agent) { UpdateTaskInventoryPacket update = (UpdateTaskInventoryPacket)packet; LLInventoryTaskItem item; ISceneEntity targetObj; if (update.UpdateData.Key != 0) { m_log.Warn("Got an UpdateTaskInventory packet with a Key of " + update.UpdateData.Key); return; } if (m_scene.TryGetEntity(update.UpdateData.LocalID, out targetObj) && targetObj is LLPrimitive) { LLPrimitive targetPrim = (LLPrimitive)targetObj; // Updating an existing item in the task inventory if (targetPrim.Inventory.TryGetItem(update.InventoryData.ItemID, out item)) { if (update.InventoryData.TransactionID != UUID.Zero) item.AssetID = UUID.Combine(update.InventoryData.TransactionID, agent.SecureSessionID); item.Description = Utils.BytesToString(update.InventoryData.Description); item.Flags = update.InventoryData.Flags; item.GroupID = update.InventoryData.GroupID; item.GroupOwned = update.InventoryData.GroupOwned; item.Name = Utils.BytesToString(update.InventoryData.Name); item.Permissions = new Permissions(update.InventoryData.BaseMask, update.InventoryData.EveryoneMask, update.InventoryData.GroupMask, update.InventoryData.NextOwnerMask, update.InventoryData.OwnerMask); item.SalePrice = update.InventoryData.SalePrice; item.SaleType = (SaleType)update.InventoryData.SaleType; targetPrim.Inventory.AddOrUpdateItem(item, true); m_log.Debug(agent.Name + " updated task inventory item: " + item.Name); SignalTaskInventoryChange(agent, targetPrim); } else if (m_inventory != null) { // Copying from agent inventory to task inventory InventoryBase obj; if (m_inventory.TryGetInventory(agent.ID, update.InventoryData.ItemID, out obj)) { if (obj is InventoryItem) { // Create a new item in the task inventory LLInventoryItem fromItem = new LLInventoryItem((InventoryItem)obj); item = new LLInventoryTaskItem(); //item.ID will be assigned in AddOrUpdateItem item.AssetID = fromItem.AssetID; item.ContentType = fromItem.ContentType; item.CreationDate = fromItem.CreationDate; item.CreatorID = fromItem.CreatorID; item.Description = fromItem.Description; item.Flags = fromItem.ExtraData["Flags"].AsUInteger(); item.GrantedPermissions = 0; item.GroupID = fromItem.ExtraData["group_id"].AsUUID(); item.GroupOwned = fromItem.ExtraData["group_owned"].AsBoolean(); item.Name = fromItem.Name; item.OwnerID = agent.ID; item.ParentID = update.InventoryData.FolderID; item.ParentObjectID = targetPrim.ID; item.PermissionGranter = UUID.Zero; item.Permissions = fromItem.Permissions; item.SalePrice = fromItem.ExtraData["sale_price"].AsInteger(); item.SaleType = (SaleType)fromItem.ExtraData["sale_type"].AsInteger(); targetPrim.Inventory.AddOrUpdateItem(item, false); m_log.Debug(agent.Name + " created new task inventory item: " + item.Name); SignalTaskInventoryChange(agent, targetPrim); } else { m_log.Error("[TODO] Handle dropping folders in task inventory"); } } else { m_log.Warn(agent.Name + " sent an UpdateTaskInventory packet requesting unknown " + "(or failed to fetch) inventory item " + update.InventoryData.ItemID); } } else { m_log.Warn(agent.Name + "attempted to copy inventory item " + update.InventoryData.ItemID + " to task inventory, but we have no IInventoryClient"); } } else { m_log.Warn(agent.Name + " attempted to update task inventory for prim " + update.UpdateData.LocalID + " that does not exist in this scene"); } }
private void ModifyLandHandler(Packet packet, LLAgent agent) { ModifyLandPacket modify = (ModifyLandPacket)packet; TerrainAction action = (TerrainAction)modify.ModifyBlock.Action; float height = modify.ModifyBlock.Height; float seconds = modify.ModifyBlock.Seconds; // TODO: Build a permission mask based on this agent's permission to edit the affected parcels bool[] allowMask = new bool[64 * 64]; for (int y = 0; y < 64; y++) { for (int x = 0; x < 64; x++) { allowMask[y * 64 + x] = true; } } // Build an edit mask that tracks all of the terrain blocks modified by this request bool[] editMask = new bool[16 * 16]; for (int i = 0; i < modify.ParcelData.Length; i++) { ModifyLandPacket.ParcelDataBlock block = modify.ParcelData[i]; int localID = block.LocalID; float north = block.North; float east = block.East; float south = block.South; float west = block.West; float size = (modify.ModifyBlockExtended.Length > i) ? modify.ModifyBlockExtended[i].BrushSize : modify.ModifyBlock.BrushSize; if (north == south && east == west) { // Terrain painting switch (action) { case TerrainAction.Raise: RaiseLowerSphere(allowMask, ref editMask, west, south, height, size, seconds); break; case TerrainAction.Flatten: FlattenSphere(allowMask, ref editMask, west, south, height, size, seconds); break; case TerrainAction.Lower: RaiseLowerSphere(allowMask, ref editMask, west, south, height, size, seconds * -1.0f); break; case TerrainAction.Noise: NoiseSphere(allowMask, ref editMask, west, south, height, size, seconds); break; case TerrainAction.Revert: RevertSphere(allowMask, ref editMask, west, south, height, size, seconds); break; case TerrainAction.Smooth: SmoothSphere(allowMask, ref editMask, west, south, height, size, seconds); break; default: m_log.Warn("Unhandled ModifyLand paint action " + action); break; } } else { // Terrain flooding switch (action) { case TerrainAction.Raise: case TerrainAction.Flatten: case TerrainAction.Lower: case TerrainAction.Noise: case TerrainAction.Revert: case TerrainAction.Smooth: default: m_log.Warn("Unhandled ModifyLand flood action " + action); break; } } } // Send updates out for any modified terrain blocks for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { if (editMask[y * 16 + x]) { m_scene.CreateInterestListEvent(new InterestListEvent( CreateTerrainEventID(x, y), TERRAIN, new Vector3(x * 16 + 8, y * 16 + 8, 0.0f), TERRAIN_SCALE, new int[] { x, y }) ); } } } }
private void AgentIsNowWearingHandler(Packet packet, LLAgent agent) { // This odd function takes the incoming map of WearableType -> ItemID, converts it to // the LLAppearance format of string -> ItemID, fetches all of the wearable inventory // items, and converts them into the LLAppearance format of string -> AssetID before // updating the user's LLAppearance data AgentIsNowWearingPacket wearing = (AgentIsNowWearingPacket)packet; OSDMap appearanceMap = new OSDMap(); List<UUID> requestIDs = new List<UUID>(wearing.WearableData.Length); Dictionary<UUID, string> wornItems = new Dictionary<UUID, string>(); int count = 0; // Put the ItemIDs in appearanceMap and requestIDs for (int i = 0; i < wearing.WearableData.Length; i++) { AgentIsNowWearingPacket.WearableDataBlock block = wearing.WearableData[i]; #region WearableType Conversion switch ((WearableType)block.WearableType) { case WearableType.Shape: appearanceMap["ShapeItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "ShapeAsset"; break; case WearableType.Skin: appearanceMap["SkinItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "SkinAsset"; break; case WearableType.Hair: appearanceMap["HairItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "HairAsset"; break; case WearableType.Eyes: appearanceMap["EyesItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "EyesAsset"; break; case WearableType.Shirt: appearanceMap["ShirtItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "ShirtAsset"; break; case WearableType.Pants: appearanceMap["PantsItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "PantsAsset"; break; case WearableType.Shoes: appearanceMap["ShoesItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "ShoesAsset"; break; case WearableType.Socks: appearanceMap["SocksItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "SocksAsset"; break; case WearableType.Jacket: appearanceMap["JacketItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "JacketAsset"; break; case WearableType.Gloves: appearanceMap["GlovesItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "GlovesAsset"; break; case WearableType.Undershirt: appearanceMap["UndershirtItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "UndershirtAsset"; break; case WearableType.Underpants: appearanceMap["UnderpantsItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "UnderpantsAsset"; break; case WearableType.Skirt: appearanceMap["SkirtItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "SkirtAsset"; break; case WearableType.Alpha: appearanceMap["AlphaItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "AlphaAsset"; break; case WearableType.Tattoo: appearanceMap["TattooItem"] = OSD.FromUUID(block.ItemID); wornItems[block.ItemID] = "TattooAsset"; break; } #endregion WearableType Conversion if (block.ItemID != UUID.Zero) { requestIDs.Add(block.ItemID); ++count; } } m_log.Debug("Updating agent wearables for " + agent.Name + ", new count: " + count); // Fetch all of the AssetIDs for inventory items listed in requestIDs IDictionary<UUID, UUID> itemsToAssetIDs; if (m_inventoryClient != null && m_inventoryClient.TryGetAssetIDs(agent.ID, requestIDs.ToArray(), out itemsToAssetIDs)) { foreach (KeyValuePair<UUID, UUID> kvp in itemsToAssetIDs) { // Put the AssetIDs in appearanceMap string wearableAssetKey; if (wornItems.TryGetValue(kvp.Key, out wearableAssetKey)) appearanceMap[wearableAssetKey] = OSD.FromUUID(kvp.Value); } m_log.Debug("Did " + itemsToAssetIDs.Count + " ItemID -> AssetID lookups for " + agent.Name); } else { m_log.Warn("Failed to resolve ItemIDs to AssetIDs for " + agent.Name); } if (m_userClient != null) m_userClient.UpdateUserFields(agent.ID, new OSDMap { { "LLAppearance", appearanceMap } }); else m_log.Warn("Cannot save agent appearance without an IUserClient"); }