diff options
author | UbitUmarov | 2015-08-19 08:48:50 +0100 |
---|---|---|
committer | UbitUmarov | 2015-08-19 08:48:50 +0100 |
commit | 0b105da626ae8c2fb519a817b827f90534ed7d08 (patch) | |
tree | 509e6d091fb12f38fd09528335e51aeedbe59c08 /OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |
parent | Merge branch 'master' into ubitworkmaster (diff) | |
parent | varregion: update MapImageServiceModule to upload multiple map tiles for larg... (diff) | |
download | opensim-SC_OLD-0b105da626ae8c2fb519a817b827f90534ed7d08.zip opensim-SC_OLD-0b105da626ae8c2fb519a817b827f90534ed7d08.tar.gz opensim-SC_OLD-0b105da626ae8c2fb519a817b827f90534ed7d08.tar.bz2 opensim-SC_OLD-0b105da626ae8c2fb519a817b827f90534ed7d08.tar.xz |
Merge branch 'mbworkvar2' into ubitvar
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 273 |
1 files changed, 164 insertions, 109 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7b6889a..226f2a1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -312,6 +312,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
312 | private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; | 312 | private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; |
313 | 313 | ||
314 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 314 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
315 | private static string LogHeader = "[LLCLIENTVIEW]"; | ||
315 | protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients | 316 | protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients |
316 | 317 | ||
317 | /// <summary> | 318 | /// <summary> |
@@ -692,12 +693,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
692 | /// <returns>true if the handler was added. This is currently always the case.</returns> | 693 | /// <returns>true if the handler was added. This is currently always the case.</returns> |
693 | public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync) | 694 | public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync) |
694 | { | 695 | { |
696 | return AddLocalPacketHandler(packetType, handler, doAsync, false); | ||
697 | } | ||
698 | |||
699 | /// <summary> | ||
700 | /// Add a handler for the given packet type. | ||
701 | /// </summary> | ||
702 | /// <param name="packetType"></param> | ||
703 | /// <param name="handler"></param> | ||
704 | /// <param name="doAsync"> | ||
705 | /// If true, when the packet is received handle it on a different thread. Whether this is given direct to | ||
706 | /// a threadpool thread or placed in a queue depends on the inEngine parameter. | ||
707 | /// </param> | ||
708 | /// <param name="inEngine"> | ||
709 | /// If async is false then this parameter is ignored. | ||
710 | /// If async is true and inEngine is false, then the packet is sent directly to a | ||
711 | /// threadpool thread. | ||
712 | /// If async is true and inEngine is true, then the packet is sent to the IncomingPacketAsyncHandlingEngine. | ||
713 | /// This may result in slower handling but reduces the risk of overloading the simulator when there are many | ||
714 | /// simultaneous async requests. | ||
715 | /// </param> | ||
716 | /// <returns>true if the handler was added. This is currently always the case.</returns> | ||
717 | public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync, bool inEngine) | ||
718 | { | ||
695 | bool result = false; | 719 | bool result = false; |
696 | lock (m_packetHandlers) | 720 | lock (m_packetHandlers) |
697 | { | 721 | { |
698 | if (!m_packetHandlers.ContainsKey(packetType)) | 722 | if (!m_packetHandlers.ContainsKey(packetType)) |
699 | { | 723 | { |
700 | m_packetHandlers.Add(packetType, new PacketProcessor() { method = handler, Async = doAsync }); | 724 | m_packetHandlers.Add( |
725 | packetType, new PacketProcessor() { method = handler, Async = doAsync }); | ||
701 | result = true; | 726 | result = true; |
702 | } | 727 | } |
703 | } | 728 | } |
@@ -1176,11 +1201,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1176 | 1201 | ||
1177 | /// <summary> | 1202 | /// <summary> |
1178 | /// Send the region heightmap to the client | 1203 | /// Send the region heightmap to the client |
1204 | /// This method is only called when not doing intellegent terrain patch sending and | ||
1205 | /// is only called when the scene presence is initially created and sends all of the | ||
1206 | /// region's patches to the client. | ||
1179 | /// </summary> | 1207 | /// </summary> |
1180 | /// <param name="map">heightmap</param> | 1208 | /// <param name="map">heightmap</param> |
1181 | public virtual void SendLayerData(float[] map) | 1209 | public virtual void SendLayerData(float[] map) |
1182 | { | 1210 | { |
1183 | Util.FireAndForget(DoSendLayerData, map); | 1211 | Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData()); |
1184 | 1212 | ||
1185 | // Send it sync, and async. It's not that much data | 1213 | // Send it sync, and async. It's not that much data |
1186 | // and it improves user experience just so much! | 1214 | // and it improves user experience just so much! |
@@ -1193,15 +1221,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1193 | /// <param name="o"></param> | 1221 | /// <param name="o"></param> |
1194 | private void DoSendLayerData(object o) | 1222 | private void DoSendLayerData(object o) |
1195 | { | 1223 | { |
1196 | float[] map = LLHeightFieldMoronize((float[])o); | 1224 | TerrainData map = (TerrainData)o; |
1197 | 1225 | ||
1198 | try | 1226 | try |
1199 | { | 1227 | { |
1228 | // Send LayerData in typerwriter pattern | ||
1200 | for (int y = 0; y < 16; y++) | 1229 | for (int y = 0; y < 16; y++) |
1201 | { | 1230 | { |
1202 | for (int x = 0; x < 16; x+=4) | 1231 | for (int x = 0; x < 16; x++) |
1203 | { | 1232 | { |
1204 | SendLayerPacket(x, y, map); | 1233 | SendLayerData(x, y, map); |
1205 | } | 1234 | } |
1206 | } | 1235 | } |
1207 | } | 1236 | } |
@@ -1211,77 +1240,95 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1211 | } | 1240 | } |
1212 | } | 1241 | } |
1213 | 1242 | ||
1214 | /// <summary> | 1243 | // Legacy form of invocation that passes around a bare data array. |
1215 | /// Sends a set of four patches (x, x+1, ..., x+3) to the client | 1244 | // Just ignore what was passed and use the real terrain info that is part of the scene. |
1216 | /// </summary> | 1245 | // As a HORRIBLE kludge in an attempt to not change the definition of IClientAPI, |
1217 | /// <param name="map">heightmap</param> | 1246 | // there is a special form for specifying multiple terrain patches to send. |
1218 | /// <param name="px">X coordinate for patches 0..12</param> | 1247 | // The form is to pass 'px' as negative the number of patches to send and to |
1219 | /// <param name="py">Y coordinate for patches 0..15</param> | 1248 | // pass the float array as pairs of patch X and Y coordinates. So, passing 'px' |
1220 | private void SendLayerPacket(int x, int y, float[] map) | 1249 | // as -2 and map= [3, 5, 8, 4] would mean to send two terrain heightmap patches |
1250 | // and the patches to send are <3,5> and <8,4>. | ||
1251 | public void SendLayerData(int px, int py, float[] map) | ||
1221 | { | 1252 | { |
1222 | int[] patches = new int[4]; | 1253 | if (px >= 0) |
1223 | patches[0] = x + 0 + y * 16; | 1254 | { |
1224 | patches[1] = x + 1 + y * 16; | 1255 | SendLayerData(px, py, m_scene.Heightmap.GetTerrainData()); |
1225 | patches[2] = x + 2 + y * 16; | 1256 | } |
1226 | patches[3] = x + 3 + y * 16; | 1257 | else |
1258 | { | ||
1259 | int numPatches = -px; | ||
1260 | int[] xPatches = new int[numPatches]; | ||
1261 | int[] yPatches = new int[numPatches]; | ||
1262 | for (int pp = 0; pp < numPatches; pp++) | ||
1263 | { | ||
1264 | xPatches[pp] = (int)map[pp * 2]; | ||
1265 | yPatches[pp] = (int)map[pp * 2 + 1]; | ||
1266 | } | ||
1227 | 1267 | ||
1228 | float[] heightmap = (map.Length == 65536) ? | 1268 | // DebugSendingPatches("SendLayerData", xPatches, yPatches); |
1229 | map : | ||
1230 | LLHeightFieldMoronize(map); | ||
1231 | 1269 | ||
1232 | try | 1270 | SendLayerData(xPatches, yPatches, m_scene.Heightmap.GetTerrainData()); |
1233 | { | ||
1234 | Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); | ||
1235 | OutPacket(layerpack, ThrottleOutPacketType.Land); | ||
1236 | } | 1271 | } |
1237 | catch | 1272 | } |
1273 | |||
1274 | private void DebugSendingPatches(string pWho, int[] pX, int[] pY) | ||
1275 | { | ||
1276 | if (m_log.IsDebugEnabled) | ||
1238 | { | 1277 | { |
1239 | for (int px = x ; px < x + 4 ; px++) | 1278 | int numPatches = pX.Length; |
1240 | SendLayerData(px, y, map); | 1279 | string Xs = ""; |
1280 | string Ys = ""; | ||
1281 | for (int pp = 0; pp < numPatches; pp++) | ||
1282 | { | ||
1283 | Xs += String.Format("{0}", (int)pX[pp]) + ","; | ||
1284 | Ys += String.Format("{0}", (int)pY[pp]) + ","; | ||
1285 | } | ||
1286 | m_log.DebugFormat("{0} {1}: numPatches={2}, X={3}, Y={4}", LogHeader, pWho, numPatches, Xs, Ys); | ||
1241 | } | 1287 | } |
1242 | } | 1288 | } |
1243 | 1289 | ||
1244 | /// <summary> | 1290 | /// <summary> |
1245 | /// Sends a specified patch to a client | 1291 | /// Sends a terrain packet for the point specified. |
1292 | /// This is a legacy call that has refarbed the terrain into a flat map of floats. | ||
1293 | /// We just use the terrain from the region we know about. | ||
1246 | /// </summary> | 1294 | /// </summary> |
1247 | /// <param name="px">Patch coordinate (x) 0..15</param> | 1295 | /// <param name="px">Patch coordinate (x) 0..15</param> |
1248 | /// <param name="py">Patch coordinate (y) 0..15</param> | 1296 | /// <param name="py">Patch coordinate (y) 0..15</param> |
1249 | /// <param name="map">heightmap</param> | 1297 | /// <param name="map">heightmap</param> |
1250 | public void SendLayerData(int px, int py, float[] map) | 1298 | public void SendLayerData(int px, int py, TerrainData terrData) |
1299 | { | ||
1300 | int[] xPatches = new[] { px }; | ||
1301 | int[] yPatches = new[] { py }; | ||
1302 | SendLayerData(xPatches, yPatches, terrData); | ||
1303 | } | ||
1304 | |||
1305 | private void SendLayerData(int[] px, int[] py, TerrainData terrData) | ||
1251 | { | 1306 | { |
1252 | try | 1307 | try |
1253 | { | 1308 | { |
1254 | int[] patches = new int[] { py * 16 + px }; | 1309 | /* test code using the terrain compressor in libOpenMetaverse |
1255 | float[] heightmap = (map.Length == 65536) ? | 1310 | int[] patchInd = new int[1]; |
1256 | map : | 1311 | patchInd[0] = px + (py * Constants.TerrainPatchSize); |
1257 | LLHeightFieldMoronize(map); | 1312 | LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd); |
1258 | 1313 | */ | |
1259 | LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); | 1314 | // Many, many patches could have been passed to us. Since the patches will be compressed |
1260 | 1315 | // into variable sized blocks, we cannot pre-compute how many will fit into one | |
1261 | // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience. | 1316 | // packet. While some fancy packing algorithm is possible, 4 seems to always fit. |
1262 | // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain. | 1317 | int PatchesAssumedToFit = 4; |
1263 | // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area | 1318 | for (int pcnt = 0; pcnt < px.Length; pcnt += PatchesAssumedToFit) |
1264 | // invalidating previous packets for that area. | 1319 | { |
1265 | 1320 | int remaining = Math.Min(px.Length - pcnt, PatchesAssumedToFit); | |
1266 | // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a | 1321 | int[] xPatches = new int[remaining]; |
1267 | // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower. | 1322 | int[] yPatches = new int[remaining]; |
1268 | 1323 | for (int ii = 0; ii < remaining; ii++) | |
1269 | // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will | 1324 | { |
1270 | // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain | 1325 | xPatches[ii] = px[pcnt + ii]; |
1271 | // patches. | 1326 | yPatches[ii] = py[pcnt + ii]; |
1327 | } | ||
1328 | LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, xPatches, yPatches); | ||
1329 | // DebugSendingPatches("SendLayerDataInternal", xPatches, yPatches); | ||
1272 | 1330 | ||
1273 | // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss. | 1331 | SendTheLayerPacket(layerpack); |
1274 | if (m_justEditedTerrain) | ||
1275 | { | ||
1276 | layerpack.Header.Reliable = false; | ||
1277 | OutPacket(layerpack, | ||
1278 | ThrottleOutPacketType.Unknown ); | ||
1279 | } | ||
1280 | else | ||
1281 | { | ||
1282 | layerpack.Header.Reliable = true; | ||
1283 | OutPacket(layerpack, | ||
1284 | ThrottleOutPacketType.Task); | ||
1285 | } | 1332 | } |
1286 | } | 1333 | } |
1287 | catch (Exception e) | 1334 | catch (Exception e) |
@@ -1290,36 +1337,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1290 | } | 1337 | } |
1291 | } | 1338 | } |
1292 | 1339 | ||
1293 | /// <summary> | 1340 | // When a user edits the terrain, so much data is sent, the data queues up fast and presents a |
1294 | /// Munges heightfield into the LLUDP backed in restricted heightfield. | 1341 | // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we |
1295 | /// </summary> | 1342 | // start skipping the queues until they're done editing the terrain. We also make them |
1296 | /// <param name="map">float array in the base; Constants.RegionSize</param> | 1343 | // unreliable because it's extremely likely that multiple packets will be sent for a terrain patch |
1297 | /// <returns>float array in the base 256</returns> | 1344 | // area invalidating previous packets for that area. |
1298 | internal float[] LLHeightFieldMoronize(float[] map) | 1345 | |
1346 | // It's possible for an editing user to flood themselves with edited packets but the majority | ||
1347 | // of use cases are such that only a tiny percentage of users will be editing the terrain. | ||
1348 | // Other, non-editing users will see the edits much slower. | ||
1349 | |||
1350 | // One last note on this topic, by the time users are going to be editing the terrain, it's | ||
1351 | // extremely likely that the sim will have rezzed already and therefore this is not likely going | ||
1352 | // to cause any additional issues with lost packets, objects or terrain patches. | ||
1353 | |||
1354 | // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we | ||
1355 | // only have one cache miss. | ||
1356 | private void SendTheLayerPacket(LayerDataPacket layerpack) | ||
1299 | { | 1357 | { |
1300 | if (map.Length == 65536) | 1358 | if (m_justEditedTerrain) |
1301 | return map; | 1359 | { |
1360 | layerpack.Header.Reliable = false; | ||
1361 | OutPacket(layerpack, ThrottleOutPacketType.Unknown ); | ||
1362 | } | ||
1302 | else | 1363 | else |
1303 | { | 1364 | { |
1304 | float[] returnmap = new float[65536]; | 1365 | layerpack.Header.Reliable = true; |
1305 | 1366 | OutPacket(layerpack, ThrottleOutPacketType.Land); | |
1306 | if (map.Length < 65535) | ||
1307 | { | ||
1308 | // rebase the vector stride to 256 | ||
1309 | for (int i = 0; i < Constants.RegionSize; i++) | ||
1310 | Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, (int)Constants.RegionSize); | ||
1311 | } | ||
1312 | else | ||
1313 | { | ||
1314 | for (int i = 0; i < 256; i++) | ||
1315 | Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256); | ||
1316 | } | ||
1317 | |||
1318 | //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536); | ||
1319 | |||
1320 | return returnmap; | ||
1321 | } | 1367 | } |
1322 | |||
1323 | } | 1368 | } |
1324 | 1369 | ||
1325 | /// <summary> | 1370 | /// <summary> |
@@ -1348,21 +1393,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1348 | { | 1393 | { |
1349 | Vector2[] windSpeeds = (Vector2[])o; | 1394 | Vector2[] windSpeeds = (Vector2[])o; |
1350 | TerrainPatch[] patches = new TerrainPatch[2]; | 1395 | TerrainPatch[] patches = new TerrainPatch[2]; |
1351 | patches[0] = new TerrainPatch(); | 1396 | patches[0] = new TerrainPatch { Data = new float[16 * 16] }; |
1352 | patches[0].Data = new float[16 * 16]; | 1397 | patches[1] = new TerrainPatch { Data = new float[16 * 16] }; |
1353 | patches[1] = new TerrainPatch(); | ||
1354 | patches[1].Data = new float[16 * 16]; | ||
1355 | 1398 | ||
1356 | for (int y = 0; y < 16; y++) | 1399 | for (int x = 0; x < 16 * 16; x++) |
1357 | { | 1400 | { |
1358 | for (int x = 0; x < 16; x++) | 1401 | patches[0].Data[x] = windSpeeds[x].X; |
1359 | { | 1402 | patches[1].Data[x] = windSpeeds[x].Y; |
1360 | patches[0].Data[y * 16 + x] = windSpeeds[y * 16 + x].X; | ||
1361 | patches[1].Data[y * 16 + x] = windSpeeds[y * 16 + x].Y; | ||
1362 | } | ||
1363 | } | 1403 | } |
1364 | 1404 | ||
1365 | LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Wind); | 1405 | byte layerType = (byte)TerrainPatch.LayerType.Wind; |
1406 | if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize) | ||
1407 | layerType = (byte)TerrainPatch.LayerType.WindExtended; | ||
1408 | |||
1409 | // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType); | ||
1410 | LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType, | ||
1411 | (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY); | ||
1366 | layerpack.Header.Zerocoded = true; | 1412 | layerpack.Header.Zerocoded = true; |
1367 | OutPacket(layerpack, ThrottleOutPacketType.Wind); | 1413 | OutPacket(layerpack, ThrottleOutPacketType.Wind); |
1368 | } | 1414 | } |
@@ -1386,7 +1432,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1386 | } | 1432 | } |
1387 | } | 1433 | } |
1388 | 1434 | ||
1389 | LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, TerrainPatch.LayerType.Cloud); | 1435 | byte layerType = (byte)TerrainPatch.LayerType.Cloud; |
1436 | if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize) | ||
1437 | layerType = (byte)TerrainPatch.LayerType.CloudExtended; | ||
1438 | |||
1439 | // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType); | ||
1440 | LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType, | ||
1441 | (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY); | ||
1390 | layerpack.Header.Zerocoded = true; | 1442 | layerpack.Header.Zerocoded = true; |
1391 | OutPacket(layerpack, ThrottleOutPacketType.Cloud); | 1443 | OutPacket(layerpack, ThrottleOutPacketType.Cloud); |
1392 | } | 1444 | } |
@@ -1491,10 +1543,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1491 | mapReply.Data[i].Access = mapBlocks2[i].Access; | 1543 | mapReply.Data[i].Access = mapBlocks2[i].Access; |
1492 | mapReply.Data[i].Agents = mapBlocks2[i].Agents; | 1544 | mapReply.Data[i].Agents = mapBlocks2[i].Agents; |
1493 | 1545 | ||
1494 | // TODO: hookup varregion sim size here | ||
1495 | mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock(); | 1546 | mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock(); |
1496 | mapReply.Size[i].SizeX = 256; | 1547 | mapReply.Size[i].SizeX = mapBlocks2[i].SizeX; |
1497 | mapReply.Size[i].SizeY = 256; | 1548 | mapReply.Size[i].SizeY = mapBlocks2[i].SizeY; |
1498 | } | 1549 | } |
1499 | OutPacket(mapReply, ThrottleOutPacketType.Land); | 1550 | OutPacket(mapReply, ThrottleOutPacketType.Land); |
1500 | } | 1551 | } |
@@ -1659,15 +1710,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1659 | 1710 | ||
1660 | public void SendKillObject(List<uint> localIDs) | 1711 | public void SendKillObject(List<uint> localIDs) |
1661 | { | 1712 | { |
1662 | // foreach (uint id in localIDs) | ||
1663 | // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); | ||
1664 | |||
1665 | // remove pending entities | ||
1666 | lock (m_entityProps.SyncRoot) | ||
1667 | m_entityProps.Remove(localIDs); | ||
1668 | lock (m_entityUpdates.SyncRoot) | ||
1669 | m_entityUpdates.Remove(localIDs); | ||
1670 | |||
1671 | KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); | 1713 | KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); |
1672 | // TODO: don't create new blocks if recycling an old packet | 1714 | // TODO: don't create new blocks if recycling an old packet |
1673 | kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count]; | 1715 | kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count]; |
@@ -9093,6 +9135,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9093 | TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest; | 9135 | TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest; |
9094 | if (handlerTeleportLocationRequest != null) | 9136 | if (handlerTeleportLocationRequest != null) |
9095 | { | 9137 | { |
9138 | // Adjust teleport location to base of a larger region if requested to teleport to a sub-region | ||
9139 | uint locX, locY; | ||
9140 | Util.RegionHandleToWorldLoc(tpLocReq.Info.RegionHandle, out locX, out locY); | ||
9141 | if ((locX >= m_scene.RegionInfo.WorldLocX) | ||
9142 | && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX)) | ||
9143 | && (locY >= m_scene.RegionInfo.WorldLocY) | ||
9144 | && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) ) | ||
9145 | { | ||
9146 | tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle; | ||
9147 | tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX; | ||
9148 | tpLocReq.Info.Position.Y += locY - m_scene.RegionInfo.WorldLocY; | ||
9149 | } | ||
9150 | |||
9096 | handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, | 9151 | handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, |
9097 | tpLocReq.Info.LookAt, 16); | 9152 | tpLocReq.Info.LookAt, 16); |
9098 | } | 9153 | } |