void AssetUploadRequestHandler(Packet packet, Agent agent) { AssetUploadRequestPacket request = (AssetUploadRequestPacket)packet; UUID assetID = UUID.Combine(request.AssetBlock.TransactionID, agent.SecureSessionID); // 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((AssetType)request.AssetBlock.Type, assetID, request.AssetBlock.AssetData); if (asset == null) { Logger.Log("Failed to create asset from uploaded data", Helpers.LogLevel.Warning); return; } Logger.DebugLog(String.Format("Storing uploaded asset {0} ({1})", assetID, asset.AssetType)); asset.Temporary = (request.AssetBlock.Tempfile | request.AssetBlock.StoreLocal); // Store the asset StoreAsset(asset); // Send a success response AssetUploadCompletePacket complete = new AssetUploadCompletePacket(); complete.AssetBlock.Success = true; complete.AssetBlock.Type = request.AssetBlock.Type; complete.AssetBlock.UUID = assetID; server.UDP.SendPacket(agent.AgentID, complete, PacketCategory.Inventory); } else { // Create a new (empty) asset for the upload Asset asset = CreateAsset((AssetType)request.AssetBlock.Type, assetID, null); if (asset == null) { Logger.Log("Failed to create asset from uploaded data", Helpers.LogLevel.Warning); return; } Logger.DebugLog(String.Format("Starting upload for {0} ({1})", assetID, asset.AssetType)); asset.Temporary = (request.AssetBlock.Tempfile | request.AssetBlock.StoreLocal); RequestXferPacket xfer = new RequestXferPacket(); xfer.XferID.DeleteOnCompletion = request.AssetBlock.Tempfile; xfer.XferID.FilePath = 0; xfer.XferID.Filename = new byte[0]; xfer.XferID.ID = request.AssetBlock.TransactionID.GetULong(); xfer.XferID.UseBigPackets = false; xfer.XferID.VFileID = asset.AssetID; xfer.XferID.VFileType = request.AssetBlock.Type; // Add this asset to the current upload list lock (CurrentUploads) CurrentUploads[xfer.XferID.ID] = asset; server.UDP.SendPacket(agent.AgentID, xfer, PacketCategory.Inventory); } }
private void SendPresenceAnimationsHandler(object sender, PhysicalPresenceArgs e) { IPhysicalPresence presence = e.Presence; presence.Scene.CreateInterestListEvent(new InterestListEvent(UUID.Combine(presence.ID, ANIMATION_EVENT_ID), AVATAR_ANIMATION, presence.ScenePosition, presence.Scale, presence)); }
public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { if (XferUploaders.ContainsKey(transactionID)) { UUID assetID = UUID.Combine(transactionID, remoteClient.SecureSessionId); AssetBase asset = Manager.MyScene.AssetService.Get(assetID.ToString()); if (asset == null) { asset = GetTransactionAsset(transactionID); } if (asset != null && asset.FullID == assetID) { // Assets never get updated, new ones get created asset.FullID = UUID.Random(); asset.Name = item.Name; asset.Description = item.Description; asset.Type = (sbyte)item.AssetType; item.AssetID = asset.FullID; Manager.MyScene.AssetService.Store(asset); } IInventoryService invService = Manager.MyScene.InventoryService; invService.UpdateItem(item); } }
public void PreloadSound(ISceneEntity source, UUID soundID, float radius) { m_scene.CreateInterestListEvent(new InterestListEvent( UUID.Combine(soundID, PRELOAD_EVENT_ID), PRELOAD_SOUND, source.ScenePosition, new Vector3(radius), new object[] { source, soundID }) ); }
/*private Packet UpdateInventory(Packet packet, IPEndPoint sim) * { * /* * UpdateInventoryItemPacket uip = (UpdateInventoryItemPacket)packet; * foreach (UpdateInventoryItemPacket.InventoryDataBlock block in uip.InventoryData) * { * if (block.Type == 10) * { * if(trans2Item.ContainsKey(block.TransactionID)) * { * trans2Item[block.TransactionID]=block.ItemID; * }else * trans2Item.Add(block.TransactionID, block.ItemID); * } * } * foreach (CurrentUploadType cu in name2SaveBuffer) * { * if (trans2Item.ContainsKey(cu.uploadID)) * { * string filename = trans2Item[curentUpload.uploadID].ToString(); * * File.WriteAllBytes("Scripts Cache\\" + filename, curentUpload.oldscriptdata); * } * } * name2SaveBuffer.Clear(); * return packet; * }*/ private Packet TryToSendAsset(Packet packet, IPEndPoint sim) { if (Enabled) { AssetUploadRequestPacket ass = (AssetUploadRequestPacket)packet; if (ass.AssetBlock.Type == (sbyte)AssetType.LSLText) { Console.WriteLine("Atempting to save to inv with asset type " + ass.AssetBlock.Type.ToString()); CurrentUploadType curentUpload = new CurrentUploadType(); curentUpload.proxySending = false; curentUpload.local = ass.AssetBlock.StoreLocal; curentUpload.temp = ass.AssetBlock.Tempfile; curentUpload.uploadID = ass.AssetBlock.TransactionID; curentUpload.type = ass.AssetBlock.Type; curentUpload.data = new byte[] { }; curentUpload.paid = false; curentUpload.oldscriptdata = new byte[300000]; /*uint newperms = 0; * newperms |= (uint)PermissionMask.Modify; * newperms |= (uint)PermissionMask.Copy; * newperms |= (uint)PermissionMask.Transfer; * * curentUpload.ownerMask = newperms;*/ curentUpload.curentdatalenght = 0; curentUpload.oldmaxsize = 90000; //Buffer.BlockCopy(ass.AssetBlock.AssetData, 0, curentUpload.oldscriptdata, 0, curentUpload.curentdatalenght); AssetUploadRequestPacket asetUp = new AssetUploadRequestPacket(); asetUp.AssetBlock.StoreLocal = curentUpload.local; asetUp.AssetBlock.Tempfile = false; asetUp.AssetBlock.TransactionID = curentUpload.uploadID; asetUp.AssetBlock.Type = (sbyte)AssetType.LSLText; asetUp.AssetBlock.AssetData = new byte[] { }; //proxy.InjectPacket(asetUp, Direction.Outgoing); //proxy curentUpload.VFileAssetID = UUID.Combine(curentUpload.uploadID, frame.SecureSessionID); form.log("We are expecintg a vfile id of " + curentUpload.VFileAssetID.ToString(), System.Drawing.Color.Black, System.Drawing.Color.Magenta); if (this.uploadsLookingForXferId.ContainsKey(curentUpload.VFileAssetID)) { this.uploadsLookingForXferId[curentUpload.VFileAssetID] = curentUpload; } else { this.uploadsLookingForXferId.Add(curentUpload.VFileAssetID, curentUpload); } } } return(packet); }
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; } }
public void SaveToSLInventory(byte[] uploaddata, String nname, sbyte type, bool copy, bool mod, bool trans, bool pay, bool local, bool temp) { Console.WriteLine("Atempting to save to inv"); uploadID = UUID.Random(); AssetUploadRequestPacket asetUp = new AssetUploadRequestPacket(); asetUp.AssetBlock.StoreLocal = local; asetUp.AssetBlock.Tempfile = temp; asetUp.AssetBlock.TransactionID = uploadID; specialID = UUID.Combine(uploadID, frame.SessionID); asetUp.AssetBlock.Type = (sbyte)type; asetUp.AssetBlock.AssetData = new byte[] { }; proxy.InjectPacket(asetUp, Direction.Outgoing); this.curentUpload = new CurrentUploadType(); curentUpload.name = nname; curentUpload.data = uploaddata; curentUpload.temp = temp; curentUpload.type = (sbyte)type; curentUpload.local = local; curentUpload.paid = pay; grabbed = 0; if (pay) { payMoney(10); } uint newperms = 0; if (mod) { newperms |= (uint)PermissionMask.Modify; } if (copy) { newperms |= (uint)PermissionMask.Copy; } if (trans) { newperms |= (uint)PermissionMask.Transfer; } curentUpload.ownerMask = newperms; //generate owner mask }
private void SaveScriptState(LSLScriptInstance instance) { // Create a state file for this script byte[] scriptState = instance.GetSerializedState(); m_assetClient.StoreAsset(new Asset { ContentType = "application/vnd.ll.lslstate", CreatorID = instance.Host.OwnerID, Data = scriptState, ID = UUID.Combine(instance.ID, SCRIPT_STATE_MAGIC_ID), Local = true, Temporary = true, CreationDate = DateTime.UtcNow }); }
private void PresenceAddHandler(object sender, PresenceArgs e) { m_scene.ForEachPresence( delegate(IScenePresence presence) { InterestListEvent eventData = new InterestListEvent ( UUID.Combine(presence.ID, APPEARANCE_EVENT_ID), AVATAR_APPEARANCE, presence.ScenePosition, presence.Scale, presence ); m_scene.CreateInterestListEventFor(e.Presence, eventData); } ); }
public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { if (XferUploaders.ContainsKey(transactionID)) { UUID assetID = UUID.Combine(transactionID, remoteClient.SecureSessionId); AssetXferUploader uploader = XferUploaders[transactionID]; if (!uploader.Finished) { uploader.FinishedEvent = () => UpdateInventoryItemWithAsset(item, assetID, transactionID); return; } UpdateInventoryItemWithAsset(item, assetID, transactionID); } }
public void llInstantMessage(IScriptInstance script, string user, string message) { if (m_messaging != null) { UUID toID; UUID.TryParse(user, out toID); // Keep a persistent messageID for all IMs from the host object to the target agent UUID messageID = UUID.Combine(script.Host.ID, toID); m_messaging.SendInstantMessage(messageID, toID, script.Host.Name, script.Host.ScenePosition, script.Host.Scene.ID, false, InstantMessageDialog.MessageFromObject, message, false, DateTime.UtcNow, Utils.EmptyBytes); } script.AddSleepMS(2000); }
public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { if (XferUploaders.ContainsKey(transactionID)) { CachedUserInfo userInfo = Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails( remoteClient.AgentId); if (userInfo != null) { UUID assetID = UUID.Combine(transactionID, remoteClient.SecureSessionId); AssetBase asset = Manager.MyScene.CommsManager.AssetCache.GetAsset( assetID, (item.AssetType == (int)AssetType.Texture ? true : false)); if (asset == null) { asset = GetTransactionAsset(transactionID); } if (asset != null && asset.FullID == assetID) { // Assets never get updated, new ones get created asset.FullID = UUID.Random(); asset.Name = item.Name; asset.Description = item.Description; asset.Type = (sbyte)item.AssetType; item.AssetID = asset.FullID; Manager.MyScene.CommsManager.AssetCache.AddAsset(asset); } userInfo.UpdateItem(item); } else { m_log.ErrorFormat( "[ASSET TRANSACTIONS]: Could not find user {0} for inventory item update", remoteClient.AgentId); } } }
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 + ")"); } } }
public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { if (XferUploaders.ContainsKey(transactionID)) { UUID assetID = UUID.Combine(transactionID, remoteClient.SecureSessionId); AssetBase asset = Manager.MyScene.AssetService.Get(assetID.ToString()); if (asset == null) { asset = GetTransactionAsset(transactionID); } if (asset != null && asset.ID == assetID) { // Assets never get updated, new ones get created asset.ID = UUID.Random(); asset.Name = item.Name; asset.Description = item.Description; asset.Type = (sbyte)item.AssetType; item.AssetID = asset.ID; asset.ID = Manager.MyScene.AssetService.Store(asset); item.AssetID = asset.ID; } IMonitorModule monitorModule = Manager.MyScene.RequestModuleInterface <IMonitorModule>(); if (monitorModule != null) { INetworkMonitor networkMonitor = (INetworkMonitor) monitorModule.GetMonitor(Manager.MyScene.RegionInfo.RegionID.ToString(), MonitorModuleHelper.NetworkMonitor); networkMonitor.AddPendingUploads(-1); } IInventoryService invService = Manager.MyScene.InventoryService; invService.UpdateItem(item); } }
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); } }
/// <summary> /// Builds a composited terrain texture given the region texture /// and heightmap settings /// </summary> /// <param name="terrain">Terrain heightmap</param> /// <param name="regionInfo">Region information including terrain texture parameters</param> /// <returns>A 256x256 square RGB texture ready for rendering</returns> /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting /// Note we create a 256x256 dimension texture even if the actual terrain is larger. /// </remarks> public static Bitmap Splat(ITerrainChannel terrain, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetService assetService, bool textureTerrain) { Debug.Assert(textureIDs.Length == 4); Debug.Assert(startHeights.Length == 4); Debug.Assert(heightRanges.Length == 4); Bitmap[] detailTexture = new Bitmap[4]; if (textureTerrain) { // Swap empty terrain textureIDs with default IDs for (int i = 0; i < textureIDs.Length; i++) { if (textureIDs[i] == UUID.Zero) { textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; } } #region Texture Fetching if (assetService != null) { for (int i = 0; i < 4; i++) { AssetBase asset; UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); // Try to fetch a cached copy of the decoded/resized version of this texture asset = assetService.GetCached(cacheID.ToString()); if (asset != null) { try { using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) detailTexture[i] = (Bitmap)Image.FromStream(stream); } catch (Exception ex) { m_log.Warn("Failed to decode cached terrain texture " + cacheID + " (textureID: " + textureIDs[i] + "): " + ex.Message); } } if (detailTexture[i] == null) { // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG asset = assetService.Get(textureIDs[i].ToString()); if (asset != null) { // m_log.DebugFormat( // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } catch (Exception ex) { m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); } } if (detailTexture[i] != null) { // Make sure this texture is the correct size, otherwise resize if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) { using (Bitmap origBitmap = detailTexture[i]) { detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256); } } // Save the decoded and resized texture to the cache byte[] data; using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) { detailTexture[i].Save(stream, ImageFormat.Png); data = stream.ToArray(); } // Cache a PNG copy of this terrain texture AssetBase newAsset = new AssetBase { Data = data, Description = "PNG", Flags = AssetFlags.Collectable, FullID = cacheID, ID = cacheID.ToString(), Local = true, Name = String.Empty, Temporary = true, Type = (sbyte)AssetType.Unknown }; newAsset.Metadata.ContentType = "image/png"; assetService.Store(newAsset); } } } } #endregion Texture Fetching } // Fill in any missing textures with a solid color for (int i = 0; i < 4; i++) { if (detailTexture[i] == null) { m_log.DebugFormat("{0} Missing terrain texture for layer {1}. Filling with solid default color", LogHeader, i); // Create a solid color texture for this layer detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); using (Graphics gfx = Graphics.FromImage(detailTexture[i])) { using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) gfx.FillRectangle(brush, 0, 0, 256, 256); } } else { if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) { detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256); } } } #region Layer Map float[,] layermap = new float[256, 256]; // Scale difference between actual region size and the 256 texture being created int xFactor = terrain.Width / 256; int yFactor = terrain.Height / 256; // Create 'layermap' where each value is the fractional layer number to place // at that point. For instance, a value of 1.345 gives the blending of // layer 1 and layer 2 for that point. for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { float height = (float)terrain[x * xFactor, y *yFactor]; float pctX = (float)x / 255f; float pctY = (float)y / 255f; // Use bilinear interpolation between the four corners of start height and // height range to select the current values at this position float startHeight = ImageUtils.Bilinear( startHeights[0], startHeights[2], startHeights[1], startHeights[3], pctX, pctY); startHeight = Utils.Clamp(startHeight, 0f, 255f); float heightRange = ImageUtils.Bilinear( heightRanges[0], heightRanges[2], heightRanges[1], heightRanges[3], pctX, pctY); heightRange = Utils.Clamp(heightRange, 0f, 255f); // Generate two frequencies of perlin noise based on our global position // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting Vector3 vec = new Vector3 ( ((float)regionPosition.X + (x * xFactor)) * 0.20319f, ((float)regionPosition.Y + (y * yFactor)) * 0.20319f, height * 0.25f ); float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f; float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; float noise = (lowFreq + highFreq) * 2f; // Combine the current height, generated noise, start height, and height range parameters, then scale all of it float layer = ((height + noise - startHeight) / heightRange) * 4f; if (Single.IsNaN(layer)) { layer = 0f; } layermap[x, y] = Utils.Clamp(layer, 0f, 3f); } } #endregion Layer Map #region Texture Compositing Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); // Unsafe work as we lock down the source textures for quicker access and access the // pixel data directly unsafe { // Get handles to all of the texture data arrays BitmapData[] datas = new BitmapData[] { detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) }; // Compute size of each pixel data (used to address into the pixel data array) int[] comps = new int[] { (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 }; for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { float layer = layermap[x, y]; // Select two textures int l0 = (int)Math.Floor(layer); int l1 = Math.Min(l0 + 1, 3); byte *ptrA = (byte *)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; byte *ptrB = (byte *)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; byte *ptrO = (byte *)outputData.Scan0 + y * outputData.Stride + x * 3; float aB = *(ptrA + 0); float aG = *(ptrA + 1); float aR = *(ptrA + 2); float bB = *(ptrB + 0); float bG = *(ptrB + 1); float bR = *(ptrB + 2); float layerDiff = layer - l0; // Interpolate between the two selected textures *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); } } for (int i = 0; i < detailTexture.Length; i++) { detailTexture[i].UnlockBits(datas[i]); } } for (int i = 0; i < detailTexture.Length; i++) { if (detailTexture[i] != null) { detailTexture[i].Dispose(); } } output.UnlockBits(outputData); // We generated the texture upside down, so flip it output.RotateFlip(RotateFlipType.RotateNoneFlipY); #endregion Texture Compositing return(output); }
public bool RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { AssetXferUploader uploader = GetTransactionUploader(transactionID); if (uploader == null) { m_log.WarnFormat("[ASSET TRANSACTIONS]: Transaction {0} NOT FOUND (duplicate removed?) for inventory item update {1}", transactionID, item.Name); return(false); } CachedUserInfo userInfo = Manager.MyScene.CommsManager.UserService.GetUserDetails(remoteClient.AgentId); if (userInfo == null) { m_log.WarnFormat("[ASSET TRANSACTIONS]: Could not find user {0} for transaction {1} for inventory update {2}", remoteClient.AgentId, transactionID, item.Name); return(false); } // This may complete now if upload complete, or later when the upload completes. uploader.TriggerWhenUploadComplete(delegate(AssetBase asset) { // This upload transaction is complete. XferUploaders.Remove(transactionID); UUID assetID = UUID.Combine(transactionID, remoteClient.SecureSessionId); if (asset == null || asset.FullID != assetID) { m_log.ErrorFormat("[ASSETS]: RequestUpdateInventoryItem wrong asset ID or not found {0}", asset == null ? "null" : asset.FullID.ToString()); return; } // Assets never get updated, new ones get created UUID oldID = asset.FullID; asset.FullID = UUID.Random(); asset.Name = item.Name; asset.Description = item.Description; asset.Type = (sbyte)item.AssetType; try { m_log.DebugFormat("[ASSETS]: RequestUpdateInventoryItem for transaction {0}, new asset {1} -> {2}", transactionID, oldID, asset.FullID); Manager.MyScene.CommsManager.AssetCache.AddAsset(asset, AssetRequestInfo.GenericNetRequest()); } catch (AssetServerException e) { remoteClient.SendAgentAlertMessage("Unable to upload asset. Please try again later.", false); m_log.ErrorFormat("[ASSET TRANSACTIONS] Creation of asset failed {0}", e); return; } item.AssetID = asset.FullID; //wait for completion of the write to avoid reversion ManualResetEventSlim waitEvent = new ManualResetEventSlim(); remoteClient.HandleWithInventoryWriteThread(() => { // Update the asset ID userInfo.UpdateItem(item); waitEvent.Set(); }); waitEvent.Wait(); waitEvent.Dispose(); }); return(true); // userInfo item was updated }
public bool UploadAssetData(bool storeLocal) { if (IsLocalScene) { ReplaceAll(); RezRequested = true; NewID = OldID; _NewItem = OldItem; return(true); } if (CogbotHelpers.IsNullOrZero(NewID)) { if (UseUploadKnown) { AssetUploaded.Reset(); if (assetType == AssetType.Notecard) { Inventory.RequestCreateItem(GetAssetUploadsFolder(), "" + OldID, Description, assetType, UUID.Zero, OpenMetaverse.InventoryType.Notecard, PermissionMask.All, UpdateInvItem); } else if (assetType == AssetType.Gesture) { Inventory.RequestCreateItem(GetAssetUploadsFolder(), "" + OldID, Description, assetType, UUID.Zero, OpenMetaverse.InventoryType.Gesture, PermissionMask.All, UpdateInvItem); // (gesture.Sequence) } else if (assetType == AssetType.LSLText) { Inventory.RequestCreateItem(GetAssetUploadsFolder(), "" + OldID, Description, assetType, UUID.Zero, OpenMetaverse.InventoryType.LSL, PermissionMask.All, UpdateInvItem); } else if (assetType == AssetType.Landmark) { var decodeME = new AssetLandmark(UUID.Zero, AssetData); decodeME.Decode(); byte[] bytes = AssetData; Inventory.RequestCreateItem(GetAssetUploadsFolder(), "" + OldID, "RegionID:" + decodeME.RegionID + ",Postion" + decodeME.Position + "," + DateTime.Now, assetType, UUID.Zero, OpenMetaverse.InventoryType.Landmark, PermissionMask.All, UpdateInvItem); } else if (assetType == AssetType.CallingCard) { var decodeME = new AssetCallingCard(UUID.Zero, AssetData); decodeME.Decode(); byte[] bytes = AssetData; Inventory.RequestCreateItem(GetAssetUploadsFolder(), "" + OldID, "AvatarID:" + decodeME.AvatarID + "," + DateTime.Now, assetType, UUID.Zero, OpenMetaverse.InventoryType.CallingCard, PermissionMask.All, UpdateInvItem); } else { Inventory.RequestCreateItemFromAsset(AssetData, "" + OldID, Description, assetType, inventoryType, GetAssetUploadsFolder(), Permissions.FullPermissions, InvItemCreated); } if (!AssetUploaded.WaitOne(10000)) { return(false); } return(true); } NewID = UUID.Combine(OldID, Importing.Client.Self.SecureSessionID); NewUUID2OBJECT[NewID] = this; Importing.Client.Assets.RequestUploadKnown(NewID, assetType, AssetData, storeLocal, OldID); RezRequested = true; } return(true); }
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 PresenceAddHandler(object sender, PresenceArgs e) { // When an LLUDP agent logs in, send them current animation data for every presence in the sim if (e.Presence is LLAgent) { m_scene.ForEachPresence( delegate(IScenePresence presence) { m_scene.CreateInterestListEventFor(e.Presence, new InterestListEvent(UUID.Combine(presence.ID, ANIMATION_EVENT_ID), AVATAR_ANIMATION, presence.ScenePosition, presence.Scale, presence)); } ); } }
private Color4 GetFaceColor(Primitive.TextureEntryFace face) { Color4 color; if (face.TextureID == UUID.Zero) { return(face.RGBA); } if (!m_colors.TryGetValue(face.TextureID, out color)) { bool fetched = false; // Attempt to fetch the texture metadata UUID metadataID = UUID.Combine(face.TextureID, TEXTURE_METADATA_MAGIC); AssetBase metadata = m_scene.AssetService.GetCached(metadataID.ToString()); if (metadata != null) { OSDMap map = null; try { map = OSDParser.Deserialize(metadata.Data) as OSDMap; } catch { } if (map != null) { color = map["X-JPEG2000-RGBA"].AsColor4(); if (!(color.R == 0.5f && color.G == 0.5f && color.B == 0.5f && color.A == 1.0f)) { //If we failed, don't save it fetched = true; } } map = null; metadata = null; } if (!fetched) { // Fetch the texture, decode and get the average color, // then save it to a temporary metadata asset AssetBase textureAsset = m_scene.AssetService.Get(face.TextureID.ToString()); if (textureAsset != null) { int width, height; color = GetAverageColor(textureAsset.ID, textureAsset.Data, m_scene, out width, out height); if (!(color.R == 0.5f && color.G == 0.5f && color.B == 0.5f && color.A == 1.0f)) //If we failed, don't save it { OSDMap data = new OSDMap { { "X-JPEG2000-RGBA", OSD.FromColor4(color) } }; metadata = new AssetBase { Data = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(data)), Description = "Avg Color-JPEG2000 texture " + face.TextureID.ToString(), Flags = AssetFlags.Collectable | AssetFlags.Temperary | AssetFlags.Local, ID = metadataID, Name = String.Empty, TypeAsset = AssetType.Simstate // Make something up to get around OpenSim's myopic treatment of assets }; metadata.ID = m_scene.AssetService.Store(metadata); } textureAsset = null; } else { color = new Color4(0.5f, 0.5f, 0.5f, 1.0f); } } m_colors[face.TextureID] = color; } return(color * face.RGBA); }
private UUID CreateTerrainEventID(int x, int y) { return(UUID.Combine(TERRAIN_EVENT_ID, new UUID(Utils.UIntsToLong((uint)x, (uint)y)))); }
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"); } }
/// <summary> /// Builds a composited terrain texture given the region texture /// and heightmap settings /// </summary> /// <param name = "heightmap">Terrain heightmap</param> /// <param name = "regionInfo">Region information including terrain texture parameters</param> /// <returns>A composited 256x256 RGB texture ready for rendering</returns> /// <remarks> /// Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting /// </remarks> public static Bitmap Splat(ITerrainChannel heightmap, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetService assetService, bool textureTerrain) { Debug.Assert(textureIDs.Length == 4); Debug.Assert(startHeights.Length == 4); Debug.Assert(heightRanges.Length == 4); Bitmap[] detailTexture = new Bitmap[4]; if (textureTerrain) { // Swap empty terrain textureIDs with default IDs for (int i = 0; i < textureIDs.Length; i++) { if (textureIDs[i] == UUID.Zero) { textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; } } #region Texture Fetching if (assetService != null) { for (int i = 0; i < 4; i++) { UUID cacheID = UUID.Combine(TERRAIN_CACHE_MAGIC, textureIDs[i]); AssetBase asset = assetService.GetCached(cacheID.ToString()); if ((asset != null) && (asset.Data != null) && (asset.Data.Length != 0)) { try { using (MemoryStream stream = new MemoryStream(asset.Data)) detailTexture[i] = (Bitmap)Image.FromStream(stream); } catch (Exception ex) { MainConsole.Instance.Warn("Failed to decode cached terrain texture " + cacheID + " (textureID: " + textureIDs[i] + "): " + ex.Message); } } if (detailTexture[i] == null) { // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG asset = assetService.Get(textureIDs[i].ToString()); if (asset != null) { try { detailTexture[i] = (Bitmap)J2kImage.FromBytes(asset.Data); } catch (Exception ex) { MainConsole.Instance.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); } } if (detailTexture[i] != null) { Bitmap bitmap = detailTexture[i]; // Make sure this texture is the correct size, otherwise resize if (bitmap.Width != 256 || bitmap.Height != 256) { bitmap = ImageUtils.ResizeImage(bitmap, 256, 256); } // Save the decoded and resized texture to the cache byte[] data; using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); data = stream.ToArray(); } // Cache a PNG copy of this terrain texture AssetBase newAsset = new AssetBase { Data = data, Description = "PNG", Flags = AssetFlags.Collectable | AssetFlags.Temporary | AssetFlags.Local, ID = cacheID, Name = String.Empty, TypeString = "image/png" }; newAsset.FillHash(); newAsset.ID = assetService.Store(newAsset); } } } } #endregion Texture Fetching } // Fill in any missing textures with a solid color for (int i = 0; i < 4; i++) { if (detailTexture[i] == null) { // Create a solid color texture for this layer detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); using (Graphics gfx = Graphics.FromImage(detailTexture[i])) { using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) gfx.FillRectangle(brush, 0, 0, 256, 256); } } else if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) { detailTexture[i] = ResizeBitmap(detailTexture[i], 256, 256); } } #region Layer Map float diff = (float)heightmap.Height / (float)Constants.RegionSize; float[] layermap = new float[Constants.RegionSize * Constants.RegionSize]; for (float y = 0; y < heightmap.Height; y += diff) { for (float x = 0; x < heightmap.Height; x += diff) { float newX = x / diff; float newY = y / diff; float height = heightmap[(int)newX, (int)newY]; float pctX = newX / 255f; float pctY = newY / 255f; // Use bilinear interpolation between the four corners of start height and // height range to select the current values at this position float startHeight = ImageUtils.Bilinear( startHeights[0], startHeights[2], startHeights[1], startHeights[3], pctX, pctY); startHeight = Utils.Clamp(startHeight, 0f, 255f); float heightRange = ImageUtils.Bilinear( heightRanges[0], heightRanges[2], heightRanges[1], heightRanges[3], pctX, pctY); heightRange = Utils.Clamp(heightRange, 0f, 255f); // Generate two frequencies of perlin noise based on our global position // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting Vector3 vec = new Vector3 ( ((float)regionPosition.X + newX) * 0.20319f, ((float)regionPosition.Y + newY) * 0.20319f, height * 0.25f ); float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f; float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; float noise = (lowFreq + highFreq) * 2f; // Combine the current height, generated noise, start height, and height range parameters, then scale all of it float layer = ((height + noise - startHeight) / heightRange) * 4f; if (Single.IsNaN(layer)) { layer = 0f; } layermap[(int)(newY * Constants.RegionSize + newX)] = Utils.Clamp(layer, 0f, 3f); } } #endregion Layer Map #region Texture Compositing Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); unsafe { // Get handles to all of the texture data arrays BitmapData[] datas = new[] { detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) }; int[] comps = new[] { (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 }; for (int y = 0; y < Constants.RegionSize; y++) { for (int x = 0; x < Constants.RegionSize; x++) { float layer = layermap[y * Constants.RegionSize + x]; // Select two textures int l0 = (int)Math.Floor(layer); int l1 = Math.Min(l0 + 1, 3); byte *ptrA = (byte *)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; byte *ptrB = (byte *)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; byte *ptrO = (byte *)outputData.Scan0 + y * outputData.Stride + x * 3; float aB = *(ptrA + 0); float aG = *(ptrA + 1); float aR = *(ptrA + 2); float bB = *(ptrB + 0); float bG = *(ptrB + 1); float bR = *(ptrB + 2); float layerDiff = layer - l0; // Interpolate between the two selected textures *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); } } for (int i = 0; i < 4; i++) { detailTexture[i].UnlockBits(datas[i]); detailTexture[i].Dispose(); } } layermap = null; output.UnlockBits(outputData); // We generated the texture upside down, so flip it output.RotateFlip(RotateFlipType.RotateNoneFlipY); #endregion Texture Compositing return(output); }
private void RezScriptHandler(Packet packet, LLAgent agent) { RezScriptPacket rez = (RezScriptPacket)packet; LLInventoryTaskItem scriptItem; ISceneEntity targetObj; if (m_scene.TryGetEntity(rez.UpdateBlock.ObjectLocalID, out targetObj) && targetObj is LLPrimitive) { LLPrimitive targetPrim = (LLPrimitive)targetObj; if (rez.InventoryBlock.ItemID != UUID.Zero) { if (targetPrim.Inventory.TryGetItem(rez.InventoryBlock.ItemID, out scriptItem)) { // Rezzing a script from task inventory UUID assetID = UUID.Combine(rez.InventoryBlock.TransactionID, agent.SecureSessionID); // Update task inventory with the new script source assetID scriptItem.AssetID = assetID; targetPrim.Inventory.AddOrUpdateItem(scriptItem, true); // Run the script if (m_scriptEngine != null) { m_scriptEngine.RezScript(scriptItem.ID, assetID, targetObj, 0); } else { m_log.Warn("Can't rez script in prim " + targetObj.ID + " without an ILSLScriptEngine"); } SignalTaskInventoryChange(agent, targetPrim); } else if (m_inventory != null) { InventoryBase obj; if (m_inventory.TryGetInventory(agent.ID, rez.InventoryBlock.ItemID, out obj) && obj is InventoryItem && ((InventoryItem)obj).ContentType == "application/vnd.ll.lsltext") { LLInventoryItem sourceItem = new LLInventoryItem((InventoryItem)obj); // Rezzing a script from agent inventory scriptItem = new LLInventoryTaskItem(); scriptItem.AssetID = sourceItem.AssetID; scriptItem.ContentType = "application/vnd.ll.lsltext"; scriptItem.CreationDate = DateTime.UtcNow; scriptItem.CreatorID = agent.ID; scriptItem.Description = sourceItem.Description; scriptItem.ID = UUID.Random(); scriptItem.Name = sourceItem.Name; scriptItem.OwnerID = sourceItem.OwnerID; scriptItem.ParentID = sourceItem.ParentID; scriptItem.ParentObjectID = targetPrim.ID; scriptItem.Flags = sourceItem.Flags; scriptItem.GroupID = sourceItem.GroupID; scriptItem.GroupOwned = sourceItem.GroupOwned; scriptItem.Permissions = sourceItem.Permissions; scriptItem.SalePrice = sourceItem.SalePrice; scriptItem.SaleType = sourceItem.SaleType; targetPrim.Inventory.AddOrUpdateItem(scriptItem, false); m_log.Info(agent.Name + " copied agent inventory script to task inventory: " + scriptItem.Name); // Run the script if (m_scriptEngine != null) { m_scriptEngine.RezScript(scriptItem.ID, scriptItem.AssetID, targetObj, 0); } else { m_log.Warn("Can't rez script in prim " + targetObj.ID + " without an ILSLScriptEngine"); } SignalTaskInventoryChange(agent, targetPrim); } else { m_log.Warn(agent.Name + " called RezScript for unknown inventory script " + rez.InventoryBlock.ItemID); } } else { m_log.Warn(agent.Name + "attempted to copy (and rez) script " + rez.InventoryBlock.ItemID + " to task inventory, but we have no IInventoryClient"); } } else { // Rezzing a new script scriptItem = new LLInventoryTaskItem(); scriptItem.AssetID = DEFAULT_SCRIPT; scriptItem.ContentType = "application/vnd.ll.lsltext"; scriptItem.CreationDate = DateTime.UtcNow; scriptItem.CreatorID = agent.ID; scriptItem.Description = String.Empty; scriptItem.ID = UUID.Random(); scriptItem.Name = "New script"; scriptItem.OwnerID = agent.ID; scriptItem.ParentID = rez.InventoryBlock.FolderID; scriptItem.ParentObjectID = targetPrim.ID; scriptItem.Permissions = GetDefaultPermissions(); scriptItem.SalePrice = 10; scriptItem.SaleType = SaleType.Not; targetPrim.Inventory.AddOrUpdateItem(scriptItem, false); m_log.Info(agent.Name + " created new task inventory script: " + scriptItem.Name); // Run the script if (m_scriptEngine != null) { m_scriptEngine.RezScript(scriptItem.ID, scriptItem.AssetID, targetObj, 0); } else { m_log.Warn("Can't rez script in prim " + targetObj.ID + " without an ILSLScriptEngine"); } SignalTaskInventoryChange(agent, targetPrim); } } else { m_log.Warn(agent.Name + "sent a RezScript packet referencing unknown object " + rez.UpdateBlock.ObjectLocalID); } }
private Color4 GetFaceColor(Primitive.TextureEntryFace face) { Color4 color; if (face.TextureID == UUID.Zero) { return(face.RGBA); } if (!m_colors.TryGetValue(face.TextureID, out color)) { bool fetched = false; // Attempt to fetch the texture metadata UUID metadataID = UUID.Combine(face.TextureID, TEXTURE_METADATA_MAGIC); AssetBase metadata = m_scene.AssetService.GetCached(metadataID.ToString()); if (metadata != null) { OSDMap map = null; try { map = OSDParser.Deserialize(metadata.Data) as OSDMap; } catch { } if (map != null) { color = map["X-JPEG2000-RGBA"].AsColor4(); fetched = true; } } if (!fetched) { // Fetch the texture, decode and get the average color, // then save it to a temporary metadata asset AssetBase textureAsset = m_scene.AssetService.Get(face.TextureID.ToString()); if (textureAsset != null) { int width, height; color = GetAverageColor(textureAsset.FullID, textureAsset.Data, out width, out height); OSDMap data = new OSDMap { { "X-JPEG2000-RGBA", OSD.FromColor4(color) } }; metadata = new AssetBase { Data = System.Text.Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(data)), Description = "Metadata for JPEG2000 texture " + face.TextureID.ToString(), Flags = AssetFlags.Collectable, FullID = metadataID, ID = metadataID.ToString(), Local = true, Temporary = true, Name = String.Empty, Type = (sbyte)AssetType.Unknown }; m_scene.AssetService.Store(metadata); } else { color = new Color4(0.5f, 0.5f, 0.5f, 1.0f); } } m_colors[face.TextureID] = color; } return(color * face.RGBA); }
/// <summary> /// Builds a composited terrain texture given the region texture /// and heightmap settings /// </summary> /// <param name="heightmap">Terrain heightmap</param> /// <param name="regionInfo">Region information including terrain texture parameters</param> /// <returns>A composited 256x256 RGB texture ready for rendering</returns> /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting /// </remarks> public static Bitmap Splat(float[] heightmap, UUID[] textureIDs, float[] startHeights, float[] heightRanges, Vector3d regionPosition, IAssetClient assetClient) { Debug.Assert(heightmap.Length == 256 * 256); Debug.Assert(textureIDs.Length == 4); Debug.Assert(startHeights.Length == 4); Debug.Assert(heightRanges.Length == 4); // Swap empty terrain textureIDs with default IDs for (int i = 0; i < textureIDs.Length; i++) { if (textureIDs[i] == UUID.Zero) { textureIDs[i] = DEFAULT_TERRAIN_DETAIL[i]; } } #region Texture Fetching Bitmap[] detailTexture = new Bitmap[4]; if (assetClient != null) { for (int i = 0; i < 4; i++) { Asset asset; UUID cacheID = UUID.Combine(TEXTURE_CACHE_MAGIC, textureIDs[i]); // Try to fetch a cached copy of the decoded/resized version of this texture if (assetClient.TryGetCachedAsset(cacheID, "image/png", out asset)) { try { using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) detailTexture[i] = (Bitmap)Image.FromStream(stream); } catch (Exception ex) { m_log.Warn("Failed to decode cached terrain texture " + cacheID + " (textureID: " + textureIDs[i] + "): " + ex.Message); } } if (detailTexture[i] == null) { // Try to fetch the original JPEG2000 texture, resize if needed, and cache as PNG if (assetClient.TryGetAsset(textureIDs[i], "image/x-j2c", out asset)) { try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } catch (Exception ex) { m_log.Warn("Failed to decode terrain texture " + asset.ID + ": " + ex.Message); } } if (detailTexture[i] != null) { Bitmap bitmap = detailTexture[i]; // Make sure this texture is the correct size, otherwise resize if (bitmap.Width != 256 || bitmap.Height != 256) { bitmap = Util.ResizeImage(bitmap, 256, 256); } // Save the decoded and resized texture to the cache byte[] data; using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); data = stream.ToArray(); } assetClient.StoreAsset( new Asset { ContentType = "image/png", CreationDate = DateTime.UtcNow, CreatorID = UUID.Zero, Data = data, ID = cacheID, Local = true, Temporary = true } ); } } } } // Fill in any missing textures with a solid color for (int i = 0; i < 4; i++) { if (detailTexture[i] == null) { // Create a solid color texture for this layer detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); using (Graphics gfx = Graphics.FromImage(detailTexture[i])) { using (SolidBrush brush = new SolidBrush(DEFAULT_TERRAIN_COLOR[i])) gfx.FillRectangle(brush, 0, 0, 256, 256); } } } #endregion Texture Fetching #region Layer Map float[] layermap = new float[256 * 256]; for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { float height = heightmap[y * 256 + x]; float pctX = (float)x / 255f; float pctY = (float)y / 255f; // Use bilinear interpolation between the four corners of start height and // height range to select the current values at this position float startHeight = Util.Bilinear( startHeights[0], startHeights[2], startHeights[1], startHeights[3], pctX, pctY); startHeight = Utils.Clamp(startHeight, 0f, 255f); float heightRange = Util.Bilinear( heightRanges[0], heightRanges[2], heightRanges[1], heightRanges[3], pctX, pctY); heightRange = Utils.Clamp(heightRange, 0f, 255f); // Generate two frequencies of perlin noise based on our global position // The magic values were taken from http://opensimulator.org/wiki/Terrain_Splatting Vector3 vec = new Vector3 ( ((float)regionPosition.X + x) * 0.20319f, ((float)regionPosition.Y + y) * 0.20319f, height * 0.25f ); float lowFreq = Perlin.noise2(vec.X * 0.222222f, vec.Y * 0.222222f) * 6.5f; float highFreq = Perlin.turbulence2(vec.X, vec.Y, 2f) * 2.25f; float noise = (lowFreq + highFreq) * 2f; // Combine the current height, generated noise, start height, and height range parameters, then scale all of it float layer = ((height + noise - startHeight) / heightRange) * 4f; if (Single.IsNaN(layer)) { layer = 0f; } layermap[y * 256 + x] = Utils.Clamp(layer, 0f, 3f); } } #endregion Layer Map #region Texture Compositing Bitmap output = new Bitmap(256, 256, PixelFormat.Format24bppRgb); BitmapData outputData = output.LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); unsafe { // Get handles to all of the texture data arrays BitmapData[] datas = new BitmapData[] { detailTexture[0].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[0].PixelFormat), detailTexture[1].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[1].PixelFormat), detailTexture[2].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[2].PixelFormat), detailTexture[3].LockBits(new Rectangle(0, 0, 256, 256), ImageLockMode.ReadOnly, detailTexture[3].PixelFormat) }; int[] comps = new int[] { (datas[0].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[1].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[2].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3, (datas[3].PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3 }; for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { float layer = layermap[y * 256 + x]; // Select two textures int l0 = (int)Math.Floor(layer); int l1 = Math.Min(l0 + 1, 3); byte *ptrA = (byte *)datas[l0].Scan0 + y * datas[l0].Stride + x * comps[l0]; byte *ptrB = (byte *)datas[l1].Scan0 + y * datas[l1].Stride + x * comps[l1]; byte *ptrO = (byte *)outputData.Scan0 + y * outputData.Stride + x * 3; float aB = *(ptrA + 0); float aG = *(ptrA + 1); float aR = *(ptrA + 2); float bB = *(ptrB + 0); float bG = *(ptrB + 1); float bR = *(ptrB + 2); float layerDiff = layer - l0; // Interpolate between the two selected textures *(ptrO + 0) = (byte)Math.Floor(aB + layerDiff * (bB - aB)); *(ptrO + 1) = (byte)Math.Floor(aG + layerDiff * (bG - aG)); *(ptrO + 2) = (byte)Math.Floor(aR + layerDiff * (bR - aR)); } } for (int i = 0; i < 4; i++) { detailTexture[i].UnlockBits(datas[i]); } } output.UnlockBits(outputData); // We generated the texture upside down, so flip it output.RotateFlip(RotateFlipType.RotateNoneFlipY); #endregion Texture Compositing return(output); }