diff options
Diffstat (limited to 'OpenSim/Region')
20 files changed, 323 insertions, 358 deletions
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index 241af53..33b01e5 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs | |||
@@ -205,13 +205,10 @@ namespace OpenSim | |||
205 | Directory.CreateDirectory(m_crashDir); | 205 | Directory.CreateDirectory(m_crashDir); |
206 | } | 206 | } |
207 | string log = Util.GetUniqueFilename(ex.GetType() + ".txt"); | 207 | string log = Util.GetUniqueFilename(ex.GetType() + ".txt"); |
208 | StreamWriter m_crashLog = | 208 | using (StreamWriter m_crashLog = new StreamWriter(Path.Combine(m_crashDir, log))) |
209 | new StreamWriter( | 209 | { |
210 | Path.Combine(m_crashDir, log) | 210 | m_crashLog.WriteLine(msg); |
211 | ); | 211 | } |
212 | |||
213 | m_crashLog.WriteLine(msg); | ||
214 | m_crashLog.Close(); | ||
215 | 212 | ||
216 | File.Copy("OpenSim.ini", Path.Combine(m_crashDir, log + "_OpenSim.ini"), true); | 213 | File.Copy("OpenSim.ini", Path.Combine(m_crashDir, log + "_OpenSim.ini"), true); |
217 | } | 214 | } |
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 468c5d7..6e7a2a0 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs | |||
@@ -699,7 +699,7 @@ namespace OpenSim | |||
699 | public byte[] Handle(string path, Stream request, | 699 | public byte[] Handle(string path, Stream request, |
700 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | 700 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) |
701 | { | 701 | { |
702 | return Encoding.UTF8.GetBytes("OK"); | 702 | return Util.UTF8.GetBytes("OK"); |
703 | } | 703 | } |
704 | 704 | ||
705 | public string ContentType | 705 | public string ContentType |
@@ -736,7 +736,7 @@ namespace OpenSim | |||
736 | public byte[] Handle(string path, Stream request, | 736 | public byte[] Handle(string path, Stream request, |
737 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | 737 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) |
738 | { | 738 | { |
739 | return Encoding.UTF8.GetBytes(m_opensim.StatReport(httpRequest)); | 739 | return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest)); |
740 | } | 740 | } |
741 | 741 | ||
742 | public string ContentType | 742 | public string ContentType |
@@ -777,7 +777,7 @@ namespace OpenSim | |||
777 | public byte[] Handle(string path, Stream request, | 777 | public byte[] Handle(string path, Stream request, |
778 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | 778 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) |
779 | { | 779 | { |
780 | return Encoding.UTF8.GetBytes(m_opensim.StatReport(httpRequest)); | 780 | return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest)); |
781 | } | 781 | } |
782 | 782 | ||
783 | public string ContentType | 783 | public string ContentType |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs index 5f549b5..19ad0b4 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs | |||
@@ -47,69 +47,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
47 | 47 | ||
48 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 48 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
49 | 49 | ||
50 | public uint m_lastSequence; | 50 | public uint LastSequence; |
51 | public float m_requestedPriority; | 51 | public float Priority; |
52 | public uint m_requestedPacketNumber; | 52 | public uint StartPacket; |
53 | public sbyte m_requestedDiscardLevel; | 53 | public sbyte DiscardLevel; |
54 | public UUID m_requestedUUID; | 54 | public UUID TextureID; |
55 | public IJ2KDecoder m_j2kDecodeModule; | 55 | public IJ2KDecoder J2KDecoder; |
56 | public IAssetService m_assetCache; | 56 | public IAssetService AssetService; |
57 | public OpenJPEG.J2KLayerInfo[] m_layers; | 57 | public OpenJPEG.J2KLayerInfo[] Layers; |
58 | public bool m_decoded; | 58 | public bool IsDecoded; |
59 | public bool m_hasasset; | 59 | public bool HasAsset; |
60 | public C5.IPriorityQueueHandle<J2KImage> m_priorityQueueHandle; | 60 | public C5.IPriorityQueueHandle<J2KImage> PriorityQueueHandle; |
61 | 61 | ||
62 | private uint m_packetNumber; | 62 | private uint m_currentPacket; |
63 | private bool m_decoderequested; | 63 | private bool m_decodeRequested; |
64 | private bool m_asset_requested; | 64 | private bool m_assetRequested; |
65 | private bool m_sentinfo; | 65 | private bool m_sentInfo; |
66 | private uint m_stopPacket; | 66 | private uint m_stopPacket; |
67 | private AssetBase m_asset; | 67 | private byte[] m_asset; |
68 | private int m_assetDataLength; | ||
69 | private LLImageManager m_imageManager; | 68 | private LLImageManager m_imageManager; |
70 | 69 | ||
71 | #region Properties | ||
72 | |||
73 | public uint m_pPacketNumber | ||
74 | { | ||
75 | get { return m_packetNumber; } | ||
76 | } | ||
77 | public uint m_pStopPacketNumber | ||
78 | { | ||
79 | get { return m_stopPacket; } | ||
80 | } | ||
81 | |||
82 | public byte[] Data | ||
83 | { | ||
84 | get | ||
85 | { | ||
86 | if (m_asset != null) | ||
87 | return m_asset.Data; | ||
88 | else | ||
89 | return null; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | public ushort TexturePacketCount() | ||
94 | { | ||
95 | if (!m_decoded) | ||
96 | return 0; | ||
97 | |||
98 | try | ||
99 | { | ||
100 | return (ushort)(((m_assetDataLength - FIRST_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1); | ||
101 | } | ||
102 | catch (Exception) | ||
103 | { | ||
104 | // If the asset is missing/destroyed/truncated, we will land | ||
105 | // here | ||
106 | // | ||
107 | return 0; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | #endregion Properties | ||
112 | |||
113 | public J2KImage(LLImageManager imageManager) | 70 | public J2KImage(LLImageManager imageManager) |
114 | { | 71 | { |
115 | m_imageManager = imageManager; | 72 | m_imageManager = imageManager; |
@@ -117,33 +74,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
117 | 74 | ||
118 | public bool SendPackets(LLClientView client, int maxpack) | 75 | public bool SendPackets(LLClientView client, int maxpack) |
119 | { | 76 | { |
120 | if (m_packetNumber <= m_stopPacket) | 77 | if (m_currentPacket <= m_stopPacket) |
121 | { | 78 | { |
122 | bool SendMore = true; | 79 | bool SendMore = true; |
123 | if (!m_sentinfo || (m_packetNumber == 0)) | 80 | if (!m_sentInfo || (m_currentPacket == 0)) |
124 | { | 81 | { |
125 | if (SendFirstPacket(client)) | 82 | if (SendFirstPacket(client)) |
126 | { | 83 | { |
127 | SendMore = false; | 84 | SendMore = false; |
128 | } | 85 | } |
129 | m_sentinfo = true; | 86 | m_sentInfo = true; |
130 | m_packetNumber++; | 87 | m_currentPacket++; |
131 | } | 88 | } |
132 | // bool ignoreStop = false; | 89 | if (m_currentPacket < 2) |
133 | if (m_packetNumber < 2) | ||
134 | { | 90 | { |
135 | m_packetNumber = 2; | 91 | m_currentPacket = 2; |
136 | } | 92 | } |
137 | 93 | ||
138 | int count = 0; | 94 | int count = 0; |
139 | while (SendMore && count < maxpack && m_packetNumber <= m_stopPacket) | 95 | while (SendMore && count < maxpack && m_currentPacket <= m_stopPacket) |
140 | { | 96 | { |
141 | count++; | 97 | count++; |
142 | SendMore = SendPacket(client); | 98 | SendMore = SendPacket(client); |
143 | m_packetNumber++; | 99 | m_currentPacket++; |
144 | } | 100 | } |
145 | 101 | ||
146 | if (m_packetNumber > m_stopPacket) | 102 | if (m_currentPacket > m_stopPacket) |
147 | return true; | 103 | return true; |
148 | } | 104 | } |
149 | 105 | ||
@@ -156,68 +112,76 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
156 | //and assign the real discardLevel and packetNumber | 112 | //and assign the real discardLevel and packetNumber |
157 | //assuming of course that the connected client might be bonkers | 113 | //assuming of course that the connected client might be bonkers |
158 | 114 | ||
159 | if (!m_hasasset) | 115 | if (!HasAsset) |
160 | { | 116 | { |
161 | if (!m_asset_requested) | 117 | if (!m_assetRequested) |
162 | { | 118 | { |
163 | m_asset_requested = true; | 119 | m_assetRequested = true; |
164 | m_assetCache.Get(m_requestedUUID.ToString(), this, AssetReceived); | 120 | AssetService.Get(TextureID.ToString(), this, AssetReceived); |
165 | } | 121 | } |
166 | } | 122 | } |
167 | else | 123 | else |
168 | { | 124 | { |
169 | if (!m_decoded) | 125 | if (!IsDecoded) |
170 | { | 126 | { |
171 | //We need to decode the requested image first | 127 | //We need to decode the requested image first |
172 | if (!m_decoderequested) | 128 | if (!m_decodeRequested) |
173 | { | 129 | { |
174 | //Request decode | 130 | //Request decode |
175 | m_decoderequested = true; | 131 | m_decodeRequested = true; |
176 | // Do we have a jpeg decoder? | 132 | // Do we have a jpeg decoder? |
177 | if (m_j2kDecodeModule != null) | 133 | if (J2KDecoder != null) |
178 | { | 134 | { |
179 | if (Data == null) | 135 | if (m_asset == null) |
180 | { | 136 | { |
181 | J2KDecodedCallback(m_requestedUUID, new OpenJPEG.J2KLayerInfo[0]); | 137 | J2KDecodedCallback(TextureID, new OpenJPEG.J2KLayerInfo[0]); |
182 | } | 138 | } |
183 | else | 139 | else |
184 | { | 140 | { |
185 | // Send it off to the jpeg decoder | 141 | // Send it off to the jpeg decoder |
186 | m_j2kDecodeModule.BeginDecode(m_requestedUUID, Data, J2KDecodedCallback); | 142 | J2KDecoder.BeginDecode(TextureID, m_asset, J2KDecodedCallback); |
187 | } | 143 | } |
188 | 144 | ||
189 | } | 145 | } |
190 | else | 146 | else |
191 | { | 147 | { |
192 | J2KDecodedCallback(m_requestedUUID, new OpenJPEG.J2KLayerInfo[0]); | 148 | J2KDecodedCallback(TextureID, new OpenJPEG.J2KLayerInfo[0]); |
193 | } | 149 | } |
194 | } | 150 | } |
195 | } | 151 | } |
196 | else | 152 | else |
197 | { | 153 | { |
198 | // Check for missing image asset data | 154 | // Check for missing image asset data |
199 | if (m_asset == null || m_asset.Data == null) | 155 | if (m_asset == null) |
200 | { | 156 | { |
201 | // FIXME: | 157 | m_log.Warn("[J2KIMAGE]: RunUpdate() called with missing asset data (no missing image texture?). Canceling texture transfer"); |
202 | m_packetNumber = m_stopPacket; | 158 | m_currentPacket = m_stopPacket; |
203 | return; | 159 | return; |
204 | } | 160 | } |
205 | 161 | ||
206 | if (m_requestedDiscardLevel >= 0 || m_stopPacket == 0) | 162 | if (DiscardLevel >= 0 || m_stopPacket == 0) |
207 | { | 163 | { |
208 | int maxDiscardLevel = Math.Max(0, m_layers.Length - 1); | 164 | // This shouldn't happen, but if it does, we really can't proceed |
165 | if (Layers == null) | ||
166 | { | ||
167 | m_log.Warn("[J2KIMAGE]: RunUpdate() called with missing Layers. Canceling texture transfer"); | ||
168 | m_currentPacket = m_stopPacket; | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | int maxDiscardLevel = Math.Max(0, Layers.Length - 1); | ||
209 | 173 | ||
210 | // Treat initial texture downloads with a DiscardLevel of -1 a request for the highest DiscardLevel | 174 | // Treat initial texture downloads with a DiscardLevel of -1 a request for the highest DiscardLevel |
211 | if (m_requestedDiscardLevel < 0 && m_stopPacket == 0) | 175 | if (DiscardLevel < 0 && m_stopPacket == 0) |
212 | m_requestedDiscardLevel = (sbyte)maxDiscardLevel; | 176 | DiscardLevel = (sbyte)maxDiscardLevel; |
213 | 177 | ||
214 | // Clamp at the highest discard level | 178 | // Clamp at the highest discard level |
215 | m_requestedDiscardLevel = (sbyte)Math.Min(m_requestedDiscardLevel, maxDiscardLevel); | 179 | DiscardLevel = (sbyte)Math.Min(DiscardLevel, maxDiscardLevel); |
216 | 180 | ||
217 | //Calculate the m_stopPacket | 181 | //Calculate the m_stopPacket |
218 | if (m_layers.Length > 0) | 182 | if (Layers.Length > 0) |
219 | { | 183 | { |
220 | m_stopPacket = (uint)GetPacketForBytePosition(m_layers[(m_layers.Length - 1) - m_requestedDiscardLevel].End); | 184 | m_stopPacket = (uint)GetPacketForBytePosition(Layers[(Layers.Length - 1) - DiscardLevel].End); |
221 | //I don't know why, but the viewer seems to expect the final packet if the file | 185 | //I don't know why, but the viewer seems to expect the final packet if the file |
222 | //is just one packet bigger. | 186 | //is just one packet bigger. |
223 | if (TexturePacketCount() == m_stopPacket + 1) | 187 | if (TexturePacketCount() == m_stopPacket + 1) |
@@ -230,32 +194,65 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
230 | m_stopPacket = TexturePacketCount(); | 194 | m_stopPacket = TexturePacketCount(); |
231 | } | 195 | } |
232 | 196 | ||
233 | m_packetNumber = m_requestedPacketNumber; | 197 | m_currentPacket = StartPacket; |
234 | } | 198 | } |
235 | 199 | ||
236 | if (m_imageManager.Client.PacketHandler.GetQueueCount(ThrottleOutPacketType.Texture) == 0) | 200 | if ((m_imageManager != null) && (m_imageManager.Client != null) && (m_imageManager.Client.PacketHandler != null)) |
237 | { | 201 | if (m_imageManager.Client.PacketHandler.GetQueueCount(ThrottleOutPacketType.Texture) == 0) |
238 | //m_log.Debug("No textures queued, sending one packet to kickstart it"); | 202 | { |
239 | SendPacket(m_imageManager.Client); | 203 | //m_log.Debug("No textures queued, sending one packet to kickstart it"); |
240 | } | 204 | SendPacket(m_imageManager.Client); |
205 | } | ||
241 | } | 206 | } |
242 | } | 207 | } |
243 | } | 208 | } |
244 | 209 | ||
210 | private bool SendFirstPacket(LLClientView client) | ||
211 | { | ||
212 | if (m_asset == null) | ||
213 | { | ||
214 | m_log.Warn("[J2KIMAGE]: Sending ImageNotInDatabase for texture " + TextureID); | ||
215 | client.SendImageNotFound(TextureID); | ||
216 | return true; | ||
217 | } | ||
218 | else if (m_asset.Length <= FIRST_PACKET_SIZE) | ||
219 | { | ||
220 | // We have less then one packet's worth of data | ||
221 | client.SendImageFirstPart(1, TextureID, (uint)m_asset.Length, m_asset, 2); | ||
222 | m_stopPacket = 0; | ||
223 | return true; | ||
224 | } | ||
225 | else | ||
226 | { | ||
227 | // This is going to be a multi-packet texture download | ||
228 | byte[] firstImageData = new byte[FIRST_PACKET_SIZE]; | ||
229 | |||
230 | try { Buffer.BlockCopy(m_asset, 0, firstImageData, 0, FIRST_PACKET_SIZE); } | ||
231 | catch (Exception) | ||
232 | { | ||
233 | m_log.ErrorFormat("[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}", TextureID, m_asset.Length); | ||
234 | return true; | ||
235 | } | ||
236 | |||
237 | client.SendImageFirstPart(TexturePacketCount(), TextureID, (uint)m_asset.Length, firstImageData, (byte)ImageCodec.J2C); | ||
238 | } | ||
239 | return false; | ||
240 | } | ||
241 | |||
245 | private bool SendPacket(LLClientView client) | 242 | private bool SendPacket(LLClientView client) |
246 | { | 243 | { |
247 | bool complete = false; | 244 | bool complete = false; |
248 | int imagePacketSize = ((int)m_packetNumber == (TexturePacketCount())) ? LastPacketSize() : IMAGE_PACKET_SIZE; | 245 | int imagePacketSize = ((int)m_currentPacket == (TexturePacketCount())) ? LastPacketSize() : IMAGE_PACKET_SIZE; |
249 | 246 | ||
250 | try | 247 | try |
251 | { | 248 | { |
252 | if ((CurrentBytePosition() + IMAGE_PACKET_SIZE) > m_assetDataLength) | 249 | if ((CurrentBytePosition() + IMAGE_PACKET_SIZE) > m_asset.Length) |
253 | { | 250 | { |
254 | imagePacketSize = LastPacketSize(); | 251 | imagePacketSize = LastPacketSize(); |
255 | complete = true; | 252 | complete = true; |
256 | if ((CurrentBytePosition() + imagePacketSize) > m_assetDataLength) | 253 | if ((CurrentBytePosition() + imagePacketSize) > m_asset.Length) |
257 | { | 254 | { |
258 | imagePacketSize = m_assetDataLength - CurrentBytePosition(); | 255 | imagePacketSize = m_asset.Length - CurrentBytePosition(); |
259 | complete = true; | 256 | complete = true; |
260 | } | 257 | } |
261 | } | 258 | } |
@@ -266,27 +263,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
266 | if (imagePacketSize > 0) | 263 | if (imagePacketSize > 0) |
267 | { | 264 | { |
268 | byte[] imageData = new byte[imagePacketSize]; | 265 | byte[] imageData = new byte[imagePacketSize]; |
269 | try | 266 | int currentPosition = CurrentBytePosition(); |
270 | { | 267 | |
271 | Buffer.BlockCopy(m_asset.Data, CurrentBytePosition(), imageData, 0, imagePacketSize); | 268 | try { Buffer.BlockCopy(m_asset, currentPosition, imageData, 0, imagePacketSize); } |
272 | } | ||
273 | catch (Exception e) | 269 | catch (Exception e) |
274 | { | 270 | { |
275 | m_log.Error("Error copying texture block. Out of memory? imagePacketSize was " + imagePacketSize.ToString() + " on packet " + m_packetNumber.ToString() + " out of " + m_stopPacket.ToString() + ". Exception: " + e.ToString()); | 271 | m_log.ErrorFormat("[J2KIMAGE]: Texture block copy for the first packet failed. textureid={0}, assetlength={1}, currentposition={2}, imagepacketsize={3}, exception={4}", |
272 | TextureID, m_asset.Length, currentPosition, imagePacketSize, e.Message); | ||
276 | return false; | 273 | return false; |
277 | } | 274 | } |
278 | 275 | ||
279 | //Send the packet | 276 | //Send the packet |
280 | client.SendImageNextPart((ushort)(m_packetNumber - 1), m_requestedUUID, imageData); | 277 | client.SendImageNextPart((ushort)(m_currentPacket - 1), TextureID, imageData); |
281 | } | ||
282 | if (complete) | ||
283 | { | ||
284 | return false; | ||
285 | } | ||
286 | else | ||
287 | { | ||
288 | return true; | ||
289 | } | 278 | } |
279 | |||
280 | return !complete; | ||
290 | } | 281 | } |
291 | catch (Exception) | 282 | catch (Exception) |
292 | { | 283 | { |
@@ -294,6 +285,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
294 | } | 285 | } |
295 | } | 286 | } |
296 | 287 | ||
288 | private ushort TexturePacketCount() | ||
289 | { | ||
290 | if (!IsDecoded) | ||
291 | return 0; | ||
292 | |||
293 | if (m_asset == null) | ||
294 | return 0; | ||
295 | |||
296 | if (m_asset.Length <= FIRST_PACKET_SIZE) | ||
297 | return 1; | ||
298 | |||
299 | return (ushort)(((m_asset.Length - FIRST_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1); | ||
300 | } | ||
301 | |||
297 | private int GetPacketForBytePosition(int bytePosition) | 302 | private int GetPacketForBytePosition(int bytePosition) |
298 | { | 303 | { |
299 | return ((bytePosition - FIRST_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1; | 304 | return ((bytePosition - FIRST_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1; |
@@ -301,9 +306,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
301 | 306 | ||
302 | private int LastPacketSize() | 307 | private int LastPacketSize() |
303 | { | 308 | { |
304 | if (m_packetNumber == 1) | 309 | if (m_currentPacket == 1) |
305 | return m_assetDataLength; | 310 | return m_asset.Length; |
306 | int lastsize = (m_assetDataLength - FIRST_PACKET_SIZE) % IMAGE_PACKET_SIZE; | 311 | int lastsize = (m_asset.Length - FIRST_PACKET_SIZE) % IMAGE_PACKET_SIZE; |
307 | //If the last packet size is zero, it's really cImagePacketSize, it sits on the boundary | 312 | //If the last packet size is zero, it's really cImagePacketSize, it sits on the boundary |
308 | if (lastsize == 0) | 313 | if (lastsize == 0) |
309 | { | 314 | { |
@@ -314,12 +319,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
314 | 319 | ||
315 | private int CurrentBytePosition() | 320 | private int CurrentBytePosition() |
316 | { | 321 | { |
317 | if (m_packetNumber == 0) | 322 | if (m_currentPacket == 0) |
318 | return 0; | 323 | return 0; |
319 | if (m_packetNumber == 1) | 324 | if (m_currentPacket == 1) |
320 | return FIRST_PACKET_SIZE; | 325 | return FIRST_PACKET_SIZE; |
321 | 326 | ||
322 | int result = FIRST_PACKET_SIZE + ((int)m_packetNumber - 2) * IMAGE_PACKET_SIZE; | 327 | int result = FIRST_PACKET_SIZE + ((int)m_currentPacket - 2) * IMAGE_PACKET_SIZE; |
323 | if (result < 0) | 328 | if (result < 0) |
324 | { | 329 | { |
325 | result = FIRST_PACKET_SIZE; | 330 | result = FIRST_PACKET_SIZE; |
@@ -327,68 +332,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
327 | return result; | 332 | return result; |
328 | } | 333 | } |
329 | 334 | ||
330 | private bool SendFirstPacket(LLClientView client) | ||
331 | { | ||
332 | // this means we don't have | ||
333 | if (Data == null) | ||
334 | { | ||
335 | client.SendImageNotFound(m_requestedUUID); | ||
336 | m_log.WarnFormat("[TEXTURE]: Got null Data element on a asset {0}.. and the missing image Data property is also null", m_requestedUUID); | ||
337 | return true; | ||
338 | } | ||
339 | // Do we have less then 1 packet's worth of data? | ||
340 | else if (m_assetDataLength <= FIRST_PACKET_SIZE) | ||
341 | { | ||
342 | // Send only 1 packet | ||
343 | client.SendImageFirstPart(1, m_requestedUUID, (uint)m_assetDataLength, m_asset.Data, 2); | ||
344 | m_stopPacket = 0; | ||
345 | return true; | ||
346 | } | ||
347 | else | ||
348 | { | ||
349 | byte[] firstImageData = new byte[FIRST_PACKET_SIZE]; | ||
350 | try | ||
351 | { | ||
352 | Buffer.BlockCopy(m_asset.Data, 0, firstImageData, 0, (int)FIRST_PACKET_SIZE); | ||
353 | client.SendImageFirstPart(TexturePacketCount(), m_requestedUUID, (uint)m_assetDataLength, firstImageData, 2); | ||
354 | } | ||
355 | catch (Exception) | ||
356 | { | ||
357 | m_log.Error("Texture block copy failed. Possibly out of memory?"); | ||
358 | return true; | ||
359 | } | ||
360 | } | ||
361 | return false; | ||
362 | } | ||
363 | |||
364 | private void J2KDecodedCallback(UUID AssetId, OpenJPEG.J2KLayerInfo[] layers) | 335 | private void J2KDecodedCallback(UUID AssetId, OpenJPEG.J2KLayerInfo[] layers) |
365 | { | 336 | { |
366 | m_layers = layers; | 337 | Layers = layers; |
367 | m_decoded = true; | 338 | IsDecoded = true; |
368 | RunUpdate(); | 339 | RunUpdate(); |
369 | } | 340 | } |
370 | 341 | ||
371 | private void AssetDataCallback(UUID AssetID, AssetBase asset) | 342 | private void AssetDataCallback(UUID AssetID, AssetBase asset) |
372 | { | 343 | { |
373 | m_hasasset = true; | 344 | HasAsset = true; |
374 | 345 | ||
375 | if (asset == null || asset.Data == null) | 346 | if (asset == null || asset.Data == null) |
376 | { | 347 | { |
377 | if (m_imageManager.MissingImage != null) | 348 | if (m_imageManager.MissingImage != null) |
378 | { | 349 | { |
379 | m_asset = m_imageManager.MissingImage; | 350 | m_asset = m_imageManager.MissingImage.Data; |
380 | m_assetDataLength = m_asset.Data.Length; | ||
381 | } | 351 | } |
382 | else | 352 | else |
383 | { | 353 | { |
384 | m_asset = null; | 354 | m_asset = null; |
385 | m_decoded = true; | 355 | IsDecoded = true; |
386 | } | 356 | } |
387 | } | 357 | } |
388 | else | 358 | else |
389 | { | 359 | { |
390 | m_asset = asset; | 360 | m_asset = asset.Data; |
391 | m_assetDataLength = m_asset.Data.Length; | ||
392 | } | 361 | } |
393 | 362 | ||
394 | RunUpdate(); | 363 | RunUpdate(); |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 3b43771..0052729 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -4751,7 +4751,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4751 | { | 4751 | { |
4752 | Hashtable mp = (Hashtable)simMapProfiles[iii]; | 4752 | Hashtable mp = (Hashtable)simMapProfiles[iii]; |
4753 | mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); | 4753 | mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock(); |
4754 | mbReply.Data[iii].Name = System.Text.Encoding.UTF8.GetBytes((string)mp["name"]); | 4754 | mbReply.Data[iii].Name = Util.UTF8.GetBytes((string)mp["name"]); |
4755 | mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); | 4755 | mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]); |
4756 | mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); | 4756 | mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]); |
4757 | mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]); | 4757 | mbReply.Data[iii].MapImageID = new UUID((string)mp["map-image-id"]); |
@@ -7341,7 +7341,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
7341 | } | 7341 | } |
7342 | #endregion | 7342 | #endregion |
7343 | 7343 | ||
7344 | string mapName = Encoding.UTF8.GetString(map.NameData.Name, 0, | 7344 | string mapName = Util.UTF8.GetString(map.NameData.Name, 0, |
7345 | map.NameData.Name.Length - 1); | 7345 | map.NameData.Name.Length - 1); |
7346 | handlerMapNameRequest = OnMapNameRequest; | 7346 | handlerMapNameRequest = OnMapNameRequest; |
7347 | if (handlerMapNameRequest != null) | 7347 | if (handlerMapNameRequest != null) |
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs index a484fdf..2120d33 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs | |||
@@ -45,48 +45,43 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
45 | { | 45 | { |
46 | public int Compare(J2KImage x, J2KImage y) | 46 | public int Compare(J2KImage x, J2KImage y) |
47 | { | 47 | { |
48 | return x.m_requestedPriority.CompareTo(y.m_requestedPriority); | 48 | return x.Priority.CompareTo(y.Priority); |
49 | } | 49 | } |
50 | } | 50 | } |
51 | 51 | ||
52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
53 | private bool m_shuttingdown = false; | 53 | private bool m_shuttingdown; |
54 | private long m_lastloopprocessed = 0; | 54 | private long m_lastloopprocessed; |
55 | private AssetBase m_missingImage = null; | 55 | private AssetBase m_missingImage; |
56 | |||
57 | private LLClientView m_client; //Client we're assigned to | 56 | private LLClientView m_client; //Client we're assigned to |
58 | private IAssetService m_assetCache; //Asset Cache | 57 | private IAssetService m_assetCache; //Asset Cache |
59 | private IJ2KDecoder m_j2kDecodeModule; //Our J2K module | 58 | private IJ2KDecoder m_j2kDecodeModule; //Our J2K module |
60 | private C5.IntervalHeap<J2KImage> m_priorityQueue = new C5.IntervalHeap<J2KImage>(10, new J2KImageComparer()); | 59 | private C5.IntervalHeap<J2KImage> m_priorityQueue = new C5.IntervalHeap<J2KImage>(10, new J2KImageComparer()); |
60 | private object m_syncRoot = new object(); | ||
61 | |||
62 | public LLClientView Client { get { return m_client; } } | ||
63 | public AssetBase MissingImage { get { return m_missingImage; } } | ||
61 | 64 | ||
62 | public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) | 65 | public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) |
63 | { | 66 | { |
64 | m_client = client; | 67 | m_client = client; |
65 | m_assetCache = pAssetCache; | 68 | m_assetCache = pAssetCache; |
69 | |||
66 | if (pAssetCache != null) | 70 | if (pAssetCache != null) |
67 | m_missingImage = pAssetCache.Get("5748decc-f629-461c-9a36-a35a221fe21f"); | 71 | m_missingImage = pAssetCache.Get("5748decc-f629-461c-9a36-a35a221fe21f"); |
68 | else | 72 | |
69 | m_log.Error("[ClientView] - couldn't set missing image asset, falling back to missing image packet. This is known to crash the client"); | 73 | if (m_missingImage == null) |
74 | m_log.Error("[ClientView] - Couldn't set missing image asset, falling back to missing image packet. This is known to crash the client"); | ||
70 | 75 | ||
71 | m_j2kDecodeModule = pJ2kDecodeModule; | 76 | m_j2kDecodeModule = pJ2kDecodeModule; |
72 | } | 77 | } |
73 | 78 | ||
74 | public LLClientView Client | 79 | /// <summary> |
75 | { | 80 | /// Handles an incoming texture request or update to an existing texture request |
76 | get { return m_client; } | 81 | /// </summary> |
77 | } | 82 | /// <param name="newRequest"></param> |
78 | |||
79 | public AssetBase MissingImage | ||
80 | { | ||
81 | get { return m_missingImage; } | ||
82 | } | ||
83 | |||
84 | public void EnqueueReq(TextureRequestArgs newRequest) | 83 | public void EnqueueReq(TextureRequestArgs newRequest) |
85 | { | 84 | { |
86 | //newRequest is the properties of our new texture fetch request. | ||
87 | //Basically, here is where we queue up "new" requests.. | ||
88 | // .. or modify existing requests to suit. | ||
89 | |||
90 | //Make sure we're not shutting down.. | 85 | //Make sure we're not shutting down.. |
91 | if (!m_shuttingdown) | 86 | if (!m_shuttingdown) |
92 | { | 87 | { |
@@ -94,7 +89,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
94 | 89 | ||
95 | // Do a linear search for this texture download | 90 | // Do a linear search for this texture download |
96 | lock (m_priorityQueue) | 91 | lock (m_priorityQueue) |
97 | m_priorityQueue.Find(delegate(J2KImage img) { return img.m_requestedUUID == newRequest.RequestedAssetID; }, out imgrequest); | 92 | m_priorityQueue.Find(delegate(J2KImage img) { return img.TextureID == newRequest.RequestedAssetID; }, out imgrequest); |
98 | 93 | ||
99 | if (imgrequest != null) | 94 | if (imgrequest != null) |
100 | { | 95 | { |
@@ -105,7 +100,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
105 | try | 100 | try |
106 | { | 101 | { |
107 | lock (m_priorityQueue) | 102 | lock (m_priorityQueue) |
108 | m_priorityQueue.Delete(imgrequest.m_priorityQueueHandle); | 103 | m_priorityQueue.Delete(imgrequest.PriorityQueueHandle); |
109 | } | 104 | } |
110 | catch (Exception) { } | 105 | catch (Exception) { } |
111 | } | 106 | } |
@@ -116,30 +111,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
116 | 111 | ||
117 | //Check the packet sequence to make sure this isn't older than | 112 | //Check the packet sequence to make sure this isn't older than |
118 | //one we've already received | 113 | //one we've already received |
119 | if (newRequest.requestSequence > imgrequest.m_lastSequence) | 114 | if (newRequest.requestSequence > imgrequest.LastSequence) |
120 | { | 115 | { |
121 | //Update the sequence number of the last RequestImage packet | 116 | //Update the sequence number of the last RequestImage packet |
122 | imgrequest.m_lastSequence = newRequest.requestSequence; | 117 | imgrequest.LastSequence = newRequest.requestSequence; |
123 | 118 | ||
124 | //Update the requested discard level | 119 | //Update the requested discard level |
125 | imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel; | 120 | imgrequest.DiscardLevel = newRequest.DiscardLevel; |
126 | 121 | ||
127 | //Update the requested packet number | 122 | //Update the requested packet number |
128 | imgrequest.m_requestedPacketNumber = newRequest.PacketNumber; | 123 | imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); |
129 | 124 | ||
130 | //Update the requested priority | 125 | //Update the requested priority |
131 | imgrequest.m_requestedPriority = newRequest.Priority; | 126 | imgrequest.Priority = newRequest.Priority; |
132 | try | 127 | UpdateImageInQueue(imgrequest); |
133 | { | ||
134 | lock (m_priorityQueue) | ||
135 | m_priorityQueue.Replace(imgrequest.m_priorityQueueHandle, imgrequest); | ||
136 | } | ||
137 | catch (Exception) | ||
138 | { | ||
139 | imgrequest.m_priorityQueueHandle = null; | ||
140 | lock (m_priorityQueue) | ||
141 | m_priorityQueue.Add(ref imgrequest.m_priorityQueueHandle, imgrequest); | ||
142 | } | ||
143 | 128 | ||
144 | //Run an update | 129 | //Run an update |
145 | imgrequest.RunUpdate(); | 130 | imgrequest.RunUpdate(); |
@@ -159,31 +144,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
159 | // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); | 144 | // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); |
160 | 145 | ||
161 | imgrequest = new J2KImage(this); | 146 | imgrequest = new J2KImage(this); |
162 | 147 | imgrequest.J2KDecoder = m_j2kDecodeModule; | |
163 | //Assign our decoder module | 148 | imgrequest.AssetService = m_assetCache; |
164 | imgrequest.m_j2kDecodeModule = m_j2kDecodeModule; | 149 | imgrequest.DiscardLevel = newRequest.DiscardLevel; |
165 | 150 | imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); | |
166 | //Assign our asset cache module | 151 | imgrequest.Priority = newRequest.Priority; |
167 | imgrequest.m_assetCache = m_assetCache; | 152 | imgrequest.TextureID = newRequest.RequestedAssetID; |
168 | 153 | imgrequest.Priority = newRequest.Priority; | |
169 | //Assign the requested discard level | ||
170 | imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel; | ||
171 | |||
172 | //Assign the requested packet number | ||
173 | imgrequest.m_requestedPacketNumber = newRequest.PacketNumber; | ||
174 | |||
175 | //Assign the requested priority | ||
176 | imgrequest.m_requestedPriority = newRequest.Priority; | ||
177 | |||
178 | //Assign the asset uuid | ||
179 | imgrequest.m_requestedUUID = newRequest.RequestedAssetID; | ||
180 | |||
181 | //Assign the requested priority | ||
182 | imgrequest.m_requestedPriority = newRequest.Priority; | ||
183 | 154 | ||
184 | //Add this download to the priority queue | 155 | //Add this download to the priority queue |
185 | lock (m_priorityQueue) | 156 | AddImageToQueue(imgrequest); |
186 | m_priorityQueue.Add(ref imgrequest.m_priorityQueueHandle, imgrequest); | ||
187 | 157 | ||
188 | //Run an update | 158 | //Run an update |
189 | imgrequest.RunUpdate(); | 159 | imgrequest.RunUpdate(); |
@@ -194,105 +164,99 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
194 | 164 | ||
195 | public bool ProcessImageQueue(int count, int maxpack) | 165 | public bool ProcessImageQueue(int count, int maxpack) |
196 | { | 166 | { |
197 | lock (this) | 167 | J2KImage imagereq; |
198 | { | 168 | int numCollected = 0; |
199 | //count is the number of textures we want to process in one go. | ||
200 | //As part of this class re-write, that number will probably rise | ||
201 | //since we're processing in a more efficient manner. | ||
202 | |||
203 | // this can happen during Close() | ||
204 | if (m_client == null) | ||
205 | return false; | ||
206 | |||
207 | int numCollected = 0; | ||
208 | |||
209 | //Calculate our threshold | ||
210 | int threshold; | ||
211 | if (m_lastloopprocessed == 0) | ||
212 | { | ||
213 | if (m_client.PacketHandler == null || m_client.PacketHandler.PacketQueue == null || m_client.PacketHandler.PacketQueue.TextureThrottle == null) | ||
214 | return false; | ||
215 | //This is decent for a semi fast machine, but we'll calculate it more accurately based on time below | ||
216 | threshold = m_client.PacketHandler.PacketQueue.TextureThrottle.Current / 6300; | ||
217 | m_lastloopprocessed = DateTime.Now.Ticks; | ||
218 | } | ||
219 | else | ||
220 | { | ||
221 | double throttleseconds = ((double)DateTime.Now.Ticks - (double)m_lastloopprocessed) / (double)TimeSpan.TicksPerSecond; | ||
222 | throttleseconds = throttleseconds * m_client.PacketHandler.PacketQueue.TextureThrottle.Current; | ||
223 | |||
224 | //Average of 1000 bytes per packet | ||
225 | throttleseconds = throttleseconds / 1000; | ||
226 | |||
227 | //Safe-zone multiplier of 2.0 | ||
228 | threshold = (int)(throttleseconds * 2.0); | ||
229 | m_lastloopprocessed = DateTime.Now.Ticks; | ||
230 | |||
231 | } | ||
232 | 169 | ||
233 | if (m_client.PacketHandler == null) | 170 | //lock (m_syncRoot) |
234 | return false; | 171 | //{ |
172 | m_lastloopprocessed = DateTime.Now.Ticks; | ||
235 | 173 | ||
236 | if (m_client.PacketHandler.PacketQueue == null) | 174 | // This can happen during Close() |
175 | if (m_client == null || m_client.PacketHandler == null || m_client.PacketHandler.PacketQueue == null) | ||
237 | return false; | 176 | return false; |
238 | 177 | ||
239 | if (threshold < 10) | 178 | while ((imagereq = GetHighestPriorityImage()) != null) |
240 | threshold = 10; | ||
241 | |||
242 | //Uncomment this to see what the texture stack is doing | ||
243 | //m_log.Debug("Queue: " + m_client.PacketHandler.PacketQueue.getQueueCount(ThrottleOutPacketType.Texture).ToString() + " Threshold: " + threshold.ToString() + " outstanding: " + m_outstandingtextures.ToString()); | ||
244 | if (true) //m_client.PacketHandler.PacketQueue.GetQueueCount(ThrottleOutPacketType.Texture) < threshold) | ||
245 | { | 179 | { |
246 | while (m_priorityQueue.Count > 0) | 180 | if (imagereq.IsDecoded == true) |
247 | { | 181 | { |
248 | J2KImage imagereq = null; | 182 | ++numCollected; |
249 | lock (m_priorityQueue) | ||
250 | imagereq = m_priorityQueue.FindMax(); | ||
251 | 183 | ||
252 | if (imagereq.m_decoded == true) | 184 | if (imagereq.SendPackets(m_client, maxpack)) |
253 | { | 185 | { |
254 | // we need to test this here now that we are dropping assets | 186 | // Send complete. Destroy any knowledge of this transfer |
255 | if (!imagereq.m_hasasset) | 187 | RemoveImageFromQueue(imagereq); |
256 | { | ||
257 | m_log.WarnFormat("[LLIMAGE MANAGER]: Re-requesting the image asset {0}", imagereq.m_requestedUUID); | ||
258 | imagereq.RunUpdate(); | ||
259 | continue; | ||
260 | } | ||
261 | |||
262 | ++numCollected; | ||
263 | |||
264 | //SendPackets will send up to ten packets per cycle | ||
265 | if (imagereq.SendPackets(m_client, maxpack)) | ||
266 | { | ||
267 | // Send complete. Destroy any knowledge of this transfer | ||
268 | try | ||
269 | { | ||
270 | lock (m_priorityQueue) | ||
271 | m_priorityQueue.Delete(imagereq.m_priorityQueueHandle); | ||
272 | } | ||
273 | catch (Exception) { } | ||
274 | } | ||
275 | } | 188 | } |
276 | |||
277 | if (numCollected == count) | ||
278 | break; | ||
279 | } | 189 | } |
190 | |||
191 | if (numCollected == count) | ||
192 | break; | ||
280 | } | 193 | } |
194 | //} | ||
281 | 195 | ||
282 | return m_priorityQueue.Count > 0; | 196 | return m_priorityQueue.Count > 0; |
283 | } | ||
284 | } | 197 | } |
285 | 198 | ||
286 | //Faux destructor | 199 | //Faux destructor |
287 | public void Close() | 200 | public void Close() |
288 | { | 201 | { |
289 | |||
290 | m_shuttingdown = true; | 202 | m_shuttingdown = true; |
291 | m_j2kDecodeModule = null; | 203 | m_j2kDecodeModule = null; |
292 | m_assetCache = null; | 204 | m_assetCache = null; |
293 | m_client = null; | 205 | m_client = null; |
294 | } | 206 | } |
295 | 207 | ||
208 | #region Priority Queue Helpers | ||
209 | |||
210 | J2KImage GetHighestPriorityImage() | ||
211 | { | ||
212 | J2KImage image = null; | ||
213 | |||
214 | lock (m_priorityQueue) | ||
215 | { | ||
216 | |||
217 | if (m_priorityQueue.Count > 0) | ||
218 | { | ||
219 | try | ||
220 | { | ||
221 | image = m_priorityQueue.FindMax(); | ||
222 | } | ||
223 | catch (Exception) { } | ||
224 | } | ||
225 | } | ||
226 | return image; | ||
227 | } | ||
228 | |||
229 | void AddImageToQueue(J2KImage image) | ||
230 | { | ||
231 | image.PriorityQueueHandle = null; | ||
232 | |||
233 | lock (m_priorityQueue) | ||
234 | m_priorityQueue.Add(ref image.PriorityQueueHandle, image); | ||
235 | } | ||
236 | |||
237 | void RemoveImageFromQueue(J2KImage image) | ||
238 | { | ||
239 | try | ||
240 | { | ||
241 | lock (m_priorityQueue) | ||
242 | m_priorityQueue.Delete(image.PriorityQueueHandle); | ||
243 | } | ||
244 | catch (Exception) { } | ||
245 | } | ||
246 | |||
247 | void UpdateImageInQueue(J2KImage image) | ||
248 | { | ||
249 | lock (m_priorityQueue) | ||
250 | { | ||
251 | try { m_priorityQueue.Replace(image.PriorityQueueHandle, image); } | ||
252 | catch (Exception) | ||
253 | { | ||
254 | image.PriorityQueueHandle = null; | ||
255 | m_priorityQueue.Add(ref image.PriorityQueueHandle, image); | ||
256 | } | ||
257 | } | ||
258 | } | ||
296 | 259 | ||
260 | #endregion Priority Queue Helpers | ||
297 | } | 261 | } |
298 | } | 262 | } |
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs index a0f359b..7456e8c 100644 --- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs +++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs | |||
@@ -257,7 +257,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
257 | stringResult.AppendFormat("{0}|{1}|{2}{3}", Layers[i].Start, Layers[i].End, Layers[i].End - Layers[i].Start, strEnd); | 257 | stringResult.AppendFormat("{0}|{1}|{2}{3}", Layers[i].Start, Layers[i].End, Layers[i].End - Layers[i].Start, strEnd); |
258 | } | 258 | } |
259 | 259 | ||
260 | layerDecodeAsset.Data = Encoding.UTF8.GetBytes(stringResult.ToString()); | 260 | layerDecodeAsset.Data = Util.UTF8.GetBytes(stringResult.ToString()); |
261 | 261 | ||
262 | #endregion Serialize Layer Data | 262 | #endregion Serialize Layer Data |
263 | 263 | ||
@@ -280,7 +280,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender | |||
280 | { | 280 | { |
281 | #region Deserialize Layer Data | 281 | #region Deserialize Layer Data |
282 | 282 | ||
283 | string readResult = Encoding.UTF8.GetString(layerDecodeAsset.Data); | 283 | string readResult = Util.UTF8.GetString(layerDecodeAsset.Data); |
284 | string[] lines = readResult.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); | 284 | string[] lines = readResult.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); |
285 | 285 | ||
286 | if (lines.Length == 0) | 286 | if (lines.Length == 0) |
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 817e0d4..c0bb70c 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | |||
@@ -323,13 +323,13 @@ namespace Flotsam.RegionModules.AssetCache | |||
323 | string filename = GetFileName(id); | 323 | string filename = GetFileName(id); |
324 | if (File.Exists(filename)) | 324 | if (File.Exists(filename)) |
325 | { | 325 | { |
326 | FileStream stream = null; | ||
326 | try | 327 | try |
327 | { | 328 | { |
328 | FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); | 329 | stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); |
329 | BinaryFormatter bformatter = new BinaryFormatter(); | 330 | BinaryFormatter bformatter = new BinaryFormatter(); |
330 | 331 | ||
331 | asset = (AssetBase)bformatter.Deserialize(stream); | 332 | asset = (AssetBase)bformatter.Deserialize(stream); |
332 | stream.Close(); | ||
333 | 333 | ||
334 | UpdateMemoryCache(id, asset); | 334 | UpdateMemoryCache(id, asset); |
335 | 335 | ||
@@ -349,6 +349,11 @@ namespace Flotsam.RegionModules.AssetCache | |||
349 | { | 349 | { |
350 | LogException(e); | 350 | LogException(e); |
351 | } | 351 | } |
352 | finally | ||
353 | { | ||
354 | if (stream != null) | ||
355 | stream.Close(); | ||
356 | } | ||
352 | } | 357 | } |
353 | 358 | ||
354 | 359 | ||
@@ -493,19 +498,20 @@ namespace Flotsam.RegionModules.AssetCache | |||
493 | 498 | ||
494 | private void WriteFileCache(string filename, AssetBase asset) | 499 | private void WriteFileCache(string filename, AssetBase asset) |
495 | { | 500 | { |
501 | Stream stream = null; | ||
502 | // Make sure the target cache directory exists | ||
503 | string directory = Path.GetDirectoryName(filename); | ||
504 | // Write file first to a temp name, so that it doesn't look | ||
505 | // like it's already cached while it's still writing. | ||
506 | string tempname = Path.Combine(directory, Path.GetRandomFileName()); | ||
496 | try | 507 | try |
497 | { | 508 | { |
498 | // Make sure the target cache directory exists | ||
499 | string directory = Path.GetDirectoryName(filename); | ||
500 | if (!Directory.Exists(directory)) | 509 | if (!Directory.Exists(directory)) |
501 | { | 510 | { |
502 | Directory.CreateDirectory(directory); | 511 | Directory.CreateDirectory(directory); |
503 | } | 512 | } |
504 | 513 | ||
505 | // Write file first to a temp name, so that it doesn't look | 514 | stream = File.Open(tempname, FileMode.Create); |
506 | // like it's already cached while it's still writing. | ||
507 | string tempname = Path.Combine(directory, Path.GetRandomFileName()); | ||
508 | Stream stream = File.Open(tempname, FileMode.Create); | ||
509 | BinaryFormatter bformatter = new BinaryFormatter(); | 515 | BinaryFormatter bformatter = new BinaryFormatter(); |
510 | bformatter.Serialize(stream, asset); | 516 | bformatter.Serialize(stream, asset); |
511 | stream.Close(); | 517 | stream.Close(); |
@@ -522,6 +528,9 @@ namespace Flotsam.RegionModules.AssetCache | |||
522 | } | 528 | } |
523 | finally | 529 | finally |
524 | { | 530 | { |
531 | if (stream != null) | ||
532 | stream.Close(); | ||
533 | |||
525 | // Even if the write fails with an exception, we need to make sure | 534 | // Even if the write fails with an exception, we need to make sure |
526 | // that we release the lock on that file, otherwise it'll never get | 535 | // that we release the lock on that file, otherwise it'll never get |
527 | // cached | 536 | // cached |
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 50d7c97..45e724d 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | |||
@@ -367,7 +367,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
367 | // Encode outbound data | 367 | // Encode outbound data |
368 | if (OutboundBody.Length > 0) | 368 | if (OutboundBody.Length > 0) |
369 | { | 369 | { |
370 | byte[] data = Encoding.UTF8.GetBytes(OutboundBody); | 370 | byte[] data = Util.UTF8.GetBytes(OutboundBody); |
371 | 371 | ||
372 | Request.ContentLength = data.Length; | 372 | Request.ContentLength = data.Length; |
373 | Stream bstream = Request.GetRequestStream(); | 373 | Stream bstream = Request.GetRequestStream(); |
@@ -390,7 +390,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
390 | if (count != 0) | 390 | if (count != 0) |
391 | { | 391 | { |
392 | // translate from bytes to ASCII text | 392 | // translate from bytes to ASCII text |
393 | tempString = Encoding.UTF8.GetString(buf, 0, count); | 393 | tempString = Util.UTF8.GetString(buf, 0, count); |
394 | 394 | ||
395 | // continue building the string | 395 | // continue building the string |
396 | sb.Append(tempString); | 396 | sb.Append(tempString); |
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 040d0a3..901144a 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | |||
@@ -397,10 +397,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
397 | // with the powers requested (powers = 0 for no powers check) | 397 | // with the powers requested (powers = 0 for no powers check) |
398 | protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers) | 398 | protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers) |
399 | { | 399 | { |
400 | IClientAPI client = m_scene.GetScenePresence(userID).ControllingClient; | 400 | ScenePresence sp = m_scene.GetScenePresence(userID); |
401 | 401 | if (sp != null) | |
402 | return ((groupID == client.ActiveGroupId) && (client.ActiveGroupPowers != 0) && | 402 | { |
403 | ((powers == 0) || ((client.ActiveGroupPowers & powers) == powers))); | 403 | IClientAPI client = sp.ControllingClient; |
404 | |||
405 | return ((groupID == client.ActiveGroupId) && (client.ActiveGroupPowers != 0) && | ||
406 | ((powers == 0) || ((client.ActiveGroupPowers & powers) == powers))); | ||
407 | } | ||
408 | return false; | ||
404 | } | 409 | } |
405 | 410 | ||
406 | /// <summary> | 411 | /// <summary> |
@@ -576,9 +581,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
576 | return objectOwnerMask; | 581 | return objectOwnerMask; |
577 | } | 582 | } |
578 | 583 | ||
584 | if ((objectOwnerMask & (uint)PermissionMask.Transfer) != 0 && task.ObjectSaleType != 0) | ||
585 | objectEveryoneMask |= (uint)PrimFlags.ObjectTransfer; | ||
586 | |||
579 | // Group permissions | 587 | // Group permissions |
580 | if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) | 588 | if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) |
581 | return objectGroupMask; | 589 | return objectGroupMask | objectEveryoneMask; |
582 | 590 | ||
583 | return objectEveryoneMask; | 591 | return objectEveryoneMask; |
584 | } | 592 | } |
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs index 3eb7cd2..a70ef13 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs | |||
@@ -36,10 +36,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders | |||
36 | { | 36 | { |
37 | public struct HeightmapLookupValue : IComparable<HeightmapLookupValue> | 37 | public struct HeightmapLookupValue : IComparable<HeightmapLookupValue> |
38 | { | 38 | { |
39 | public int Index; | 39 | public ushort Index; |
40 | public double Value; | 40 | public float Value; |
41 | 41 | ||
42 | public HeightmapLookupValue(int index, double value) | 42 | public HeightmapLookupValue(ushort index, float value) |
43 | { | 43 | { |
44 | Index = index; | 44 | Index = index; |
45 | Value = value; | 45 | Value = value; |
@@ -62,7 +62,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders | |||
62 | { | 62 | { |
63 | for (int j = 0; j < 256; j++) | 63 | for (int j = 0; j < 256; j++) |
64 | { | 64 | { |
65 | LookupHeightTable[i + (j * 256)] = new HeightmapLookupValue(i + (j * 256), ((double)i * ((double)j / 128.0d))); | 65 | LookupHeightTable[i + (j * 256)] = new HeightmapLookupValue((ushort)(i + (j * 256)), (float)((double)i * ((double)j / 128.0d))); |
66 | } | 66 | } |
67 | } | 67 | } |
68 | Array.Sort<HeightmapLookupValue>(LookupHeightTable); | 68 | Array.Sort<HeightmapLookupValue>(LookupHeightTable); |
@@ -196,7 +196,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders | |||
196 | 196 | ||
197 | // The lookup table is pre-sorted, so we either find an exact match or | 197 | // The lookup table is pre-sorted, so we either find an exact match or |
198 | // the next closest (smaller) match with a binary search | 198 | // the next closest (smaller) match with a binary search |
199 | index = Array.BinarySearch<HeightmapLookupValue>(LookupHeightTable, new HeightmapLookupValue(0, t)); | 199 | index = Array.BinarySearch<HeightmapLookupValue>(LookupHeightTable, new HeightmapLookupValue(0, (float)t)); |
200 | if (index < 0) | 200 | if (index < 0) |
201 | index = ~index - 1; | 201 | index = ~index - 1; |
202 | 202 | ||
diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs index 080bd5a..4df9094 100644 --- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs +++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs | |||
@@ -352,7 +352,7 @@ namespace OpenSim.Region.DataSnapshot | |||
352 | m_log.WarnFormat("[DATASNAPSHOT]: Unable to decode reply from data service. Ignoring. {0}", e.StackTrace); | 352 | m_log.WarnFormat("[DATASNAPSHOT]: Unable to decode reply from data service. Ignoring. {0}", e.StackTrace); |
353 | } | 353 | } |
354 | // This is not quite working, so... | 354 | // This is not quite working, so... |
355 | // string responseStr = Encoding.UTF8.GetString(response); | 355 | // string responseStr = Util.UTF8.GetString(response); |
356 | m_log.Info("[DATASNAPSHOT]: data service notified: " + url); | 356 | m_log.Info("[DATASNAPSHOT]: data service notified: " + url); |
357 | } | 357 | } |
358 | 358 | ||
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs index 73f918e..e9660b1 100644 --- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs +++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs | |||
@@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
73 | 73 | ||
74 | public byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) | 74 | public byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) |
75 | { | 75 | { |
76 | return Encoding.UTF8.GetBytes(Report()); | 76 | return Util.UTF8.GetBytes(Report()); |
77 | } | 77 | } |
78 | 78 | ||
79 | public string ContentType | 79 | public string ContentType |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b4cfc48..23a7021 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -1332,7 +1332,8 @@ if (m_shape != null) { | |||
1332 | bool RigidBody = isPhysical && !isPhantom; | 1332 | bool RigidBody = isPhysical && !isPhantom; |
1333 | 1333 | ||
1334 | // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition | 1334 | // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition |
1335 | if (!isPhantom && !IsAttachment) | 1335 | // or flexible |
1336 | if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) | ||
1336 | { | 1337 | { |
1337 | PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( | 1338 | PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( |
1338 | Name, | 1339 | Name, |
@@ -3395,8 +3396,8 @@ if (m_shape != null) { | |||
3395 | } | 3396 | } |
3396 | } | 3397 | } |
3397 | 3398 | ||
3398 | 3399 | ||
3399 | if (IsPhantom || IsAttachment) // note: this may have been changed above in the case of joints | 3400 | if (IsPhantom || IsAttachment || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints |
3400 | { | 3401 | { |
3401 | AddFlag(PrimFlags.Phantom); | 3402 | AddFlag(PrimFlags.Phantom); |
3402 | if (PhysActor != null) | 3403 | if (PhysActor != null) |
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs index 8209ff6..ca6210d 100644 --- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs +++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs | |||
@@ -172,7 +172,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
172 | public string SaveToXmlString() | 172 | public string SaveToXmlString() |
173 | { | 173 | { |
174 | XmlWriterSettings settings = new XmlWriterSettings(); | 174 | XmlWriterSettings settings = new XmlWriterSettings(); |
175 | settings.Encoding = Encoding.UTF8; | 175 | settings.Encoding = Util.UTF8; |
176 | using (StringWriter sw = new StringWriter()) | 176 | using (StringWriter sw = new StringWriter()) |
177 | { | 177 | { |
178 | using (XmlWriter writer = XmlWriter.Create(sw, settings)) | 178 | using (XmlWriter writer = XmlWriter.Create(sw, settings)) |
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index ee2d2db..4364627 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs | |||
@@ -81,7 +81,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
81 | { | 81 | { |
82 | m_log.Info("[IRCd] Sending >>> " + command); | 82 | m_log.Info("[IRCd] Sending >>> " + command); |
83 | 83 | ||
84 | byte[] buf = Encoding.UTF8.GetBytes(command + "\r\n"); | 84 | byte[] buf = Util.UTF8.GetBytes(command + "\r\n"); |
85 | 85 | ||
86 | m_client.GetStream().BeginWrite(buf, 0, buf.Length, SendComplete, null); | 86 | m_client.GetStream().BeginWrite(buf, 0, buf.Length, SendComplete, null); |
87 | } | 87 | } |
@@ -109,7 +109,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
109 | byte[] buf = new byte[8]; // RFC1459 defines max message size as 512. | 109 | byte[] buf = new byte[8]; // RFC1459 defines max message size as 512. |
110 | 110 | ||
111 | int count = m_client.GetStream().Read(buf, 0, buf.Length); | 111 | int count = m_client.GetStream().Read(buf, 0, buf.Length); |
112 | string line = Encoding.UTF8.GetString(buf, 0, count); | 112 | string line = Util.UTF8.GetString(buf, 0, count); |
113 | 113 | ||
114 | strbuf += line; | 114 | strbuf += line; |
115 | 115 | ||
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index c7bb56a..b04b076 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | |||
@@ -559,7 +559,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
559 | 559 | ||
560 | if (method == "POST") | 560 | if (method == "POST") |
561 | { | 561 | { |
562 | byte[] contentreq = Encoding.UTF8.GetBytes(body); | 562 | byte[] contentreq = Util.UTF8.GetBytes(body); |
563 | forwardreq.ContentLength = contentreq.Length; | 563 | forwardreq.ContentLength = contentreq.Length; |
564 | Stream reqStream = forwardreq.GetRequestStream(); | 564 | Stream reqStream = forwardreq.GetRequestStream(); |
565 | reqStream.Write(contentreq, 0, contentreq.Length); | 565 | reqStream.Write(contentreq, 0, contentreq.Length); |
@@ -567,7 +567,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice | |||
567 | } | 567 | } |
568 | 568 | ||
569 | HttpWebResponse fwdrsp = (HttpWebResponse)forwardreq.GetResponse(); | 569 | HttpWebResponse fwdrsp = (HttpWebResponse)forwardreq.GetResponse(); |
570 | Encoding encoding = Encoding.UTF8; | 570 | Encoding encoding = Util.UTF8; |
571 | StreamReader fwdresponsestream = new StreamReader(fwdrsp.GetResponseStream(), encoding); | 571 | StreamReader fwdresponsestream = new StreamReader(fwdrsp.GetResponseStream(), encoding); |
572 | fwdresponsestr = fwdresponsestream.ReadToEnd(); | 572 | fwdresponsestr = fwdresponsestream.ReadToEnd(); |
573 | fwdresponsecontenttype = fwdrsp.ContentType; | 573 | fwdresponsecontenttype = fwdrsp.ContentType; |
diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs index 3044b17..e3fbb6e 100644 --- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs +++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs | |||
@@ -539,7 +539,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator | |||
539 | { | 539 | { |
540 | XmlSerializer xs = new XmlSerializer(typeof(Copse)); | 540 | XmlSerializer xs = new XmlSerializer(typeof(Copse)); |
541 | 541 | ||
542 | using (XmlTextWriter writer = new XmlTextWriter(fileName, System.Text.Encoding.UTF8)) | 542 | using (XmlTextWriter writer = new XmlTextWriter(fileName, Util.UTF8)) |
543 | { | 543 | { |
544 | writer.Formatting = Formatting.Indented; | 544 | writer.Formatting = Formatting.Indented; |
545 | xs.Serialize(writer, obj); | 545 | xs.Serialize(writer, obj); |
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index d56ddc8..0e29ccc 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -224,6 +224,14 @@ namespace OpenSim.Region.Physics.Meshing | |||
224 | for (int i = 0; i < lodBytes.Length; i++) | 224 | for (int i = 0; i < lodBytes.Length; i++) |
225 | hash = djb2(hash, lodBytes[i]); | 225 | hash = djb2(hash, lodBytes[i]); |
226 | 226 | ||
227 | // include sculpt UUID | ||
228 | if (pbs.SculptEntry) | ||
229 | { | ||
230 | scaleBytes = pbs.SculptTexture.GetBytes(); | ||
231 | for (int i = 0; i < scaleBytes.Length; i++) | ||
232 | hash = djb2(hash, scaleBytes[i]); | ||
233 | } | ||
234 | |||
227 | return hash; | 235 | return hash; |
228 | } | 236 | } |
229 | 237 | ||
@@ -330,7 +338,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
330 | bool invert = ((primShape.SculptType & 64) != 0); | 338 | bool invert = ((primShape.SculptType & 64) != 0); |
331 | 339 | ||
332 | sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); | 340 | sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); |
333 | 341 | ||
334 | idata.Dispose(); | 342 | idata.Dispose(); |
335 | 343 | ||
336 | sculptMesh.DumpRaw(baseDir, primName, "primMesh"); | 344 | sculptMesh.DumpRaw(baseDir, primName, "primMesh"); |
@@ -389,7 +397,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
389 | primMesh.pathCutBegin = pathBegin; | 397 | primMesh.pathCutBegin = pathBegin; |
390 | primMesh.pathCutEnd = pathEnd; | 398 | primMesh.pathCutEnd = pathEnd; |
391 | 399 | ||
392 | if (primShape.PathCurve == (byte)Extrusion.Straight) | 400 | if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible) |
393 | { | 401 | { |
394 | primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10; | 402 | primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10; |
395 | primMesh.twistEnd = primShape.PathTwist * 18 / 10; | 403 | primMesh.twistEnd = primShape.PathTwist * 18 / 10; |
@@ -484,12 +492,18 @@ namespace OpenSim.Region.Physics.Meshing | |||
484 | 492 | ||
485 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod, bool isPhysical) | 493 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod, bool isPhysical) |
486 | { | 494 | { |
495 | Mesh mesh = null; | ||
496 | ulong key = 0; | ||
497 | |||
487 | // If this mesh has been created already, return it instead of creating another copy | 498 | // If this mesh has been created already, return it instead of creating another copy |
488 | // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory | 499 | // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory |
489 | ulong key = GetMeshKey(primShape, size, lod); | 500 | |
490 | Mesh mesh = null; | 501 | if (! primShape.SculptEntry) |
491 | if (m_uniqueMeshes.TryGetValue(key, out mesh)) | 502 | { |
492 | return mesh; | 503 | key = GetMeshKey(primShape, size, lod); |
504 | if (m_uniqueMeshes.TryGetValue(key, out mesh)) | ||
505 | return mesh; | ||
506 | } | ||
493 | 507 | ||
494 | if (size.X < 0.01f) size.X = 0.01f; | 508 | if (size.X < 0.01f) size.X = 0.01f; |
495 | if (size.Y < 0.01f) size.Y = 0.01f; | 509 | if (size.Y < 0.01f) size.Y = 0.01f; |
@@ -512,7 +526,10 @@ namespace OpenSim.Region.Physics.Meshing | |||
512 | // trim the vertex and triangle lists to free up memory | 526 | // trim the vertex and triangle lists to free up memory |
513 | mesh.TrimExcess(); | 527 | mesh.TrimExcess(); |
514 | } | 528 | } |
515 | m_uniqueMeshes.Add(key, mesh); | 529 | |
530 | if (!primShape.SculptEntry) | ||
531 | m_uniqueMeshes.Add(key, mesh); | ||
532 | |||
516 | return mesh; | 533 | return mesh; |
517 | } | 534 | } |
518 | } | 535 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ca67a64..b79c356 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -7080,7 +7080,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7080 | try | 7080 | try |
7081 | { | 7081 | { |
7082 | byte[] encData_byte = new byte[str.Length]; | 7082 | byte[] encData_byte = new byte[str.Length]; |
7083 | encData_byte = Encoding.UTF8.GetBytes(str); | 7083 | encData_byte = Util.UTF8.GetBytes(str); |
7084 | string encodedData = Convert.ToBase64String(encData_byte); | 7084 | string encodedData = Convert.ToBase64String(encData_byte); |
7085 | return encodedData; | 7085 | return encodedData; |
7086 | } | 7086 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 59525b6..4cb4b61 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -1491,7 +1491,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1491 | notecardData = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length " | 1491 | notecardData = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length " |
1492 | + textLength.ToString() + "\n" + notecardData + "}\n"; | 1492 | + textLength.ToString() + "\n" + notecardData + "}\n"; |
1493 | 1493 | ||
1494 | asset.Data = Encoding.UTF8.GetBytes(notecardData); | 1494 | asset.Data = Util.UTF8.GetBytes(notecardData); |
1495 | World.AssetService.Store(asset); | 1495 | World.AssetService.Store(asset); |
1496 | 1496 | ||
1497 | // Create Task Entry | 1497 | // Create Task Entry |