diff --git a/OpenSim/Framework/Communications/Cache/AssetCache.cs b/OpenSim/Framework/Communications/Cache/AssetCache.cs index a950f51b0e..4c18744e9b 100644 --- a/OpenSim/Framework/Communications/Cache/AssetCache.cs +++ b/OpenSim/Framework/Communications/Cache/AssetCache.cs @@ -42,6 +42,8 @@ namespace OpenSim.Framework.Communications.Cache { public delegate void DownloadComplete(AssetCache.TextureSender sender); + public delegate void AssetRequestCallback(LLUUID assetID, AssetBase asset); + /// /// Manages local cache of assets and their sending to viewers. /// @@ -63,6 +65,8 @@ namespace OpenSim.Framework.Communications.Cache private Dictionary> TimesTextureSent = new Dictionary>(); + public Dictionary RequestLists = new Dictionary(); + private IAssetServer _assetServer; private Thread _assetCacheThread; @@ -123,6 +127,46 @@ namespace OpenSim.Framework.Communications.Cache return asset; } + public void GetAsset(LLUUID assetID, AssetRequestCallback callback) + { + AssetBase asset = null; + if (this.Textures.ContainsKey(assetID)) + { + asset = this.Textures[assetID]; + } + else if (this.Assets.ContainsKey(assetID)) + { + asset = this.Assets[assetID]; + } + + if (asset != null) + { + callback(assetID, asset); + } + else + { + NewAssetRequest req = new NewAssetRequest(assetID, callback); + if (this.RequestLists.ContainsKey(assetID)) + { + lock (RequestLists) + { + RequestLists[assetID].Requests.Add(req); + } + } + else + { + AssetRequestsList reqList = new AssetRequestsList(assetID); + reqList.Requests.Add(req); + lock (RequestLists) + { + RequestLists.Add(assetID, reqList); + } + } + this._assetServer.FetchAsset(assetID, false); + } + } + + public AssetBase GetAsset(LLUUID assetID, bool isTexture) { AssetBase asset = GetAsset(assetID); @@ -135,7 +179,7 @@ namespace OpenSim.Framework.Communications.Cache public void AddAsset(AssetBase asset) { - // System.Console.WriteLine("adding asset " + asset.FullID.ToStringHyphenated()); + //System.Console.WriteLine("adding asset " + asset.FullID.ToStringHyphenated()); if (asset.Type == 0) { //Console.WriteLine("which is a texture"); @@ -207,26 +251,7 @@ namespace OpenSim.Framework.Communications.Cache while (true) { TextureSender sender = this.QueueTextures.Dequeue(); - /* if (TimesTextureSent.ContainsKey(sender.request.RequestUser.AgentId)) - { - if (TimesTextureSent[sender.request.RequestUser.AgentId].ContainsKey(sender.request.ImageInfo.FullID)) - { - TimesTextureSent[sender.request.RequestUser.AgentId][sender.request.ImageInfo.FullID]++; - } - else - { - TimesTextureSent[sender.request.RequestUser.AgentId].Add(sender.request.ImageInfo.FullID, 1); - } - } - else - { - Dictionary UsersSent = new Dictionary(); - TimesTextureSent.Add(sender.request.RequestUser.AgentId, UsersSent ); - UsersSent.Add(sender.request.ImageInfo.FullID, 1); - - } - if (TimesTextureSent[sender.request.RequestUser.AgentId][sender.request.ImageInfo.FullID] < 1000) - {*/ + bool finished = sender.SendTexture(); if (finished) { @@ -237,11 +262,7 @@ namespace OpenSim.Framework.Communications.Cache // Console.WriteLine("readding texture"); this.QueueTextures.Enqueue(sender); } - /* } - else - { - this.TextureSent(sender); - }*/ + } } @@ -317,6 +338,21 @@ namespace OpenSim.Framework.Communications.Cache } } } + + if (RequestLists.ContainsKey(asset.FullID)) + { + AssetRequestsList reqList = RequestLists[asset.FullID]; + foreach (NewAssetRequest req in reqList.Requests) + { + req.Callback(asset.FullID, asset); + } + + lock (RequestLists) + { + RequestLists.Remove(asset.FullID); + reqList.Requests.Clear(); + } + } } } @@ -508,17 +544,6 @@ namespace OpenSim.Framework.Communications.Cache } } - - public AssetInfo CloneAsset(LLUUID newOwner, AssetInfo sourceAsset) - { - AssetInfo newAsset = new AssetInfo(); - newAsset.Data = new byte[sourceAsset.Data.Length]; - Array.Copy(sourceAsset.Data, newAsset.Data, sourceAsset.Data.Length); - newAsset.FullID = LLUUID.Random(); - newAsset.Type = sourceAsset.Type; - newAsset.InvType = sourceAsset.InvType; - return (newAsset); - } #endregion #region Textures @@ -529,7 +554,7 @@ namespace OpenSim.Framework.Communications.Cache /// public void AddTextureRequest(IClientAPI userInfo, LLUUID imageID, uint packetNumber, int discard) { - //Console.WriteLine("texture request for " + imageID.ToStringHyphenated() + " packetnumber= " + packetNumber); + // System.Console.WriteLine("texture request for " + imageID.ToStringHyphenated() + " packetnumber= " + packetNumber); //check to see if texture is in local cache, if not request from asset server if (!this.AvatarRecievedTextures.ContainsKey(userInfo.AgentId)) { @@ -540,6 +565,7 @@ namespace OpenSim.Framework.Communications.Cache //Console.WriteLine(userInfo.AgentId +" is requesting a image( "+ imageID+" that has already been sent to them"); return; }*/ + if (!this.Textures.ContainsKey(imageID)) { if (!this.RequestedTextures.ContainsKey(imageID)) @@ -556,7 +582,7 @@ namespace OpenSim.Framework.Communications.Cache return; } - //Console.WriteLine("texture already in cache"); + // System.Console.WriteLine("texture already in cache"); TextureImage imag = this.Textures[imageID]; AssetRequest req = new AssetRequest(); req.RequestUser = userInfo; @@ -583,46 +609,9 @@ namespace OpenSim.Framework.Communications.Cache this.TextureRequests.Add(req); } - public TextureImage CloneImage(LLUUID newOwner, TextureImage source) - { - TextureImage newImage = new TextureImage(); - newImage.Data = new byte[source.Data.Length]; - Array.Copy(source.Data, newImage.Data, source.Data.Length); - //newImage.filename = source.filename; - newImage.FullID = LLUUID.Random(); - newImage.Name = source.Name; - return (newImage); - } + #endregion - private IAssetServer LoadAssetDll(string dllName) - { - Assembly pluginAssembly = Assembly.LoadFrom(dllName); - IAssetServer server = null; - - foreach (Type pluginType in pluginAssembly.GetTypes()) - { - if (pluginType.IsPublic) - { - if (!pluginType.IsAbstract) - { - Type typeInterface = pluginType.GetInterface("IAssetPlugin", true); - - if (typeInterface != null) - { - IAssetPlugin plug = (IAssetPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); - server = plug.GetAssetServer(); - break; - } - - typeInterface = null; - } - } - } - pluginAssembly = null; - return server; - } - public class AssetRequest { public IClientAPI RequestUser; @@ -779,4 +768,29 @@ namespace OpenSim.Framework.Communications.Cache } } } + + public class AssetRequestsList + { + public LLUUID AssetID; + public List Requests = new List(); + + public AssetRequestsList(LLUUID assetID) + { + AssetID = assetID; + } + } + + public class NewAssetRequest + { + public LLUUID AssetID; + public AssetRequestCallback Callback; + + public NewAssetRequest(LLUUID assetID, AssetRequestCallback callback) + { + AssetID = assetID; + Callback = callback; + } + + + } } diff --git a/OpenSim/Framework/General/Interfaces/IClientAPI.cs b/OpenSim/Framework/General/Interfaces/IClientAPI.cs index 7cb18e5459..8aae3c2224 100644 --- a/OpenSim/Framework/General/Interfaces/IClientAPI.cs +++ b/OpenSim/Framework/General/Interfaces/IClientAPI.cs @@ -136,6 +136,33 @@ namespace OpenSim.Framework.Interfaces } } + public class TextureRequestArgs : EventArgs + { + protected LLUUID m_requestedAssetID; + private sbyte m_discardLevel; + private uint m_packetNumber; + + public uint PacketNumber + { + get { return m_packetNumber; } + set { m_packetNumber = value; } + } + + public sbyte DiscardLevel + { + get { return m_discardLevel; } + set { m_discardLevel = value; } + } + + public LLUUID RequestedAssetID + { + get { return m_requestedAssetID; } + set { m_requestedAssetID = value; } + } + } + + public delegate void TextureRequest(Object sender, TextureRequestArgs e); + public delegate void ImprovedInstantMessage(LLUUID fromAgentID, LLUUID fromAgentSession, LLUUID toAgentID, LLUUID imSessionID, uint timestamp, string fromAgentName, string message, byte dialog); // Cut down from full list public delegate void RezObject(IClientAPI remoteClient, LLUUID itemID, LLVector3 pos); public delegate void ModifyTerrain(float height, float seconds, byte size, byte action, float north, float west, IClientAPI remoteClient); @@ -204,6 +231,7 @@ namespace OpenSim.Framework.Interfaces { event ImprovedInstantMessage OnInstantMessage; event ChatFromViewer OnChatFromViewer; + event TextureRequest OnRequestTexture; event RezObject OnRezObject; event ModifyTerrain OnModifyTerrain; event SetAppearance OnSetAppearance; diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs index bb26caec46..8ea9347bad 100644 --- a/OpenSim/Region/Application/OpenSimMain.cs +++ b/OpenSim/Region/Application/OpenSimMain.cs @@ -149,11 +149,6 @@ namespace OpenSim config.Set("asset_database", "sqlite"); - // wtf? - config.Set("default_modules", true); - config.Set("default_shared_modules", true); - config.Set("except_modules", ""); - config.Set("except_shared_modules", ""); } if (m_config.Configs["StandAlone"] == null) @@ -195,6 +190,7 @@ namespace OpenSim m_networkServersInfo = new NetworkServersInfo(); IConfig startupConfig = m_config.Configs["Startup"]; + if (startupConfig != null) { m_sandbox = !startupConfig.GetBoolean("gridmode", false); diff --git a/OpenSim/Region/ClientStack/ClientView.API.cs b/OpenSim/Region/ClientStack/ClientView.API.cs index 74f1824ee4..ba8bf02fb2 100644 --- a/OpenSim/Region/ClientStack/ClientView.API.cs +++ b/OpenSim/Region/ClientStack/ClientView.API.cs @@ -46,6 +46,7 @@ namespace OpenSim.Region.ClientStack public event ViewerEffectEventHandler OnViewerEffect; public event ImprovedInstantMessage OnInstantMessage; public event ChatFromViewer OnChatFromViewer; + public event TextureRequest OnRequestTexture; public event RezObject OnRezObject; public event GenericCall4 OnDeRezObject; public event ModifyTerrain OnModifyTerrain; diff --git a/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs b/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs index 65a0e44656..8a1a5202d0 100644 --- a/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs +++ b/OpenSim/Region/ClientStack/ClientView.ProcessPackets.cs @@ -210,7 +210,7 @@ namespace OpenSim.Region.ClientStack case PacketType.AgentSit: if (OnAgentSit != null) { - AgentSitPacket agentSit = (AgentSitPacket) Pack; + AgentSitPacket agentSit = (AgentSitPacket)Pack; OnAgentSit(this, agentSit.AgentData.AgentID); } break; @@ -364,7 +364,17 @@ namespace OpenSim.Region.ClientStack for (int i = 0; i < imageRequest.RequestImage.Length; i++) { - // Console.WriteLine("image request of "+ imageRequest.RequestImage[i].Image+ " at discard level " + imageRequest.RequestImage[i].DiscardLevel); + // still working on the Texture download module so for now using old method + // TextureRequestArgs args = new TextureRequestArgs(); + // args.RequestedAssetID = imageRequest.RequestImage[i].Image; + // args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel; + // args.PacketNumber = imageRequest.RequestImage[i].Packet; + + // if (OnRequestTexture != null) + // { + // OnRequestTexture(this, args); + // } + m_assetCache.AddTextureRequest(this, imageRequest.RequestImage[i].Image, imageRequest.RequestImage[i].Packet, imageRequest.RequestImage[i].DiscardLevel); } break; diff --git a/OpenSim/Region/Environment/ModuleLoader.cs b/OpenSim/Region/Environment/ModuleLoader.cs index 160b740e0b..442ee77f87 100644 --- a/OpenSim/Region/Environment/ModuleLoader.cs +++ b/OpenSim/Region/Environment/ModuleLoader.cs @@ -79,6 +79,9 @@ namespace OpenSim.Region.Environment AvatarFactoryModule avatarFactory = new AvatarFactoryModule(); LoadedSharedModules.Add(avatarFactory.Name, avatarFactory); + + //TextureDownloadModule textureModule = new TextureDownloadModule(); + //LoadedSharedModules.Add(textureModule.Name, textureModule); } public void InitialiseSharedModules(Scene scene) diff --git a/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs b/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs index 440d948e43..3ce3e4edb1 100644 --- a/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs +++ b/OpenSim/Region/Environment/Modules/AssetDownloadModule.cs @@ -62,7 +62,7 @@ namespace OpenSim.Region.Environment.Modules public bool IsSharedModule { - get { return false; } + get { return true; } } public void NewClient(IClientAPI client) diff --git a/OpenSim/Region/Environment/Modules/InstantMessageModule.cs b/OpenSim/Region/Environment/Modules/InstantMessageModule.cs index 7c4e2c8dc6..77ff24b606 100644 --- a/OpenSim/Region/Environment/Modules/InstantMessageModule.cs +++ b/OpenSim/Region/Environment/Modules/InstantMessageModule.cs @@ -39,14 +39,17 @@ namespace OpenSim.Region.Environment.Modules private List m_scenes = new List(); private LogBase m_log; + public InstantMessageModule() + { + m_log = OpenSim.Framework.Console.MainLog.Instance; + } + public void Initialise(Scene scene, IConfigSource config) { if (!m_scenes.Contains(scene)) { m_scenes.Add(scene); - - scene.EventManager.OnNewClient += OnNewClient; - m_log = OpenSim.Framework.Console.MainLog.Instance; + scene.EventManager.OnNewClient += OnNewClient; } } @@ -69,9 +72,11 @@ namespace OpenSim.Region.Environment.Modules { // Local Message ScenePresence user = (ScenePresence)m_scene.Entities[toAgentID]; - user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, - toAgentID, imSessionID, user.Firstname + " " + user.Lastname, dialog, timestamp); - + if (!user.IsChildAgent) + { + user.ControllingClient.SendInstantMessage(fromAgentID, fromAgentSession, message, + toAgentID, imSessionID, fromAgentName, dialog, timestamp); + } // Message sent return; } diff --git a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs index d3297c84fe..56e20d118e 100644 --- a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs +++ b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs @@ -25,9 +25,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ - +using System; +using System.Collections.Generic; +using System.Threading; using libsecondlife; +using libsecondlife.Packets; using OpenSim.Framework.Interfaces; +using OpenSim.Framework.Types; +using OpenSim.Framework.Utilities; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes; using Nini.Config; @@ -37,15 +42,28 @@ namespace OpenSim.Region.Environment.Modules public class TextureDownloadModule : IRegionModule { private Scene m_scene; + private List m_scenes = new List(); + private Dictionary> ClientRequests = new Dictionary>(); + + private BlockingQueue QueueSenders = new BlockingQueue(); + private Dictionary> InProcess = new Dictionary>(); + // private Thread m_thread; public TextureDownloadModule() { + // m_thread = new Thread(new ThreadStart(ProcessTextureSenders)); + // m_thread.IsBackground = true; + // m_thread.Start(); } public void Initialise(Scene scene, IConfigSource config) { - m_scene = scene; - m_scene.EventManager.OnNewClient += NewClient; + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + } } public void PostInitialise() @@ -63,15 +81,184 @@ namespace OpenSim.Region.Environment.Modules public bool IsSharedModule { - get { return false; } + get { return true; } } public void NewClient(IClientAPI client) { + /* lock (ClientRequests) + { + if (!ClientRequests.ContainsKey(client.AgentId)) + { + ClientRequests.Add(client.AgentId, new Dictionary()); + InProcess.Add(client.AgentId, new List()); + } + } + client.OnRequestTexture += TextureRequest; + */ } - public void TextureAssetCallback(LLUUID texture, byte[] data) + public void TextureCallback(LLUUID textureID, AssetBase asset) { + lock (ClientRequests) + { + foreach (Dictionary reqList in ClientRequests.Values) + { + if (reqList.ContainsKey(textureID)) + { + //check the texture isn't already in the process of being sent to the client. + if (!InProcess[reqList[textureID].RequestUser.AgentId].Contains(textureID)) + { + TextureSender sender = new TextureSender(reqList[textureID], asset); + QueueSenders.Enqueue(sender); + InProcess[reqList[textureID].RequestUser.AgentId].Add(textureID); + reqList.Remove(textureID); + } + } + } + } } + + public void TextureRequest(Object sender, TextureRequestArgs e) + { + IClientAPI client = (IClientAPI)sender; + if (!ClientRequests[client.AgentId].ContainsKey(e.RequestedAssetID)) + { + lock (ClientRequests) + { + AssetRequest request = new AssetRequest(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber); + ClientRequests[client.AgentId].Add(e.RequestedAssetID, request); + } + m_scene.commsManager.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback); + } + } + + public void ProcessTextureSenders() + { + while (true) + { + TextureSender sender = this.QueueSenders.Dequeue(); + bool finished = sender.SendTexture(); + if (finished) + { + this.TextureSent(sender); + } + else + { + this.QueueSenders.Enqueue(sender); + } + } + } + + private void TextureSent(TextureSender sender) + { + if (InProcess[sender.request.RequestUser.AgentId].Contains(sender.request.RequestAssetID)) + { + InProcess[sender.request.RequestUser.AgentId].Remove(sender.request.RequestAssetID); + } + } + + public class TextureSender + { + public AssetRequest request; + private int counter = 0; + private AssetBase m_asset; + public long DataPointer = 0; + public int NumPackets = 0; + public int PacketCounter = 0; + + public TextureSender(AssetRequest req, AssetBase asset) + { + request = req; + m_asset = asset; + + if (asset.Data.LongLength > 600) + { + NumPackets = 2 + (int)(asset.Data.Length - 601) / 1000; + } + else + { + NumPackets = 1; + } + + PacketCounter = (int) req.PacketNumber; + } + + public bool SendTexture() + { + SendPacket(); + counter++; + if ((PacketCounter >= NumPackets) | counter > 100 | (NumPackets == 1) | (request.DiscardLevel == -1)) + { + return true; + } + return false; + } + + public void SendPacket() + { + AssetRequest req = request; + if (PacketCounter == 0) + { + if (NumPackets == 1) + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = 1; + im.ImageID.ID = m_asset.FullID; + im.ImageID.Size = (uint)m_asset.Data.Length; + im.ImageData.Data = m_asset.Data; + im.ImageID.Codec = 2; + req.RequestUser.OutPacket(im); + PacketCounter++; + } + else + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = (ushort)(NumPackets); + im.ImageID.ID = m_asset.FullID; + im.ImageID.Size = (uint)m_asset.Data.Length; + im.ImageData.Data = new byte[600]; + Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600); + im.ImageID.Codec = 2; + req.RequestUser.OutPacket(im); + PacketCounter++; + } + } + else + { + ImagePacketPacket im = new ImagePacketPacket(); + im.Header.Reliable = false; + im.ImageID.Packet = (ushort)(PacketCounter); + im.ImageID.ID = m_asset.FullID; + int size = m_asset.Data.Length - 600 - (1000 * (PacketCounter - 1)); + if (size > 1000) size = 1000; + im.ImageData.Data = new byte[size]; + Array.Copy(m_asset.Data, 600 + (1000 * (PacketCounter - 1)), im.ImageData.Data, 0, size); + req.RequestUser.OutPacket(im); + PacketCounter++; + } + + } + + } + + public class AssetRequest + { + public IClientAPI RequestUser; + public LLUUID RequestAssetID; + public int DiscardLevel = -1; + public uint PacketNumber = 0; + + public AssetRequest(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber) + { + RequestUser = client; + RequestAssetID = textureID; + DiscardLevel = discardLevel; + PacketNumber = packetNumber; + } + } + } } diff --git a/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/WorldCommModule.cs index cf5bba3613..c7e0f8fe83 100644 --- a/OpenSim/Region/Environment/Modules/WorldCommModule.cs +++ b/OpenSim/Region/Environment/Modules/WorldCommModule.cs @@ -87,13 +87,11 @@ namespace OpenSim.Region.Environment.Modules public void Initialise(Scene scene, IConfigSource config) { - m_scene = scene; m_scene.RegisterModuleInterface(this); m_listenerManager = new ListenerManager(); m_pending = new Queue(); m_scene.EventManager.OnNewClient += NewClient; - } public void PostInitialise() diff --git a/OpenSim/Region/Environment/Scenes/SceneManager.cs b/OpenSim/Region/Environment/Scenes/SceneManager.cs index 7db6927919..76ff6cf97a 100644 --- a/OpenSim/Region/Environment/Scenes/SceneManager.cs +++ b/OpenSim/Region/Environment/Scenes/SceneManager.cs @@ -274,6 +274,23 @@ namespace OpenSim.Region.Environment.Scenes return false; } + public bool TryGetAvatarsScene(LLUUID avatarId, out Scene scene) + { + ScenePresence avatar = null; + foreach (Scene mScene in m_localScenes) + { + if (mScene.TryGetAvatar(avatarId, out avatar)) + { + scene = mScene; + return true; + } + } + + scene = null; + return false; + } + + public void CloseScene(Scene scene) { m_localScenes.Remove(scene); diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 58d2157694..a0d1d2a5af 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -125,7 +125,7 @@ namespace OpenSim.Region.Environment.Scenes set { m_name = value; } } - protected LLObject.ObjectFlags m_flags; + protected LLObject.ObjectFlags m_flags =0; public uint ObjectFlags { @@ -133,7 +133,7 @@ namespace OpenSim.Region.Environment.Scenes set { m_flags = (LLObject.ObjectFlags) value; } } - protected LLObject.MaterialType m_material; + protected LLObject.MaterialType m_material =0; public byte Material { diff --git a/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs index 7962698cdb..b935f24d1e 100644 --- a/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleApp/MyNpcCharacter.cs @@ -53,6 +53,7 @@ namespace SimpleApp public event ImprovedInstantMessage OnInstantMessage; public event ChatFromViewer OnChatFromViewer; + public event TextureRequest OnRequestTexture; public event RezObject OnRezObject; public event ModifyTerrain OnModifyTerrain; public event SetAppearance OnSetAppearance;