diff options
Diffstat (limited to '')
9 files changed, 400 insertions, 270 deletions
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs index defaa9c..582df22 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs | |||
@@ -1125,7 +1125,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice | |||
1125 | return null; | 1125 | return null; |
1126 | 1126 | ||
1127 | doc = new XmlDocument(); | 1127 | doc = new XmlDocument(); |
1128 | doc.XmlResolver = null; | ||
1129 | 1128 | ||
1130 | // Let's serialize all calls to Vivox. Most of these are driven by | 1129 | // Let's serialize all calls to Vivox. Most of these are driven by |
1131 | // the clients (CAPs), when the user arrives at the region. We don't | 1130 | // the clients (CAPs), when the user arrives at the region. We don't |
@@ -1147,10 +1146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice | |||
1147 | using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse()) | 1146 | using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse()) |
1148 | using (Stream s = rsp.GetResponseStream()) | 1147 | using (Stream s = rsp.GetResponseStream()) |
1149 | using (XmlTextReader rdr = new XmlTextReader(s)) | 1148 | using (XmlTextReader rdr = new XmlTextReader(s)) |
1150 | { | ||
1151 | rdr.ProhibitDtd = true; | ||
1152 | doc.Load(rdr); | 1149 | doc.Load(rdr); |
1153 | } | ||
1154 | } | 1150 | } |
1155 | catch (Exception e) | 1151 | catch (Exception e) |
1156 | { | 1152 | { |
diff --git a/OpenSim/Region/OptionalModules/DataSnapshot/DataRequestHandler.cs b/OpenSim/Region/OptionalModules/DataSnapshot/DataRequestHandler.cs index 50276ae..817170f 100644 --- a/OpenSim/Region/OptionalModules/DataSnapshot/DataRequestHandler.cs +++ b/OpenSim/Region/OptionalModules/DataSnapshot/DataRequestHandler.cs | |||
@@ -45,6 +45,7 @@ namespace OpenSim.Region.DataSnapshot | |||
45 | // private Scene m_scene = null; | 45 | // private Scene m_scene = null; |
46 | private DataSnapshotManager m_externalData = null; | 46 | private DataSnapshotManager m_externalData = null; |
47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
48 | private ExpiringCache<string, int> throotleGen = new ExpiringCache<string, int>(); | ||
48 | 49 | ||
49 | public DataRequestHandler(Scene scene, DataSnapshotManager externalData) | 50 | public DataRequestHandler(Scene scene, DataSnapshotManager externalData) |
50 | { | 51 | { |
@@ -52,29 +53,91 @@ namespace OpenSim.Region.DataSnapshot | |||
52 | m_externalData = externalData; | 53 | m_externalData = externalData; |
53 | 54 | ||
54 | //Register HTTP handler | 55 | //Register HTTP handler |
55 | if (MainServer.Instance.AddHTTPHandler("collector", OnGetSnapshot)) | 56 | if (MainServer.UnSecureInstance.AddHTTPHandler("collector", OnGetSnapshot)) |
56 | { | 57 | { |
57 | m_log.Info("[DATASNAPSHOT]: Set up snapshot service"); | 58 | m_log.Info("[DATASNAPSHOT]: Set up snapshot service"); |
58 | } | 59 | } |
59 | // Register validation callback handler | 60 | // Register validation callback handler |
60 | MainServer.Instance.AddHTTPHandler("validate", OnValidate); | 61 | MainServer.UnSecureInstance.AddHTTPHandler("validate", OnValidate); |
61 | 62 | ||
62 | } | 63 | } |
63 | 64 | ||
65 | private string GetClientString(Hashtable request) | ||
66 | { | ||
67 | string clientstring = ""; | ||
68 | if (!request.ContainsKey("headers")) | ||
69 | return clientstring; | ||
70 | |||
71 | Hashtable requestinfo = (Hashtable)request["headers"]; | ||
72 | if (requestinfo.ContainsKey("x-forwarded-for")) | ||
73 | { | ||
74 | object str = requestinfo["x-forwarded-for"]; | ||
75 | if (str != null) | ||
76 | { | ||
77 | if (!string.IsNullOrEmpty(str.ToString())) | ||
78 | { | ||
79 | return str.ToString(); | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | if (!requestinfo.ContainsKey("remote_addr")) | ||
84 | return clientstring; | ||
85 | |||
86 | object remote_addrobj = requestinfo["remote_addr"]; | ||
87 | if (remote_addrobj != null) | ||
88 | { | ||
89 | if (!string.IsNullOrEmpty(remote_addrobj.ToString())) | ||
90 | { | ||
91 | clientstring = remote_addrobj.ToString(); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | return clientstring; | ||
96 | } | ||
97 | |||
64 | public Hashtable OnGetSnapshot(Hashtable keysvals) | 98 | public Hashtable OnGetSnapshot(Hashtable keysvals) |
65 | { | 99 | { |
66 | m_log.Debug("[DATASNAPSHOT] Received collection request"); | ||
67 | Hashtable reply = new Hashtable(); | 100 | Hashtable reply = new Hashtable(); |
68 | int statuscode = 200; | 101 | string reqtag; |
69 | |||
70 | string snapObj = (string)keysvals["region"]; | 102 | string snapObj = (string)keysvals["region"]; |
103 | if(string.IsNullOrWhiteSpace(snapObj)) | ||
104 | reqtag = GetClientString(keysvals); | ||
105 | else | ||
106 | reqtag = snapObj + GetClientString(keysvals); | ||
107 | |||
108 | |||
109 | if(!string.IsNullOrWhiteSpace(reqtag)) | ||
110 | { | ||
111 | if(throotleGen.Contains(reqtag)) | ||
112 | { | ||
113 | reply["str_response_string"] = "Please try your request again later"; | ||
114 | reply["int_response_code"] = 503; | ||
115 | reply["content_type"] = "text/plain"; | ||
116 | m_log.Debug("[DATASNAPSHOT] Collection request spam. reply try later"); | ||
117 | return reply; | ||
118 | } | ||
119 | |||
120 | throotleGen.AddOrUpdate(reqtag, 0, 60); | ||
121 | } | ||
122 | |||
123 | if(string.IsNullOrWhiteSpace(snapObj)) | ||
124 | m_log.DebugFormat("[DATASNAPSHOT] Received collection request for all"); | ||
125 | else | ||
126 | m_log.DebugFormat("[DATASNAPSHOT] Received collection request for {0}", snapObj); | ||
71 | 127 | ||
72 | XmlDocument response = m_externalData.GetSnapshot(snapObj); | 128 | XmlDocument response = m_externalData.GetSnapshot(snapObj); |
129 | if(response == null) | ||
130 | { | ||
131 | reply["str_response_string"] = "Please try your request again later"; | ||
132 | reply["int_response_code"] = 503; | ||
133 | reply["content_type"] = "text/plain"; | ||
134 | m_log.Debug("[DATASNAPSHOT] Collection request spam. reply try later"); | ||
135 | return reply; | ||
136 | } | ||
73 | 137 | ||
74 | reply["str_response_string"] = response.OuterXml; | 138 | reply["str_response_string"] = response.OuterXml; |
75 | reply["int_response_code"] = statuscode; | 139 | reply["int_response_code"] = 200; |
76 | reply["content_type"] = "text/xml"; | 140 | reply["content_type"] = "text/xml"; |
77 | |||
78 | return reply; | 141 | return reply; |
79 | } | 142 | } |
80 | 143 | ||
diff --git a/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs index 0436f96..fd841d4 100644 --- a/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs +++ b/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs | |||
@@ -32,6 +32,7 @@ using System.IO; | |||
32 | using System.Linq; | 32 | using System.Linq; |
33 | using System.Net; | 33 | using System.Net; |
34 | using System.Reflection; | 34 | using System.Reflection; |
35 | using System.Threading; | ||
35 | using System.Text; | 36 | using System.Text; |
36 | using System.Xml; | 37 | using System.Xml; |
37 | using log4net; | 38 | using log4net; |
@@ -64,6 +65,7 @@ namespace OpenSim.Region.DataSnapshot | |||
64 | //Various internal objects | 65 | //Various internal objects |
65 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 66 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
66 | internal object m_syncInit = new object(); | 67 | internal object m_syncInit = new object(); |
68 | private object m_serializeGen = new object(); | ||
67 | 69 | ||
68 | //DataServices and networking | 70 | //DataServices and networking |
69 | private string m_dataServices = "noservices"; | 71 | private string m_dataServices = "noservices"; |
@@ -148,11 +150,8 @@ namespace OpenSim.Region.DataSnapshot | |||
148 | m_enabled = false; | 150 | m_enabled = false; |
149 | return; | 151 | return; |
150 | } | 152 | } |
151 | |||
152 | } | 153 | } |
153 | |||
154 | } | 154 | } |
155 | |||
156 | } | 155 | } |
157 | 156 | ||
158 | public void AddRegion(Scene scene) | 157 | public void AddRegion(Scene scene) |
@@ -160,23 +159,14 @@ namespace OpenSim.Region.DataSnapshot | |||
160 | if (!m_enabled) | 159 | if (!m_enabled) |
161 | return; | 160 | return; |
162 | 161 | ||
163 | m_log.DebugFormat("[DATASNAPSHOT]: Module added to Scene {0}.", scene.RegionInfo.RegionName); | 162 | m_scenes.Add(scene); |
164 | 163 | ||
165 | if (!m_servicesNotified) | 164 | if (m_snapStore == null) |
166 | { | 165 | { |
167 | m_hostname = scene.RegionInfo.ExternalHostName; | 166 | m_hostname = scene.RegionInfo.ExternalHostName; |
168 | m_snapStore = new SnapshotStore(m_snapsDir, m_gridinfo, m_listener_port, m_hostname); | 167 | m_snapStore = new SnapshotStore(m_snapsDir, m_gridinfo, m_listener_port, m_hostname); |
169 | |||
170 | //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer | ||
171 | new DataRequestHandler(scene, this); | ||
172 | |||
173 | if (m_dataServices != "" && m_dataServices != "noservices") | ||
174 | NotifyDataServices(m_dataServices, "online"); | ||
175 | |||
176 | m_servicesNotified = true; | ||
177 | } | 168 | } |
178 | 169 | ||
179 | m_scenes.Add(scene); | ||
180 | m_snapStore.AddScene(scene); | 170 | m_snapStore.AddScene(scene); |
181 | 171 | ||
182 | Assembly currentasm = Assembly.GetExecutingAssembly(); | 172 | Assembly currentasm = Assembly.GetExecutingAssembly(); |
@@ -201,7 +191,7 @@ namespace OpenSim.Region.DataSnapshot | |||
201 | } | 191 | } |
202 | } | 192 | } |
203 | } | 193 | } |
204 | 194 | m_log.DebugFormat("[DATASNAPSHOT]: Module added to Scene {0}.", scene.RegionInfo.RegionName); | |
205 | } | 195 | } |
206 | 196 | ||
207 | public void RemoveRegion(Scene scene) | 197 | public void RemoveRegion(Scene scene) |
@@ -244,8 +234,16 @@ namespace OpenSim.Region.DataSnapshot | |||
244 | if (!m_enabled) | 234 | if (!m_enabled) |
245 | return; | 235 | return; |
246 | 236 | ||
247 | m_log.DebugFormat("[DATASNAPSHOT]: Marking scene {0} as stale.", scene.RegionInfo.RegionName); | 237 | if (!m_servicesNotified) |
248 | m_snapStore.ForceSceneStale(scene); | 238 | { |
239 | //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer | ||
240 | new DataRequestHandler(scene, this); | ||
241 | |||
242 | if (m_dataServices != "" && m_dataServices != "noservices") | ||
243 | NotifyDataServices(m_dataServices, "online"); | ||
244 | |||
245 | m_servicesNotified = true; | ||
246 | } | ||
249 | } | 247 | } |
250 | 248 | ||
251 | public void Close() | 249 | public void Close() |
@@ -257,7 +255,6 @@ namespace OpenSim.Region.DataSnapshot | |||
257 | NotifyDataServices(m_dataServices, "offline"); | 255 | NotifyDataServices(m_dataServices, "offline"); |
258 | } | 256 | } |
259 | 257 | ||
260 | |||
261 | public string Name | 258 | public string Name |
262 | { | 259 | { |
263 | get { return "External Data Generator"; } | 260 | get { return "External Data Generator"; } |
@@ -319,8 +316,14 @@ namespace OpenSim.Region.DataSnapshot | |||
319 | /** | 316 | /** |
320 | * Reply to the http request | 317 | * Reply to the http request |
321 | */ | 318 | */ |
319 | |||
322 | public XmlDocument GetSnapshot(string regionName) | 320 | public XmlDocument GetSnapshot(string regionName) |
323 | { | 321 | { |
322 | if(!Monitor.TryEnter(m_serializeGen,30000)) | ||
323 | { | ||
324 | return null; | ||
325 | } | ||
326 | |||
324 | CheckStale(); | 327 | CheckStale(); |
325 | 328 | ||
326 | XmlDocument requestedSnap = new XmlDocument(); | 329 | XmlDocument requestedSnap = new XmlDocument(); |
@@ -360,9 +363,13 @@ namespace OpenSim.Region.DataSnapshot | |||
360 | m_log.Warn("[DATASNAPSHOT]: Caught unknown exception while trying to load snapshot: " + e.StackTrace); | 363 | m_log.Warn("[DATASNAPSHOT]: Caught unknown exception while trying to load snapshot: " + e.StackTrace); |
361 | requestedSnap = GetErrorMessage(regionName, e); | 364 | requestedSnap = GetErrorMessage(regionName, e); |
362 | } | 365 | } |
363 | 366 | finally | |
367 | { | ||
368 | Monitor.Exit(m_serializeGen); | ||
369 | } | ||
364 | 370 | ||
365 | return requestedSnap; | 371 | return requestedSnap; |
372 | |||
366 | } | 373 | } |
367 | 374 | ||
368 | private XmlDocument GetErrorMessage(string regionName, Exception e) | 375 | private XmlDocument GetErrorMessage(string regionName, Exception e) |
diff --git a/OpenSim/Region/OptionalModules/DataSnapshot/SnapshotStore.cs b/OpenSim/Region/OptionalModules/DataSnapshot/SnapshotStore.cs index 480aaaf..0ed421a 100644 --- a/OpenSim/Region/OptionalModules/DataSnapshot/SnapshotStore.cs +++ b/OpenSim/Region/OptionalModules/DataSnapshot/SnapshotStore.cs | |||
@@ -107,6 +107,7 @@ namespace OpenSim.Region.DataSnapshot | |||
107 | snapXWriter.WriteStartDocument(); | 107 | snapXWriter.WriteStartDocument(); |
108 | data.WriteTo(snapXWriter); | 108 | data.WriteTo(snapXWriter); |
109 | snapXWriter.WriteEndDocument(); | 109 | snapXWriter.WriteEndDocument(); |
110 | snapXWriter.Flush(); | ||
110 | } | 111 | } |
111 | } | 112 | } |
112 | catch (Exception e) | 113 | catch (Exception e) |
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs index e8cb052..c661268 100644 --- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs +++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs | |||
@@ -46,16 +46,10 @@ using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType; | |||
46 | 46 | ||
47 | using Ionic.Zlib; | 47 | using Ionic.Zlib; |
48 | 48 | ||
49 | // You will need to uncomment these lines if you are adding a region module to some other assembly which does not already | ||
50 | // specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans | ||
51 | // the available DLLs | ||
52 | //[assembly: Addin("MaterialsModule", "1.0")] | ||
53 | //[assembly: AddinDependency("OpenSim", "0.8.1")] | ||
54 | |||
55 | namespace OpenSim.Region.OptionalModules.Materials | 49 | namespace OpenSim.Region.OptionalModules.Materials |
56 | { | 50 | { |
57 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")] | 51 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")] |
58 | public class MaterialsModule : INonSharedRegionModule | 52 | public class MaterialsModule : INonSharedRegionModule, IMaterialsModule |
59 | { | 53 | { |
60 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
61 | 55 | ||
@@ -67,12 +61,12 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
67 | private Scene m_scene = null; | 61 | private Scene m_scene = null; |
68 | private bool m_enabled = false; | 62 | private bool m_enabled = false; |
69 | private int m_maxMaterialsPerTransaction = 50; | 63 | private int m_maxMaterialsPerTransaction = 50; |
64 | private object materialslock = new object(); | ||
70 | 65 | ||
71 | public Dictionary<UUID, OSDMap> m_Materials = new Dictionary<UUID, OSDMap>(); | 66 | public Dictionary<UUID, FaceMaterial> m_Materials = new Dictionary<UUID, FaceMaterial>(); |
72 | public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>(); | 67 | public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>(); |
73 | 68 | ||
74 | private Dictionary<ulong, AssetBase> m_changes = new Dictionary<ulong, AssetBase>(); | 69 | private Dictionary<FaceMaterial, double> m_changed = new Dictionary<FaceMaterial, double>(); |
75 | private Dictionary<ulong, double> m_changesTime = new Dictionary<ulong, double>(); | ||
76 | 70 | ||
77 | public void Initialise(IConfigSource source) | 71 | public void Initialise(IConfigSource source) |
78 | { | 72 | { |
@@ -101,54 +95,72 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
101 | return; | 95 | return; |
102 | 96 | ||
103 | m_scene = scene; | 97 | m_scene = scene; |
98 | m_scene.RegisterModuleInterface<IMaterialsModule>(this); | ||
104 | m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; | 99 | m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; |
105 | m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; | 100 | m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; |
101 | m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManager_OnObjectDeleteFromScene; | ||
106 | m_scene.EventManager.OnBackup += EventManager_OnBackup; | 102 | m_scene.EventManager.OnBackup += EventManager_OnBackup; |
107 | } | 103 | } |
108 | 104 | ||
109 | private void EventManager_OnBackup(ISimulationDataService datastore, bool forcedBackup) | 105 | public void RemoveRegion(Scene scene) |
110 | { | 106 | { |
111 | List<AssetBase> toStore; | 107 | if (!m_enabled) |
112 | List<ulong> hashlist; | 108 | return; |
113 | 109 | ||
110 | m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; | ||
111 | m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene; | ||
112 | m_scene.EventManager.OnObjectBeingRemovedFromScene -= EventManager_OnObjectDeleteFromScene; | ||
113 | m_scene.EventManager.OnBackup -= EventManager_OnBackup; | ||
114 | m_scene.UnregisterModuleInterface<IMaterialsModule>(this); | ||
115 | } | ||
114 | 116 | ||
115 | lock (m_Materials) | 117 | public void RegionLoaded(Scene scene) |
118 | { | ||
119 | if (!m_enabled) return; | ||
120 | |||
121 | m_cache = scene.RequestModuleInterface<IAssetCache>(); | ||
122 | ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>(); | ||
123 | if (featuresModule != null) | ||
124 | featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest; | ||
125 | } | ||
126 | |||
127 | private void EventManager_OnBackup(ISimulationDataService datastore, bool forcedBackup) | ||
128 | { | ||
129 | List<FaceMaterial> toStore; | ||
130 | |||
131 | lock (materialslock) | ||
116 | { | 132 | { |
117 | if(m_changes.Count == 0) | 133 | if(m_changed.Count == 0) |
118 | return; | 134 | return; |
119 | 135 | ||
120 | if(forcedBackup) | 136 | if(forcedBackup) |
121 | { | 137 | { |
122 | toStore = new List<AssetBase>(m_changes.Values); | 138 | toStore = new List<FaceMaterial>(m_changed.Keys); |
123 | m_changes.Clear(); | 139 | m_changed.Clear(); |
124 | m_changesTime.Clear(); | ||
125 | } | 140 | } |
126 | else | 141 | else |
127 | { | 142 | { |
128 | toStore = new List<AssetBase>(); | 143 | toStore = new List<FaceMaterial>(); |
129 | hashlist = new List<ulong>(); | 144 | double storetime = Util.GetTimeStamp() - 60.0; |
130 | double storetime = Util.GetTimeStampMS() - 60000; | 145 | foreach(KeyValuePair<FaceMaterial, double> kvp in m_changed) |
131 | foreach(KeyValuePair<ulong,double> kvp in m_changesTime) | ||
132 | { | 146 | { |
133 | if(kvp.Value < storetime) | 147 | if(kvp.Value < storetime) |
134 | { | 148 | { |
135 | toStore.Add(m_changes[kvp.Key]); | 149 | toStore.Add(kvp.Key); |
136 | hashlist.Add(kvp.Key); | ||
137 | } | 150 | } |
138 | } | 151 | } |
139 | foreach(ulong u in hashlist) | 152 | foreach(FaceMaterial fm in toStore) |
140 | { | 153 | { |
141 | m_changesTime.Remove(u); | 154 | m_changed.Remove(fm); |
142 | m_changes.Remove(u); | ||
143 | } | 155 | } |
144 | } | 156 | } |
145 | 157 | ||
146 | if(toStore.Count > 0) | 158 | if(toStore.Count > 0) |
147 | Util.FireAndForget(delegate | 159 | Util.FireAndForget(delegate |
148 | { | 160 | { |
149 | foreach(AssetBase a in toStore) | 161 | foreach(FaceMaterial fm in toStore) |
150 | { | 162 | { |
151 | a.Local = false; | 163 | AssetBase a = MakeAsset(fm, false); |
152 | m_scene.AssetService.Store(a); | 164 | m_scene.AssetService.Store(a); |
153 | } | 165 | } |
154 | }); | 166 | }); |
@@ -162,6 +174,13 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
162 | GetStoredMaterialsInPart(part); | 174 | GetStoredMaterialsInPart(part); |
163 | } | 175 | } |
164 | 176 | ||
177 | private void EventManager_OnObjectDeleteFromScene(SceneObjectGroup obj) | ||
178 | { | ||
179 | foreach (var part in obj.Parts) | ||
180 | if (part != null) | ||
181 | RemoveMaterialsInPart(part); | ||
182 | } | ||
183 | |||
165 | private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps) | 184 | private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps) |
166 | { | 185 | { |
167 | string capsBase = "/CAPS/" + caps.CapsObjectPath; | 186 | string capsBase = "/CAPS/" + caps.CapsObjectPath; |
@@ -193,26 +212,6 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
193 | MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler); | 212 | MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler); |
194 | } | 213 | } |
195 | 214 | ||
196 | public void RemoveRegion(Scene scene) | ||
197 | { | ||
198 | if (!m_enabled) | ||
199 | return; | ||
200 | |||
201 | m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; | ||
202 | m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene; | ||
203 | m_scene.EventManager.OnBackup -= EventManager_OnBackup; | ||
204 | } | ||
205 | |||
206 | public void RegionLoaded(Scene scene) | ||
207 | { | ||
208 | if (!m_enabled) return; | ||
209 | |||
210 | m_cache = scene.RequestModuleInterface<IAssetCache>(); | ||
211 | ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>(); | ||
212 | if (featuresModule != null) | ||
213 | featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest; | ||
214 | } | ||
215 | |||
216 | private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) | 215 | private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) |
217 | { | 216 | { |
218 | features["MaxMaterialsPerTransaction"] = m_maxMaterialsPerTransaction; | 217 | features["MaxMaterialsPerTransaction"] = m_maxMaterialsPerTransaction; |
@@ -222,14 +221,16 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
222 | /// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'. | 221 | /// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'. |
223 | /// </summary> | 222 | /// </summary> |
224 | /// <param name="part"></param> | 223 | /// <param name="part"></param> |
225 | private void GetLegacyStoredMaterialsInPart(SceneObjectPart part) | 224 | private bool GetLegacyStoredMaterialsInPart(SceneObjectPart part) |
226 | { | 225 | { |
227 | if (part.DynAttrs == null) | 226 | if (part.DynAttrs == null) |
228 | return; | 227 | return false; |
229 | 228 | ||
230 | OSD OSMaterials = null; | 229 | OSD OSMaterials = null; |
231 | OSDArray matsArr = null; | 230 | OSDArray matsArr = null; |
232 | 231 | ||
232 | bool partchanged = false; | ||
233 | |||
233 | lock (part.DynAttrs) | 234 | lock (part.DynAttrs) |
234 | { | 235 | { |
235 | if (part.DynAttrs.ContainsStore("OpenSim", "Materials")) | 236 | if (part.DynAttrs.ContainsStore("OpenSim", "Materials")) |
@@ -237,20 +238,22 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
237 | OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials"); | 238 | OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials"); |
238 | 239 | ||
239 | if (materialsStore == null) | 240 | if (materialsStore == null) |
240 | return; | 241 | return false; |
241 | 242 | ||
242 | materialsStore.TryGetValue("Materials", out OSMaterials); | 243 | materialsStore.TryGetValue("Materials", out OSMaterials); |
244 | part.DynAttrs.RemoveStore("OpenSim", "Materials"); | ||
245 | partchanged = true; | ||
243 | } | 246 | } |
244 | 247 | ||
245 | if (OSMaterials != null && OSMaterials is OSDArray) | 248 | if (OSMaterials != null && OSMaterials is OSDArray) |
246 | matsArr = OSMaterials as OSDArray; | 249 | matsArr = OSMaterials as OSDArray; |
247 | else | 250 | else |
248 | return; | 251 | return partchanged; |
249 | } | 252 | } |
250 | 253 | ||
251 | if (matsArr == null) | 254 | if (matsArr == null) |
252 | return; | 255 | return partchanged; |
253 | 256 | ||
254 | foreach (OSD elemOsd in matsArr) | 257 | foreach (OSD elemOsd in matsArr) |
255 | { | 258 | { |
256 | if (elemOsd != null && elemOsd is OSDMap) | 259 | if (elemOsd != null && elemOsd is OSDMap) |
@@ -260,16 +263,24 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
260 | { | 263 | { |
261 | try | 264 | try |
262 | { | 265 | { |
263 | lock (m_Materials) | 266 | lock (materialslock) |
264 | { | 267 | { |
265 | UUID id = matMap["ID"].AsUUID(); | 268 | UUID id = matMap["ID"].AsUUID(); |
266 | if(m_Materials.ContainsKey(id)) | 269 | if(m_Materials.ContainsKey(id)) |
267 | m_MaterialsRefCount[id]++; | 270 | continue; |
268 | else | 271 | |
269 | { | 272 | OSDMap theMatMap = (OSDMap)matMap["Material"]; |
270 | m_Materials[id] = (OSDMap)matMap["Material"]; | 273 | FaceMaterial fmat = new FaceMaterial(theMatMap); |
271 | m_MaterialsRefCount[id] = 1; | 274 | |
272 | } | 275 | if(fmat == null || |
276 | ( fmat.DiffuseAlphaMode == 1 | ||
277 | && fmat.NormalMapID == UUID.Zero | ||
278 | && fmat.SpecularMapID == UUID.Zero)) | ||
279 | continue; | ||
280 | |||
281 | fmat.ID = id; | ||
282 | m_Materials[id] = fmat; | ||
283 | m_MaterialsRefCount[id] = 0; | ||
273 | } | 284 | } |
274 | } | 285 | } |
275 | catch (Exception e) | 286 | catch (Exception e) |
@@ -279,6 +290,7 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
279 | } | 290 | } |
280 | } | 291 | } |
281 | } | 292 | } |
293 | return partchanged; | ||
282 | } | 294 | } |
283 | 295 | ||
284 | /// <summary> | 296 | /// <summary> |
@@ -289,14 +301,16 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
289 | if (part.Shape == null) | 301 | if (part.Shape == null) |
290 | return; | 302 | return; |
291 | 303 | ||
304 | bool partchanged = false; | ||
305 | bool facechanged = false; | ||
292 | var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length); | 306 | var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length); |
293 | if (te == null) | 307 | if (te == null) |
294 | return; | 308 | return; |
295 | 309 | ||
296 | GetLegacyStoredMaterialsInPart(part); | 310 | partchanged = GetLegacyStoredMaterialsInPart(part); |
297 | 311 | ||
298 | if (te.DefaultTexture != null) | 312 | if (te.DefaultTexture != null) |
299 | GetStoredMaterialInFace(part, te.DefaultTexture); | 313 | facechanged = GetStoredMaterialInFace(part, te.DefaultTexture); |
300 | else | 314 | else |
301 | m_log.WarnFormat( | 315 | m_log.WarnFormat( |
302 | "[Materials]: Default texture for part {0} (part of object {1}) in {2} unexpectedly null. Ignoring.", | 316 | "[Materials]: Default texture for part {0} (part of object {1}) in {2} unexpectedly null. Ignoring.", |
@@ -305,36 +319,47 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
305 | foreach (Primitive.TextureEntryFace face in te.FaceTextures) | 319 | foreach (Primitive.TextureEntryFace face in te.FaceTextures) |
306 | { | 320 | { |
307 | if (face != null) | 321 | if (face != null) |
308 | GetStoredMaterialInFace(part, face); | 322 | facechanged |= GetStoredMaterialInFace(part, face); |
323 | } | ||
324 | |||
325 | if(facechanged) | ||
326 | part.Shape.TextureEntry = te.GetBytes(); | ||
327 | |||
328 | if(facechanged || partchanged) | ||
329 | { | ||
330 | if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) | ||
331 | part.ParentGroup.HasGroupChanged = true; | ||
309 | } | 332 | } |
310 | } | 333 | } |
311 | 334 | ||
312 | /// <summary> | 335 | /// <summary> |
313 | /// Find the materials used in one Face, and add them to 'm_regionMaterials'. | 336 | /// Find the materials used in one Face, and add them to 'm_regionMaterials'. |
314 | /// </summary> | 337 | /// </summary> |
315 | private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face) | 338 | private bool GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face) |
316 | { | 339 | { |
317 | UUID id = face.MaterialID; | 340 | UUID id = face.MaterialID; |
318 | if (id == UUID.Zero) | 341 | if (id == UUID.Zero) |
319 | return; | 342 | return false; |
320 | 343 | ||
321 | lock (m_Materials) | 344 | OSDMap mat; |
345 | lock (materialslock) | ||
322 | { | 346 | { |
323 | if (m_Materials.ContainsKey(id)) | 347 | if(m_Materials.ContainsKey(id)) |
324 | { | 348 | { |
325 | m_MaterialsRefCount[id]++; | 349 | m_MaterialsRefCount[id]++; |
326 | return; | 350 | return false; |
327 | } | 351 | } |
328 | 352 | ||
329 | AssetBase matAsset = m_scene.AssetService.Get(id.ToString()); | 353 | AssetBase matAsset = m_scene.AssetService.Get(id.ToString()); |
330 | if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 ) | 354 | if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 ) |
331 | { | 355 | { |
332 | //m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id); | 356 | // grid may just be down... |
333 | return; | 357 | return false; |
334 | } | 358 | } |
335 | 359 | ||
336 | byte[] data = matAsset.Data; | 360 | byte[] data = matAsset.Data; |
337 | OSDMap mat; | 361 | |
362 | // string txt = System.Text.Encoding.ASCII.GetString(data); | ||
338 | try | 363 | try |
339 | { | 364 | { |
340 | mat = (OSDMap)OSDParser.DeserializeLLSDXml(data); | 365 | mat = (OSDMap)OSDParser.DeserializeLLSDXml(data); |
@@ -342,11 +367,76 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
342 | catch (Exception e) | 367 | catch (Exception e) |
343 | { | 368 | { |
344 | m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message); | 369 | m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message); |
345 | return; | 370 | return false; |
346 | } | 371 | } |
347 | 372 | ||
348 | m_Materials[id] = mat; | 373 | FaceMaterial fmat = new FaceMaterial(mat); |
349 | m_MaterialsRefCount[id] = 1; | 374 | |
375 | if(fmat == null || | ||
376 | (fmat.DiffuseAlphaMode == 1 | ||
377 | && fmat.NormalMapID == UUID.Zero | ||
378 | && fmat.SpecularMapID == UUID.Zero)) | ||
379 | { | ||
380 | face.MaterialID = UUID.Zero; | ||
381 | return true; | ||
382 | } | ||
383 | |||
384 | fmat.ID = id; | ||
385 | |||
386 | if (m_Materials.ContainsKey(id)) | ||
387 | { | ||
388 | m_MaterialsRefCount[id]++; | ||
389 | } | ||
390 | else | ||
391 | { | ||
392 | m_Materials[id] = fmat; | ||
393 | m_MaterialsRefCount[id] = 1; | ||
394 | } | ||
395 | return false; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | private void RemoveMaterialsInPart(SceneObjectPart part) | ||
400 | { | ||
401 | if (part.Shape == null) | ||
402 | return; | ||
403 | |||
404 | var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length); | ||
405 | if (te == null) | ||
406 | return; | ||
407 | |||
408 | if (te.DefaultTexture != null) | ||
409 | RemoveMaterialInFace(te.DefaultTexture); | ||
410 | |||
411 | foreach (Primitive.TextureEntryFace face in te.FaceTextures) | ||
412 | { | ||
413 | if(face != null) | ||
414 | RemoveMaterialInFace(face); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | private void RemoveMaterialInFace(Primitive.TextureEntryFace face) | ||
419 | { | ||
420 | UUID id = face.MaterialID; | ||
421 | if (id == UUID.Zero) | ||
422 | return; | ||
423 | |||
424 | lock (materialslock) | ||
425 | { | ||
426 | if(!m_Materials.ContainsKey(id)) | ||
427 | return; | ||
428 | else | ||
429 | { | ||
430 | m_MaterialsRefCount[id]--; | ||
431 | if(m_MaterialsRefCount[id] <= 0) | ||
432 | { | ||
433 | FaceMaterial oldFaceMat = m_Materials[id]; | ||
434 | m_changed.Remove(oldFaceMat); | ||
435 | m_Materials.Remove(id); | ||
436 | m_MaterialsRefCount.Remove(id); | ||
437 | m_cache.Expire(id.ToString()); | ||
438 | } | ||
439 | } | ||
350 | } | 440 | } |
351 | } | 441 | } |
352 | 442 | ||
@@ -375,13 +465,13 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
375 | { | 465 | { |
376 | UUID id = new UUID(elem.AsBinary(), 0); | 466 | UUID id = new UUID(elem.AsBinary(), 0); |
377 | 467 | ||
378 | lock (m_Materials) | 468 | lock (materialslock) |
379 | { | 469 | { |
380 | if (m_Materials.ContainsKey(id)) | 470 | if (m_Materials.ContainsKey(id)) |
381 | { | 471 | { |
382 | OSDMap matMap = new OSDMap(); | 472 | OSDMap matMap = new OSDMap(); |
383 | matMap["ID"] = OSD.FromBinary(id.GetBytes()); | 473 | matMap["ID"] = OSD.FromBinary(id.GetBytes()); |
384 | matMap["Material"] = m_Materials[id]; | 474 | matMap["Material"] = m_Materials[id].toOSD(); |
385 | respArr.Add(matMap); | 475 | respArr.Add(matMap); |
386 | } | 476 | } |
387 | else | 477 | else |
@@ -455,10 +545,12 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
455 | foreach (OSDMap matsMap in matsArr) | 545 | foreach (OSDMap matsMap in matsArr) |
456 | { | 546 | { |
457 | uint primLocalID = 0; | 547 | uint primLocalID = 0; |
458 | try { | 548 | try |
549 | { | ||
459 | primLocalID = matsMap["ID"].AsUInteger(); | 550 | primLocalID = matsMap["ID"].AsUInteger(); |
460 | } | 551 | } |
461 | catch (Exception e) { | 552 | catch (Exception e) |
553 | { | ||
462 | m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message); | 554 | m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message); |
463 | continue; | 555 | continue; |
464 | } | 556 | } |
@@ -494,68 +586,71 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
494 | continue; | 586 | continue; |
495 | } | 587 | } |
496 | 588 | ||
497 | UUID id; | ||
498 | if (mat == null) | ||
499 | { | ||
500 | // This happens then the user removes a material from a prim | ||
501 | id = UUID.Zero; | ||
502 | } | ||
503 | else | ||
504 | { | ||
505 | id = getNewID(mat); | ||
506 | } | ||
507 | |||
508 | int face = -1; | 589 | int face = -1; |
509 | UUID oldid = UUID.Zero; | 590 | UUID oldid = UUID.Zero; |
591 | Primitive.TextureEntryFace faceEntry = null; | ||
510 | if (matsMap.ContainsKey("Face")) | 592 | if (matsMap.ContainsKey("Face")) |
511 | { | 593 | { |
512 | face = matsMap["Face"].AsInteger(); | 594 | face = matsMap["Face"].AsInteger(); |
513 | Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face); | 595 | faceEntry = te.CreateFace((uint)face); |
514 | oldid = faceEntry.MaterialID; | ||
515 | faceEntry.MaterialID = id; | ||
516 | } | 596 | } |
517 | else | 597 | else |
598 | faceEntry = te.DefaultTexture; | ||
599 | |||
600 | if (faceEntry == null) | ||
601 | continue; | ||
602 | |||
603 | UUID id; | ||
604 | FaceMaterial newFaceMat = null; | ||
605 | if (mat == null) | ||
518 | { | 606 | { |
519 | if (te.DefaultTexture == null) | 607 | // This happens then the user removes a material from a prim |
520 | m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID); | 608 | id = UUID.Zero; |
609 | } | ||
610 | else | ||
611 | { | ||
612 | newFaceMat = new FaceMaterial(mat); | ||
613 | if(newFaceMat.DiffuseAlphaMode == 1 | ||
614 | && newFaceMat.NormalMapID == UUID.Zero | ||
615 | && newFaceMat.SpecularMapID == UUID.Zero | ||
616 | ) | ||
617 | id = UUID.Zero; | ||
521 | else | 618 | else |
522 | { | 619 | { |
523 | oldid = te.DefaultTexture.MaterialID; | 620 | newFaceMat.genID(); |
524 | te.DefaultTexture.MaterialID = id; | 621 | id = newFaceMat.ID; |
525 | } | 622 | } |
526 | } | 623 | } |
527 | 624 | ||
528 | //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id); | 625 | oldid = faceEntry.MaterialID; |
529 | 626 | ||
530 | // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually | 627 | if(oldid == id) |
531 | sop.Shape.TextureEntry = te.GetBytes(); | 628 | continue; |
532 | 629 | ||
533 | lock(m_Materials) | 630 | if (faceEntry != null) |
534 | { | 631 | { |
535 | if(oldid != UUID.Zero && m_MaterialsRefCount.ContainsKey(oldid)) | 632 | faceEntry.MaterialID = id; |
536 | { | 633 | |
537 | m_MaterialsRefCount[oldid]--; | 634 | //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id); |
538 | if(m_MaterialsRefCount[oldid] <= 0) | 635 | |
539 | { | 636 | // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually |
540 | m_Materials.Remove(oldid); | 637 | sop.Shape.TextureEntry = te.GetBytes(); |
541 | m_MaterialsRefCount.Remove(oldid); | 638 | } |
542 | m_cache.Expire(oldid.ToString()); | ||
543 | } | ||
544 | } | ||
545 | 639 | ||
640 | if(oldid != UUID.Zero) | ||
641 | RemoveMaterial(oldid); | ||
642 | |||
643 | lock(materialslock) | ||
644 | { | ||
546 | if(id != UUID.Zero) | 645 | if(id != UUID.Zero) |
547 | { | 646 | { |
548 | AssetBase asset = CacheMaterialAsAsset(id, agentID, mat, sop); | 647 | if (m_Materials.ContainsKey(id)) |
549 | if(asset != null) | 648 | m_MaterialsRefCount[id]++; |
649 | else | ||
550 | { | 650 | { |
551 | ulong materialHash = (ulong)primLocalID << 32; | 651 | m_Materials[id] = newFaceMat; |
552 | if(face < 0) | 652 | m_MaterialsRefCount[id] = 1; |
553 | materialHash += 0xffffffff; | 653 | m_changed[newFaceMat] = Util.GetTimeStamp(); |
554 | else | ||
555 | materialHash +=(ulong)face; | ||
556 | |||
557 | m_changes[materialHash] = asset; | ||
558 | m_changesTime[materialHash] = Util.GetTimeStampMS(); | ||
559 | } | 654 | } |
560 | } | 655 | } |
561 | } | 656 | } |
@@ -598,119 +693,39 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
598 | return response; | 693 | return response; |
599 | } | 694 | } |
600 | 695 | ||
601 | private UUID getNewID(OSDMap mat) | 696 | private AssetBase MakeAsset(FaceMaterial fm, bool local) |
602 | { | ||
603 | // ugly and done twice but keep compatibility for now | ||
604 | Byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat)); | ||
605 | using (var md5 = MD5.Create()) | ||
606 | return new UUID(md5.ComputeHash(data), 0); | ||
607 | } | ||
608 | |||
609 | private AssetBase CacheMaterialAsAsset(UUID id, UUID agentID, OSDMap mat, SceneObjectPart sop) | ||
610 | { | 697 | { |
698 | // this are not true assets, should had never been... | ||
611 | AssetBase asset = null; | 699 | AssetBase asset = null; |
612 | lock (m_Materials) | 700 | string txt = fm.toLLSDxml(); |
613 | { | 701 | byte[] data = System.Text.Encoding.ASCII.GetBytes(txt); |
614 | if (!m_Materials.ContainsKey(id)) | ||
615 | { | ||
616 | m_Materials[id] = mat; | ||
617 | m_MaterialsRefCount[id] = 1; | ||
618 | 702 | ||
619 | byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat)); | 703 | asset = new AssetBase(fm.ID, "llmaterial", (sbyte)OpenSimAssetType.Material, "00000000-0000-0000-0000-000000000000"); |
620 | 704 | asset.Data = data; | |
621 | // This asset might exist already, but it's ok to try to store it again | 705 | asset.Local = local; |
622 | string name = "Material " + ChooseMaterialName(mat, sop); | ||
623 | name = name.Substring(0, Math.Min(64, name.Length)).Trim(); | ||
624 | asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString()); | ||
625 | asset.Data = data; | ||
626 | asset.Local = true; | ||
627 | m_cache.Cache(asset); | ||
628 | } | ||
629 | else | ||
630 | m_MaterialsRefCount[id]++; | ||
631 | } | ||
632 | return asset; | 706 | return asset; |
633 | } | 707 | } |
634 | 708 | ||
635 | private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop) | ||
636 | { | ||
637 | UUID id; | ||
638 | // Material UUID = hash of the material's data. | ||
639 | // This makes materials deduplicate across the entire grid (but isn't otherwise required). | ||
640 | byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat)); | ||
641 | using (var md5 = MD5.Create()) | ||
642 | id = new UUID(md5.ComputeHash(data), 0); | ||
643 | |||
644 | lock (m_Materials) | ||
645 | { | ||
646 | if (!m_Materials.ContainsKey(id)) | ||
647 | { | ||
648 | m_Materials[id] = mat; | ||
649 | m_MaterialsRefCount[id] = 1; | ||
650 | |||
651 | // This asset might exist already, but it's ok to try to store it again | ||
652 | string name = "Material " + ChooseMaterialName(mat, sop); | ||
653 | name = name.Substring(0, Math.Min(64, name.Length)).Trim(); | ||
654 | AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString()); | ||
655 | asset.Data = data; | ||
656 | m_scene.AssetService.Store(asset); | ||
657 | } | ||
658 | else | ||
659 | m_MaterialsRefCount[id]++; | ||
660 | } | ||
661 | return id; | ||
662 | } | ||
663 | |||
664 | /// <summary> | ||
665 | /// Use heuristics to choose a good name for the material. | ||
666 | /// </summary> | ||
667 | private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop) | ||
668 | { | ||
669 | UUID normMap = mat["NormMap"].AsUUID(); | ||
670 | if (normMap != UUID.Zero) | ||
671 | { | ||
672 | AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString()); | ||
673 | if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR")) | ||
674 | return asset.Name; | ||
675 | } | ||
676 | |||
677 | UUID specMap = mat["SpecMap"].AsUUID(); | ||
678 | if (specMap != UUID.Zero) | ||
679 | { | ||
680 | AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString()); | ||
681 | if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR")) | ||
682 | return asset.Name; | ||
683 | } | ||
684 | |||
685 | if (sop.Name != "Primitive") | ||
686 | return sop.Name; | ||
687 | |||
688 | if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive")) | ||
689 | return sop.ParentGroup.Name; | ||
690 | |||
691 | return ""; | ||
692 | } | ||
693 | |||
694 | |||
695 | public string RenderMaterialsGetCap(string request) | 709 | public string RenderMaterialsGetCap(string request) |
696 | { | 710 | { |
697 | OSDMap resp = new OSDMap(); | 711 | OSDMap resp = new OSDMap(); |
698 | int matsCount = 0; | ||
699 | OSDArray allOsd = new OSDArray(); | 712 | OSDArray allOsd = new OSDArray(); |
713 | /* | ||
714 | // this violates all idea of caching and geting things only if needed, so disabled | ||
700 | 715 | ||
716 | int matsCount = 0; | ||
701 | lock (m_Materials) | 717 | lock (m_Materials) |
702 | { | 718 | { |
703 | foreach (KeyValuePair<UUID, OSDMap> kvp in m_Materials) | 719 | foreach (KeyValuePair<UUID, FaceMaterial> kvp in m_Materials) |
704 | { | 720 | { |
705 | OSDMap matMap = new OSDMap(); | 721 | OSDMap matMap = new OSDMap(); |
706 | |||
707 | matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes()); | 722 | matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes()); |
708 | matMap["Material"] = kvp.Value; | 723 | matMap["Material"] = kvp.Value.toOSD(); |
709 | allOsd.Add(matMap); | 724 | allOsd.Add(matMap); |
710 | matsCount++; | 725 | matsCount++; |
711 | } | 726 | } |
712 | } | 727 | } |
713 | 728 | */ | |
714 | resp["Zipped"] = ZCompressOSD(allOsd, false); | 729 | resp["Zipped"] = ZCompressOSD(allOsd, false); |
715 | 730 | ||
716 | return OSDParser.SerializeLLSDXmlString(resp); | 731 | return OSDParser.SerializeLLSDXmlString(resp); |
@@ -728,18 +743,6 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
728 | } | 743 | } |
729 | } | 744 | } |
730 | 745 | ||
731 | /// <summary> | ||
732 | /// computes a UUID by hashing a OSD object | ||
733 | /// </summary> | ||
734 | /// <param name="osd"></param> | ||
735 | /// <returns></returns> | ||
736 | private static UUID HashOsd(OSD osd) | ||
737 | { | ||
738 | byte[] data = OSDParser.SerializeLLSDBinary(osd, false); | ||
739 | using (var md5 = MD5.Create()) | ||
740 | return new UUID(md5.ComputeHash(data), 0); | ||
741 | } | ||
742 | |||
743 | public static OSD ZCompressOSD(OSD inOsd, bool useHeader) | 746 | public static OSD ZCompressOSD(OSD inOsd, bool useHeader) |
744 | { | 747 | { |
745 | OSD osd = null; | 748 | OSD osd = null; |
@@ -761,7 +764,6 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
761 | return osd; | 764 | return osd; |
762 | } | 765 | } |
763 | 766 | ||
764 | |||
765 | public static OSD ZDecompressBytesToOsd(byte[] input) | 767 | public static OSD ZDecompressBytesToOsd(byte[] input) |
766 | { | 768 | { |
767 | OSD osd = null; | 769 | OSD osd = null; |
@@ -779,5 +781,67 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
779 | 781 | ||
780 | return osd; | 782 | return osd; |
781 | } | 783 | } |
784 | |||
785 | public FaceMaterial GetMaterial(UUID ID) | ||
786 | { | ||
787 | FaceMaterial fm = null; | ||
788 | if(m_Materials.TryGetValue(ID, out fm)) | ||
789 | return fm; | ||
790 | return null; | ||
791 | } | ||
792 | |||
793 | public FaceMaterial GetMaterialCopy(UUID ID) | ||
794 | { | ||
795 | FaceMaterial fm = null; | ||
796 | if(m_Materials.TryGetValue(ID, out fm)) | ||
797 | return new FaceMaterial(fm); | ||
798 | return null; | ||
799 | } | ||
800 | |||
801 | public UUID AddNewMaterial(FaceMaterial fm) | ||
802 | { | ||
803 | if(fm.DiffuseAlphaMode == 1 && fm.NormalMapID == UUID.Zero && fm.SpecularMapID == UUID.Zero) | ||
804 | { | ||
805 | fm.ID = UUID.Zero; | ||
806 | return UUID.Zero; | ||
807 | } | ||
808 | |||
809 | fm.genID(); | ||
810 | UUID id = fm.ID; | ||
811 | lock(materialslock) | ||
812 | { | ||
813 | if(m_Materials.ContainsKey(id)) | ||
814 | m_MaterialsRefCount[id]++; | ||
815 | else | ||
816 | { | ||
817 | m_Materials[id] = fm; | ||
818 | m_MaterialsRefCount[id] = 1; | ||
819 | m_changed[fm] = Util.GetTimeStamp(); | ||
820 | } | ||
821 | } | ||
822 | return id; | ||
823 | } | ||
824 | |||
825 | public void RemoveMaterial(UUID id) | ||
826 | { | ||
827 | if(id == UUID.Zero) | ||
828 | return; | ||
829 | |||
830 | lock(materialslock) | ||
831 | { | ||
832 | if(m_Materials.ContainsKey(id)) | ||
833 | { | ||
834 | m_MaterialsRefCount[id]--; | ||
835 | if(m_MaterialsRefCount[id] <= 0) | ||
836 | { | ||
837 | FaceMaterial fm = m_Materials[id]; | ||
838 | m_changed.Remove(fm); | ||
839 | m_Materials.Remove(id); | ||
840 | m_MaterialsRefCount.Remove(id); | ||
841 | m_cache.Expire(id.ToString()); | ||
842 | } | ||
843 | } | ||
844 | } | ||
845 | } | ||
782 | } | 846 | } |
783 | } | 847 | } |
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index 5513cd5..1ff9cb5 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs | |||
@@ -824,7 +824,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule | |||
824 | ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>(); | 824 | ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>(); |
825 | if (module != null) | 825 | if (module != null) |
826 | { | 826 | { |
827 | module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false); | 827 | module.SendSound(GetSOP().UUID, asset, volume, true, 0, false, false); |
828 | } | 828 | } |
829 | } | 829 | } |
830 | 830 | ||
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/World.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/World.cs index 36f70d0..eff70ef 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/World.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/World.cs | |||
@@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule | |||
231 | if (soundModule != null) | 231 | if (soundModule != null) |
232 | { | 232 | { |
233 | soundModule.TriggerSound(audio, UUID.Zero, UUID.Zero, UUID.Zero, volume, position, | 233 | soundModule.TriggerSound(audio, UUID.Zero, UUID.Zero, UUID.Zero, volume, position, |
234 | m_internalScene.RegionInfo.RegionHandle, 0); | 234 | m_internalScene.RegionInfo.RegionHandle); |
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
@@ -241,7 +241,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule | |||
241 | if (soundModule != null) | 241 | if (soundModule != null) |
242 | { | 242 | { |
243 | soundModule.TriggerSound(audio, UUID.Zero, UUID.Zero, UUID.Zero, 1.0, position, | 243 | soundModule.TriggerSound(audio, UUID.Zero, UUID.Zero, UUID.Zero, 1.0, position, |
244 | m_internalScene.RegionInfo.RegionHandle, 0); | 244 | m_internalScene.RegionInfo.RegionHandle); |
245 | } | 245 | } |
246 | } | 246 | } |
247 | 247 | ||
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index a14d819..64513a0 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs | |||
@@ -127,7 +127,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup | |||
127 | /// <summary> | 127 | /// <summary> |
128 | /// Identifies the module to the system. | 128 | /// Identifies the module to the system. |
129 | /// </summary> | 129 | /// </summary> |
130 | string IRegionModuleBase.Name | 130 | public string Name |
131 | { | 131 | { |
132 | get { return "AutoBackupModule"; } | 132 | get { return "AutoBackupModule"; } |
133 | } | 133 | } |
@@ -135,7 +135,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup | |||
135 | /// <summary> | 135 | /// <summary> |
136 | /// We don't implement an interface, this is a single-use module. | 136 | /// We don't implement an interface, this is a single-use module. |
137 | /// </summary> | 137 | /// </summary> |
138 | Type IRegionModuleBase.ReplaceableInterface | 138 | public Type ReplaceableInterface |
139 | { | 139 | { |
140 | get { return null; } | 140 | get { return null; } |
141 | } | 141 | } |
@@ -144,7 +144,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup | |||
144 | /// Called once in the lifetime of the module at startup. | 144 | /// Called once in the lifetime of the module at startup. |
145 | /// </summary> | 145 | /// </summary> |
146 | /// <param name="source">The input config source for OpenSim.ini.</param> | 146 | /// <param name="source">The input config source for OpenSim.ini.</param> |
147 | void IRegionModuleBase.Initialise(IConfigSource source) | 147 | public void Initialise(IConfigSource source) |
148 | { | 148 | { |
149 | // Determine if we have been enabled at all in OpenSim.ini -- this is part and parcel of being an optional module | 149 | // Determine if we have been enabled at all in OpenSim.ini -- this is part and parcel of being an optional module |
150 | m_configSource = source; | 150 | m_configSource = source; |
@@ -184,7 +184,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup | |||
184 | /// <summary> | 184 | /// <summary> |
185 | /// Called once at de-init (sim shutting down). | 185 | /// Called once at de-init (sim shutting down). |
186 | /// </summary> | 186 | /// </summary> |
187 | void IRegionModuleBase.Close() | 187 | public void Close() |
188 | { | 188 | { |
189 | if (!m_enabled) | 189 | if (!m_enabled) |
190 | return; | 190 | return; |
@@ -197,7 +197,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup | |||
197 | /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded. | 197 | /// Currently a no-op for AutoBackup because we have to wait for region to be fully loaded. |
198 | /// </summary> | 198 | /// </summary> |
199 | /// <param name="scene"></param> | 199 | /// <param name="scene"></param> |
200 | void IRegionModuleBase.AddRegion (Scene scene) | 200 | public void AddRegion (Scene scene) |
201 | { | 201 | { |
202 | if (!m_enabled) | 202 | if (!m_enabled) |
203 | return; | 203 | return; |
@@ -210,7 +210,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup | |||
210 | /// Here we just clean up some resources and stop the OAR backup (if any) for the given scene. | 210 | /// Here we just clean up some resources and stop the OAR backup (if any) for the given scene. |
211 | /// </summary> | 211 | /// </summary> |
212 | /// <param name="scene">The scene (region) to stop performing AutoBackup on.</param> | 212 | /// <param name="scene">The scene (region) to stop performing AutoBackup on.</param> |
213 | void IRegionModuleBase.RemoveRegion(Scene scene) | 213 | public void RemoveRegion(Scene scene) |
214 | { | 214 | { |
215 | if (m_enabled) | 215 | if (m_enabled) |
216 | return; | 216 | return; |
@@ -228,7 +228,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup | |||
228 | /// We read lots of Nini config, maybe set a timer, add members to state tracking Dictionaries, etc. | 228 | /// We read lots of Nini config, maybe set a timer, add members to state tracking Dictionaries, etc. |
229 | /// </summary> | 229 | /// </summary> |
230 | /// <param name="scene">The scene to (possibly) perform AutoBackup on.</param> | 230 | /// <param name="scene">The scene to (possibly) perform AutoBackup on.</param> |
231 | void IRegionModuleBase.RegionLoaded(Scene scene) | 231 | public void RegionLoaded(Scene scene) |
232 | { | 232 | { |
233 | if (!m_enabled) | 233 | if (!m_enabled) |
234 | return; | 234 | return; |
@@ -258,7 +258,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup | |||
258 | /// <summary> | 258 | /// <summary> |
259 | /// Currently a no-op. | 259 | /// Currently a no-op. |
260 | /// </summary> | 260 | /// </summary> |
261 | void ISharedRegionModule.PostInitialise() | 261 | public void PostInitialise() |
262 | { | 262 | { |
263 | } | 263 | } |
264 | 264 | ||
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs index 7e3bd7f..f406ca6 100644 --- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs | |||
@@ -227,7 +227,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments | |||
227 | if (bool.TryParse(options["updates"], out enableUpdateDebugging)) | 227 | if (bool.TryParse(options["updates"], out enableUpdateDebugging)) |
228 | { | 228 | { |
229 | m_scene.DebugUpdates = enableUpdateDebugging; | 229 | m_scene.DebugUpdates = enableUpdateDebugging; |
230 | GcNotify.Enabled = enableUpdateDebugging; | ||
231 | } | 230 | } |
232 | } | 231 | } |
233 | } | 232 | } |