diff options
author | Melanie | 2019-07-27 12:10:28 +0100 |
---|---|---|
committer | Melanie | 2019-07-27 12:10:28 +0100 |
commit | d6723dab37d86af22c712e2705af34fd2c82b174 (patch) | |
tree | 041be46cdcc778660fe3083794dabd2a2805283f /OpenSim/Region | |
parent | When using FSAssets, the HGAssetService would still use AssetService. (diff) | |
parent | mantis 8563: do not modify collection inside a loop on it a foreach on it (diff) | |
download | opensim-SC-d6723dab37d86af22c712e2705af34fd2c82b174.zip opensim-SC-d6723dab37d86af22c712e2705af34fd2c82b174.tar.gz opensim-SC-d6723dab37d86af22c712e2705af34fd2c82b174.tar.bz2 opensim-SC-d6723dab37d86af22c712e2705af34fd2c82b174.tar.xz |
Merge branch 'master' of brain.opensimulator.org:/var/git/opensim
Diffstat (limited to 'OpenSim/Region')
57 files changed, 4493 insertions, 2458 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/AgentPreferencesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/AgentPreferencesModule.cs index 8f65a69..b0ba5a3 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/AgentPreferencesModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/AgentPreferencesModule.cs | |||
@@ -77,6 +77,9 @@ namespace OpenSim.Region.ClientStack.LindenCaps | |||
77 | { | 77 | { |
78 | RegisterCaps(agentID, caps); | 78 | RegisterCaps(agentID, caps); |
79 | }; | 79 | }; |
80 | ISimulatorFeaturesModule simFeatures = scene.RequestModuleInterface<ISimulatorFeaturesModule>(); | ||
81 | if(simFeatures != null) | ||
82 | simFeatures.AddFeature("AvatarHoverHeightEnabled",OSD.FromBoolean(true)); | ||
80 | } | 83 | } |
81 | 84 | ||
82 | public void PostInitialise() {} | 85 | public void PostInitialise() {} |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 92f5a2c..ea68581 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | |||
@@ -61,7 +61,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
61 | string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, | 61 | string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, |
62 | byte[] data, string inventoryType, string assetType, | 62 | byte[] data, string inventoryType, string assetType, |
63 | int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, | 63 | int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, |
64 | bool IsAtestUpload, ref string error, ref int nextOwnerMask, ref int groupMask, ref int everyoneMask); | 64 | bool IsAtestUpload, ref string error, ref int nextOwnerMask, ref int groupMask, ref int everyoneMask, int[] meshesSides); |
65 | 65 | ||
66 | public delegate UUID UpdateItem(UUID itemID, byte[] data); | 66 | public delegate UUID UpdateItem(UUID itemID, byte[] data); |
67 | 67 | ||
@@ -505,7 +505,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
505 | case FileAgentInventoryState.processRequest: | 505 | case FileAgentInventoryState.processRequest: |
506 | case FileAgentInventoryState.processUpload: | 506 | case FileAgentInventoryState.processUpload: |
507 | LLSDAssetUploadError resperror = new LLSDAssetUploadError(); | 507 | LLSDAssetUploadError resperror = new LLSDAssetUploadError(); |
508 | resperror.message = "Uploader busy processing previus request"; | 508 | resperror.message = "Uploader busy processing previous request"; |
509 | resperror.identifier = UUID.Zero; | 509 | resperror.identifier = UUID.Zero; |
510 | 510 | ||
511 | LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); | 511 | LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); |
@@ -529,6 +529,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
529 | int nreqmeshs= 0; | 529 | int nreqmeshs= 0; |
530 | int nreqinstances = 0; | 530 | int nreqinstances = 0; |
531 | bool IsAtestUpload = false; | 531 | bool IsAtestUpload = false; |
532 | int[] meshesSides = null; | ||
532 | 533 | ||
533 | string assetName = llsdRequest.name; | 534 | string assetName = llsdRequest.name; |
534 | 535 | ||
@@ -578,9 +579,8 @@ namespace OpenSim.Region.ClientStack.Linden | |||
578 | string error; | 579 | string error; |
579 | int modelcost; | 580 | int modelcost; |
580 | 581 | ||
581 | |||
582 | if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost, | 582 | if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost, |
583 | meshcostdata, out error, ref warning)) | 583 | meshcostdata, out error, ref warning, out meshesSides)) |
584 | { | 584 | { |
585 | LLSDAssetUploadError resperror = new LLSDAssetUploadError(); | 585 | LLSDAssetUploadError resperror = new LLSDAssetUploadError(); |
586 | resperror.message = error; | 586 | resperror.message = error; |
@@ -668,7 +668,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
668 | new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, | 668 | new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, |
669 | llsdRequest.asset_type, uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost, | 669 | llsdRequest.asset_type, uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost, |
670 | texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload, | 670 | texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload, |
671 | llsdRequest.next_owner_mask, llsdRequest.group_mask, llsdRequest.everyone_mask); | 671 | llsdRequest.next_owner_mask, llsdRequest.group_mask, llsdRequest.everyone_mask, meshesSides); |
672 | 672 | ||
673 | m_HostCapsObj.HttpListener.AddStreamHandler( | 673 | m_HostCapsObj.HttpListener.AddStreamHandler( |
674 | new BinaryStreamHandler( | 674 | new BinaryStreamHandler( |
@@ -713,7 +713,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
713 | string assetType, int cost, | 713 | string assetType, int cost, |
714 | UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, | 714 | UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, |
715 | bool IsAtestUpload, ref string error, | 715 | bool IsAtestUpload, ref string error, |
716 | ref int nextOwnerMask, ref int groupMask, ref int everyoneMask) | 716 | ref int nextOwnerMask, ref int groupMask, ref int everyoneMask, int[] meshesSides) |
717 | { | 717 | { |
718 | lock (m_ModelCost) | 718 | lock (m_ModelCost) |
719 | m_FileAgentInventoryState = FileAgentInventoryState.processUpload; | 719 | m_FileAgentInventoryState = FileAgentInventoryState.processUpload; |
@@ -967,7 +967,12 @@ namespace OpenSim.Region.ClientStack.Linden | |||
967 | { | 967 | { |
968 | int meshindx = inner_instance_list["mesh"].AsInteger(); | 968 | int meshindx = inner_instance_list["mesh"].AsInteger(); |
969 | if (meshAssets.Count > meshindx) | 969 | if (meshAssets.Count > meshindx) |
970 | pbs = PrimitiveBaseShape.CreateMesh(face_list.Count, meshAssets[meshindx]); | 970 | { |
971 | if(meshesSides != null && meshesSides.Length > meshindx) | ||
972 | pbs = PrimitiveBaseShape.CreateMesh(meshesSides[i], meshAssets[meshindx]); | ||
973 | else | ||
974 | pbs = PrimitiveBaseShape.CreateMesh(face_list.Count, meshAssets[meshindx]); | ||
975 | } | ||
971 | } | 976 | } |
972 | if(pbs == null) // fallback | 977 | if(pbs == null) // fallback |
973 | pbs = PrimitiveBaseShape.CreateBox(); | 978 | pbs = PrimitiveBaseShape.CreateBox(); |
@@ -1012,17 +1017,25 @@ namespace OpenSim.Region.ClientStack.Linden | |||
1012 | 1017 | ||
1013 | textureEntry.FaceTextures[face] = f; | 1018 | textureEntry.FaceTextures[face] = f; |
1014 | } | 1019 | } |
1015 | pbs.TextureEntry = textureEntry.GetBytes(); | 1020 | |
1021 | if(face_list.Count > 0) | ||
1022 | { | ||
1023 | int last = face_list.Count - 1; | ||
1024 | // we do need a better te compacting code | ||
1025 | textureEntry.DefaultTexture = textureEntry.FaceTextures[last]; | ||
1026 | textureEntry.FaceTextures[last] = null; | ||
1027 | pbs.TextureEntry = textureEntry.GetBytes(last); | ||
1028 | } | ||
1016 | 1029 | ||
1017 | Vector3 position = inner_instance_list["position"].AsVector3(); | 1030 | Vector3 position = inner_instance_list["position"].AsVector3(); |
1018 | Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); | 1031 | Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); |
1019 | 1032 | ||
1020 | // for now viwers do send fixed defaults | ||
1021 | // but this may change | ||
1022 | // int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger(); | ||
1023 | byte physicsShapeType = (byte)PhysShapeType.convex; // default is simple convex | 1033 | byte physicsShapeType = (byte)PhysShapeType.convex; // default is simple convex |
1024 | // int material = inner_instance_list["material"].AsInteger(); | 1034 | if (inner_instance_list.ContainsKey("physics_shape_type")) |
1035 | physicsShapeType = (byte)inner_instance_list["physics_shape_type"].AsInteger(); | ||
1025 | byte material = (byte)Material.Wood; | 1036 | byte material = (byte)Material.Wood; |
1037 | if (inner_instance_list.ContainsKey("material")) | ||
1038 | material = (byte)inner_instance_list["material"].AsInteger(); | ||
1026 | 1039 | ||
1027 | SceneObjectPart prim | 1040 | SceneObjectPart prim |
1028 | = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); | 1041 | = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); |
@@ -2006,13 +2019,13 @@ namespace OpenSim.Region.ClientStack.Linden | |||
2006 | private int m_nextOwnerMask; | 2019 | private int m_nextOwnerMask; |
2007 | private int m_groupMask; | 2020 | private int m_groupMask; |
2008 | private int m_everyoneMask; | 2021 | private int m_everyoneMask; |
2009 | 2022 | private int[] m_meshesSides; | |
2010 | 2023 | ||
2011 | public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, | 2024 | public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, |
2012 | UUID parentFolderID, string invType, string assetType, string path, | 2025 | UUID parentFolderID, string invType, string assetType, string path, |
2013 | IHttpServer httpServer, bool dumpAssetsToFile, | 2026 | IHttpServer httpServer, bool dumpAssetsToFile, |
2014 | int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, | 2027 | int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, |
2015 | bool IsAtestUpload, int nextOwnerMask, int groupMask, int everyoneMask) | 2028 | bool IsAtestUpload, int nextOwnerMask, int groupMask, int everyoneMask, int[] meshesSides) |
2016 | { | 2029 | { |
2017 | m_assetName = assetName; | 2030 | m_assetName = assetName; |
2018 | m_assetDes = description; | 2031 | m_assetDes = description; |
@@ -2040,6 +2053,8 @@ namespace OpenSim.Region.ClientStack.Linden | |||
2040 | m_nextOwnerMask = nextOwnerMask; | 2053 | m_nextOwnerMask = nextOwnerMask; |
2041 | m_groupMask = groupMask; | 2054 | m_groupMask = groupMask; |
2042 | m_everyoneMask = everyoneMask; | 2055 | m_everyoneMask = everyoneMask; |
2056 | |||
2057 | m_meshesSides = meshesSides; | ||
2043 | } | 2058 | } |
2044 | 2059 | ||
2045 | /// <summary> | 2060 | /// <summary> |
@@ -2080,7 +2095,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
2080 | { | 2095 | { |
2081 | handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType, | 2096 | handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType, |
2082 | m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, | 2097 | m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, |
2083 | ref m_error, ref m_nextOwnerMask, ref m_groupMask, ref m_everyoneMask); | 2098 | ref m_error, ref m_nextOwnerMask, ref m_groupMask, ref m_everyoneMask, m_meshesSides); |
2084 | } | 2099 | } |
2085 | 2100 | ||
2086 | uploadComplete.new_next_owner_mask = m_nextOwnerMask; | 2101 | uploadComplete.new_next_owner_mask = m_nextOwnerMask; |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs index eb1ab45..9b8f11a 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs | |||
@@ -40,7 +40,7 @@ using OpenSim.Region.Framework; | |||
40 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
41 | using OpenSim.Framework.Capabilities; | 41 | using OpenSim.Framework.Capabilities; |
42 | 42 | ||
43 | using ComponentAce.Compression.Libs.zlib; | 43 | using System.IO.Compression; |
44 | 44 | ||
45 | using OSDArray = OpenMetaverse.StructuredData.OSDArray; | 45 | using OSDArray = OpenMetaverse.StructuredData.OSDArray; |
46 | using OSDMap = OpenMetaverse.StructuredData.OSDMap; | 46 | using OSDMap = OpenMetaverse.StructuredData.OSDMap; |
@@ -129,6 +129,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
129 | public int medLODSize; | 129 | public int medLODSize; |
130 | public int lowLODSize; | 130 | public int lowLODSize; |
131 | public int lowestLODSize; | 131 | public int lowestLODSize; |
132 | public int highLODsides; | ||
132 | // normalized fee based on compressed data sizes | 133 | // normalized fee based on compressed data sizes |
133 | public float costFee; | 134 | public float costFee; |
134 | // physics cost | 135 | // physics cost |
@@ -144,11 +145,11 @@ namespace OpenSim.Region.ClientStack.Linden | |||
144 | // avatarSkeleton if mesh includes a avatar skeleton | 145 | // avatarSkeleton if mesh includes a avatar skeleton |
145 | // useAvatarCollider if we should use physics mesh for avatar | 146 | // useAvatarCollider if we should use physics mesh for avatar |
146 | public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, | 147 | public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost, |
147 | LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning) | 148 | LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning, out int[] meshesSides) |
148 | { | 149 | { |
149 | totalcost = 0; | 150 | totalcost = 0; |
150 | error = string.Empty; | 151 | error = string.Empty; |
151 | 152 | meshesSides = null; | |
152 | bool avatarSkeleton = false; | 153 | bool avatarSkeleton = false; |
153 | 154 | ||
154 | if (resources == null || | 155 | if (resources == null || |
@@ -203,13 +204,14 @@ namespace OpenSim.Region.ClientStack.Linden | |||
203 | if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0) | 204 | if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0) |
204 | { | 205 | { |
205 | numberMeshs = resources.mesh_list.Array.Count; | 206 | numberMeshs = resources.mesh_list.Array.Count; |
207 | meshesSides = new int[numberMeshs]; | ||
206 | 208 | ||
207 | for (int i = 0; i < numberMeshs; i++) | 209 | for (int i = 0; i < numberMeshs; i++) |
208 | { | 210 | { |
209 | ameshCostParam curCost = new ameshCostParam(); | 211 | ameshCostParam curCost = new ameshCostParam(); |
210 | byte[] data = (byte[])resources.mesh_list.Array[i]; | 212 | byte[] data = (byte[])resources.mesh_list.Array[i]; |
211 | 213 | ||
212 | if (!MeshCost(data, curCost,out curskeleton, out curAvatarPhys, out error)) | 214 | if (!MeshCost(data, curCost, out curskeleton, out curAvatarPhys, out error)) |
213 | { | 215 | { |
214 | return false; | 216 | return false; |
215 | } | 217 | } |
@@ -225,6 +227,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
225 | } | 227 | } |
226 | meshsCosts.Add(curCost); | 228 | meshsCosts.Add(curCost); |
227 | meshsfee += curCost.costFee; | 229 | meshsfee += curCost.costFee; |
230 | meshesSides[i] = curCost.highLODsides; | ||
228 | } | 231 | } |
229 | haveMeshs = true; | 232 | haveMeshs = true; |
230 | } | 233 | } |
@@ -275,6 +278,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
275 | float sqdiam = scale.LengthSquared(); | 278 | float sqdiam = scale.LengthSquared(); |
276 | 279 | ||
277 | ameshCostParam curCost = meshsCosts[mesh]; | 280 | ameshCostParam curCost = meshsCosts[mesh]; |
281 | |||
278 | float mesh_streaming = streamingCost(curCost, sqdiam); | 282 | float mesh_streaming = streamingCost(curCost, sqdiam); |
279 | 283 | ||
280 | meshcostdata.model_streaming_cost += mesh_streaming; | 284 | meshcostdata.model_streaming_cost += mesh_streaming; |
@@ -339,6 +343,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
339 | private bool MeshCost(byte[] data, ameshCostParam cost,out bool skeleton, out bool avatarPhys, out string error) | 343 | private bool MeshCost(byte[] data, ameshCostParam cost,out bool skeleton, out bool avatarPhys, out string error) |
340 | { | 344 | { |
341 | cost.highLODSize = 0; | 345 | cost.highLODSize = 0; |
346 | cost.highLODsides = 0; | ||
342 | cost.medLODSize = 0; | 347 | cost.medLODSize = 0; |
343 | cost.lowLODSize = 0; | 348 | cost.lowLODSize = 0; |
344 | cost.lowestLODSize = 0; | 349 | cost.lowestLODSize = 0; |
@@ -430,7 +435,8 @@ namespace OpenSim.Region.ClientStack.Linden | |||
430 | 435 | ||
431 | submesh_offset = -1; | 436 | submesh_offset = -1; |
432 | 437 | ||
433 | // only look for LOD meshs sizes | 438 | int nsides = 0; |
439 | int lod_ntriangles = 0; | ||
434 | 440 | ||
435 | if (map.ContainsKey("high_lod")) | 441 | if (map.ContainsKey("high_lod")) |
436 | { | 442 | { |
@@ -440,6 +446,15 @@ namespace OpenSim.Region.ClientStack.Linden | |||
440 | submesh_offset = tmpmap["offset"].AsInteger() + start; | 446 | submesh_offset = tmpmap["offset"].AsInteger() + start; |
441 | if (tmpmap.ContainsKey("size")) | 447 | if (tmpmap.ContainsKey("size")) |
442 | highlod_size = tmpmap["size"].AsInteger(); | 448 | highlod_size = tmpmap["size"].AsInteger(); |
449 | |||
450 | if (submesh_offset >= 0 && highlod_size > 0) | ||
451 | { | ||
452 | if (!submesh(data, submesh_offset, highlod_size, out lod_ntriangles, out nsides)) | ||
453 | { | ||
454 | error = "Model data parsing error"; | ||
455 | return false; | ||
456 | } | ||
457 | } | ||
443 | } | 458 | } |
444 | 459 | ||
445 | if (submesh_offset < 0 || highlod_size <= 0) | 460 | if (submesh_offset < 0 || highlod_size <= 0) |
@@ -483,6 +498,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
483 | } | 498 | } |
484 | 499 | ||
485 | cost.highLODSize = highlod_size; | 500 | cost.highLODSize = highlod_size; |
501 | cost.highLODsides = nsides; | ||
486 | cost.medLODSize = medlod_size; | 502 | cost.medLODSize = medlod_size; |
487 | cost.lowLODSize = lowlod_size; | 503 | cost.lowLODSize = lowlod_size; |
488 | cost.lowestLODSize = lowestlod_size; | 504 | cost.lowestLODSize = lowestlod_size; |
@@ -495,6 +511,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
495 | else if (map.ContainsKey("physics_shape")) // old naming | 511 | else if (map.ContainsKey("physics_shape")) // old naming |
496 | tmpmap = (OSDMap)map["physics_shape"]; | 512 | tmpmap = (OSDMap)map["physics_shape"]; |
497 | 513 | ||
514 | int phys_nsides = 0; | ||
498 | if(tmpmap != null) | 515 | if(tmpmap != null) |
499 | { | 516 | { |
500 | if (tmpmap.ContainsKey("offset")) | 517 | if (tmpmap.ContainsKey("offset")) |
@@ -502,10 +519,9 @@ namespace OpenSim.Region.ClientStack.Linden | |||
502 | if (tmpmap.ContainsKey("size")) | 519 | if (tmpmap.ContainsKey("size")) |
503 | physmesh_size = tmpmap["size"].AsInteger(); | 520 | physmesh_size = tmpmap["size"].AsInteger(); |
504 | 521 | ||
505 | if (submesh_offset >= 0 || physmesh_size > 0) | 522 | if (submesh_offset >= 0 && physmesh_size > 0) |
506 | { | 523 | { |
507 | 524 | if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles, out phys_nsides)) | |
508 | if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles)) | ||
509 | { | 525 | { |
510 | error = "Model data parsing error"; | 526 | error = "Model data parsing error"; |
511 | return false; | 527 | return false; |
@@ -541,34 +557,30 @@ namespace OpenSim.Region.ClientStack.Linden | |||
541 | } | 557 | } |
542 | 558 | ||
543 | // parses a LOD or physics mesh component | 559 | // parses a LOD or physics mesh component |
544 | private bool submesh(byte[] data, int offset, int size, out int ntriangles) | 560 | private bool submesh(byte[] data, int offset, int size, out int ntriangles, out int nsides) |
545 | { | 561 | { |
546 | ntriangles = 0; | 562 | ntriangles = 0; |
563 | nsides = 0; | ||
547 | 564 | ||
548 | OSD decodedMeshOsd = new OSD(); | 565 | OSD decodedMeshOsd = new OSD(); |
549 | byte[] meshBytes = new byte[size]; | ||
550 | System.Buffer.BlockCopy(data, offset, meshBytes, 0, size); | ||
551 | try | 566 | try |
552 | { | 567 | { |
553 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | 568 | using (MemoryStream outMs = new MemoryStream()) |
554 | { | 569 | { |
555 | using (MemoryStream outMs = new MemoryStream()) | 570 | using (MemoryStream inMs = new MemoryStream(data, offset, size)) |
556 | { | 571 | { |
557 | using (ZOutputStream zOut = new ZOutputStream(outMs)) | 572 | using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress)) |
558 | { | 573 | { |
559 | byte[] readBuffer = new byte[4096]; | 574 | byte[] readBuffer = new byte[2048]; |
575 | inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header | ||
560 | int readLen = 0; | 576 | int readLen = 0; |
561 | while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) | 577 | |
562 | { | 578 | while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0) |
563 | zOut.Write(readBuffer, 0, readLen); | 579 | outMs.Write(readBuffer, 0, readLen); |
564 | } | ||
565 | zOut.Flush(); | ||
566 | outMs.Seek(0, SeekOrigin.Begin); | ||
567 | |||
568 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
569 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
570 | } | 580 | } |
571 | } | 581 | } |
582 | outMs.Seek(0, SeekOrigin.Begin); | ||
583 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(outMs); | ||
572 | } | 584 | } |
573 | } | 585 | } |
574 | catch | 586 | catch |
@@ -599,6 +611,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
599 | } | 611 | } |
600 | else | 612 | else |
601 | return false; | 613 | return false; |
614 | nsides++; | ||
602 | } | 615 | } |
603 | } | 616 | } |
604 | 617 | ||
@@ -612,29 +625,24 @@ namespace OpenSim.Region.ClientStack.Linden | |||
612 | nhulls = 1; | 625 | nhulls = 1; |
613 | 626 | ||
614 | OSD decodedMeshOsd = new OSD(); | 627 | OSD decodedMeshOsd = new OSD(); |
615 | byte[] meshBytes = new byte[size]; | ||
616 | System.Buffer.BlockCopy(data, offset, meshBytes, 0, size); | ||
617 | try | 628 | try |
618 | { | 629 | { |
619 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | 630 | using (MemoryStream outMs = new MemoryStream(4 * size)) |
620 | { | 631 | { |
621 | using (MemoryStream outMs = new MemoryStream()) | 632 | using (MemoryStream inMs = new MemoryStream(data, offset, size)) |
622 | { | 633 | { |
623 | using (ZOutputStream zOut = new ZOutputStream(outMs)) | 634 | using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress)) |
624 | { | 635 | { |
625 | byte[] readBuffer = new byte[4096]; | 636 | byte[] readBuffer = new byte[8192]; |
637 | inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header | ||
626 | int readLen = 0; | 638 | int readLen = 0; |
627 | while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) | 639 | |
628 | { | 640 | while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0) |
629 | zOut.Write(readBuffer, 0, readLen); | 641 | outMs.Write(readBuffer, 0, readLen); |
630 | } | ||
631 | zOut.Flush(); | ||
632 | outMs.Seek(0, SeekOrigin.Begin); | ||
633 | |||
634 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
635 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
636 | } | 642 | } |
637 | } | 643 | } |
644 | outMs.Seek(0, SeekOrigin.Begin); | ||
645 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(outMs); | ||
638 | } | 646 | } |
639 | } | 647 | } |
640 | catch | 648 | catch |
@@ -716,7 +724,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
716 | int m = curCost.medLODSize - 384; | 724 | int m = curCost.medLODSize - 384; |
717 | int h = curCost.highLODSize - 384; | 725 | int h = curCost.highLODSize - 384; |
718 | 726 | ||
719 | // use previus higher LOD size on missing ones | 727 | // use previous higher LOD size on missing ones |
720 | if (m <= 0) | 728 | if (m <= 0) |
721 | m = h; | 729 | m = h; |
722 | if (l <= 0) | 730 | if (l <= 0) |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index f56b212..4e451b5 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | |||
@@ -233,7 +233,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
233 | else | 233 | else |
234 | { | 234 | { |
235 | m_log.WarnFormat( | 235 | m_log.WarnFormat( |
236 | "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} in region {2}", | 236 | "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} in region {1}", |
237 | avatarID, m_scene.Name); | 237 | avatarID, m_scene.Name); |
238 | } | 238 | } |
239 | } | 239 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ac041f5..aeb728e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -332,7 +332,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
332 | private readonly UUID m_secureSessionId; | 332 | private readonly UUID m_secureSessionId; |
333 | protected readonly UUID m_agentId; | 333 | protected readonly UUID m_agentId; |
334 | private readonly uint m_circuitCode; | 334 | private readonly uint m_circuitCode; |
335 | private readonly byte[] m_channelVersion = Utils.EmptyBytes; | 335 | private readonly byte[] m_regionChannelVersion = Utils.EmptyBytes; |
336 | private readonly IGroupsModule m_GroupsModule; | 336 | private readonly IGroupsModule m_GroupsModule; |
337 | 337 | ||
338 | // private int m_cachedTextureSerial; | 338 | // private int m_cachedTextureSerial; |
@@ -392,6 +392,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
392 | 392 | ||
393 | protected IAssetService m_assetService; | 393 | protected IAssetService m_assetService; |
394 | 394 | ||
395 | protected bool m_supportViewerCache = false; | ||
395 | #endregion Class Members | 396 | #endregion Class Members |
396 | 397 | ||
397 | #region Properties | 398 | #region Properties |
@@ -407,6 +408,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
407 | get { return m_startpos; } | 408 | get { return m_startpos; } |
408 | set { m_startpos = value; } | 409 | set { m_startpos = value; } |
409 | } | 410 | } |
411 | public float StartFar { get; set; } | ||
412 | |||
410 | public bool DeliverPackets | 413 | public bool DeliverPackets |
411 | { | 414 | { |
412 | get { return m_deliverPackets; } | 415 | get { return m_deliverPackets; } |
@@ -531,7 +534,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
531 | m_assetService = m_scene.RequestModuleInterface<IAssetService>(); | 534 | m_assetService = m_scene.RequestModuleInterface<IAssetService>(); |
532 | m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); | 535 | m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); |
533 | ImageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>()); | 536 | ImageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>()); |
534 | m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion()); | 537 | m_regionChannelVersion = Util.StringToBytes1024(scene.GetSimulatorVersion()); |
535 | m_agentId = agentId; | 538 | m_agentId = agentId; |
536 | m_sessionId = sessionId; | 539 | m_sessionId = sessionId; |
537 | m_secureSessionId = sessionInfo.LoginInfo.SecureSession; | 540 | m_secureSessionId = sessionInfo.LoginInfo.SecureSession; |
@@ -539,6 +542,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
539 | m_firstName = sessionInfo.LoginInfo.First; | 542 | m_firstName = sessionInfo.LoginInfo.First; |
540 | m_lastName = sessionInfo.LoginInfo.Last; | 543 | m_lastName = sessionInfo.LoginInfo.Last; |
541 | m_startpos = sessionInfo.LoginInfo.StartPos; | 544 | m_startpos = sessionInfo.LoginInfo.StartPos; |
545 | StartFar = sessionInfo.LoginInfo.StartFar; | ||
542 | 546 | ||
543 | m_udpServer = udpServer; | 547 | m_udpServer = udpServer; |
544 | m_udpClient = udpClient; | 548 | m_udpClient = udpClient; |
@@ -552,6 +556,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
552 | string name = string.Format("AsyncInUDP-{0}",m_agentId.ToString()); | 556 | string name = string.Format("AsyncInUDP-{0}",m_agentId.ToString()); |
553 | m_asyncPacketProcess = new JobEngine(name, name, 10000); | 557 | m_asyncPacketProcess = new JobEngine(name, name, 10000); |
554 | IsActive = true; | 558 | IsActive = true; |
559 | |||
560 | m_supportViewerCache = m_udpServer.SupportViewerObjectsCache; | ||
555 | } | 561 | } |
556 | 562 | ||
557 | #region Client Methods | 563 | #region Client Methods |
@@ -817,171 +823,535 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
817 | 823 | ||
818 | #region Scene/Avatar to Client | 824 | #region Scene/Avatar to Client |
819 | 825 | ||
820 | public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) | 826 | // temporary here ( from estatemanagermodule) |
821 | { | 827 | private uint GetRegionFlags() |
822 | RegionHandshakePacket handshake = (RegionHandshakePacket)PacketPool.Instance.GetPacket(PacketType.RegionHandshake); | 828 | { |
823 | handshake.RegionInfo = new RegionHandshakePacket.RegionInfoBlock(); | 829 | RegionFlags flags = RegionFlags.None; |
824 | handshake.RegionInfo.BillableFactor = args.billableFactor; | 830 | |
825 | handshake.RegionInfo.IsEstateManager = args.isEstateManager; | 831 | if (Scene.RegionInfo.RegionSettings.AllowDamage) |
826 | handshake.RegionInfo.TerrainHeightRange00 = args.terrainHeightRange0; | 832 | flags |= RegionFlags.AllowDamage; |
827 | handshake.RegionInfo.TerrainHeightRange01 = args.terrainHeightRange1; | 833 | if (Scene.RegionInfo.EstateSettings.AllowLandmark) |
828 | handshake.RegionInfo.TerrainHeightRange10 = args.terrainHeightRange2; | 834 | flags |= RegionFlags.AllowLandmark; |
829 | handshake.RegionInfo.TerrainHeightRange11 = args.terrainHeightRange3; | 835 | if (Scene.RegionInfo.EstateSettings.AllowSetHome) |
830 | handshake.RegionInfo.TerrainStartHeight00 = args.terrainStartHeight0; | 836 | flags |= RegionFlags.AllowSetHome; |
831 | handshake.RegionInfo.TerrainStartHeight01 = args.terrainStartHeight1; | 837 | if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) |
832 | handshake.RegionInfo.TerrainStartHeight10 = args.terrainStartHeight2; | 838 | flags |= RegionFlags.ResetHomeOnTeleport; |
833 | handshake.RegionInfo.TerrainStartHeight11 = args.terrainStartHeight3; | 839 | if (Scene.RegionInfo.RegionSettings.FixedSun) |
834 | handshake.RegionInfo.SimAccess = args.simAccess; | 840 | flags |= RegionFlags.SunFixed; |
835 | handshake.RegionInfo.WaterHeight = args.waterHeight; | 841 | // allow access override (was taxfree) |
836 | 842 | if (Scene.RegionInfo.RegionSettings.BlockTerraform) | |
837 | handshake.RegionInfo.RegionFlags = args.regionFlags; | 843 | flags |= RegionFlags.BlockTerraform; |
838 | handshake.RegionInfo.SimName = Util.StringToBytes256(args.regionName); | 844 | if (!Scene.RegionInfo.RegionSettings.AllowLandResell) |
839 | handshake.RegionInfo.SimOwner = args.SimOwner; | 845 | flags |= RegionFlags.BlockLandResell; |
840 | handshake.RegionInfo.TerrainBase0 = args.terrainBase0; | 846 | if (Scene.RegionInfo.RegionSettings.Sandbox) |
841 | handshake.RegionInfo.TerrainBase1 = args.terrainBase1; | 847 | flags |= RegionFlags.Sandbox; |
842 | handshake.RegionInfo.TerrainBase2 = args.terrainBase2; | 848 | // nulllayer not used |
843 | handshake.RegionInfo.TerrainBase3 = args.terrainBase3; | 849 | if (Scene.RegionInfo.RegionSettings.Casino) |
844 | handshake.RegionInfo.TerrainDetail0 = args.terrainDetail0; | 850 | flags |= RegionFlags.SkipAgentAction; // redefined |
845 | handshake.RegionInfo.TerrainDetail1 = args.terrainDetail1; | 851 | if (Scene.RegionInfo.RegionSettings.GodBlockSearch) |
846 | handshake.RegionInfo.TerrainDetail2 = args.terrainDetail2; | 852 | flags |= RegionFlags.SkipUpdateInterestList; // redefined |
847 | handshake.RegionInfo.TerrainDetail3 = args.terrainDetail3; | 853 | if (Scene.RegionInfo.RegionSettings.DisableCollisions) |
848 | handshake.RegionInfo.CacheID = UUID.Random(); //I guess this is for the client to remember an old setting? | 854 | flags |= RegionFlags.SkipCollisions; |
849 | handshake.RegionInfo2 = new RegionHandshakePacket.RegionInfo2Block(); | 855 | if (Scene.RegionInfo.RegionSettings.DisableScripts) |
850 | handshake.RegionInfo2.RegionID = regionInfo.RegionID; | 856 | flags |= RegionFlags.SkipScripts; |
851 | 857 | if (Scene.RegionInfo.RegionSettings.DisablePhysics) | |
852 | handshake.RegionInfo3 = new RegionHandshakePacket.RegionInfo3Block(); | 858 | flags |= RegionFlags.SkipPhysics; |
853 | handshake.RegionInfo3.CPUClassID = 9; | 859 | if (Scene.RegionInfo.EstateSettings.PublicAccess) |
854 | handshake.RegionInfo3.CPURatio = 1; | 860 | flags |= RegionFlags.ExternallyVisible; // ???? need revision |
855 | 861 | //MainlandVisible -> allow return enc object | |
856 | handshake.RegionInfo3.ColoName = Utils.EmptyBytes; | 862 | //PublicAllowed -> allow return enc estate object |
857 | handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); | 863 | if (Scene.RegionInfo.EstateSettings.BlockDwell) |
858 | handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; | 864 | flags |= RegionFlags.BlockDwell; |
859 | 865 | if (Scene.RegionInfo.RegionSettings.BlockFly) | |
860 | handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[1]; | 866 | flags |= RegionFlags.NoFly; |
861 | handshake.RegionInfo4[0] = new RegionHandshakePacket.RegionInfo4Block(); | 867 | if (Scene.RegionInfo.EstateSettings.AllowDirectTeleport) |
862 | handshake.RegionInfo4[0].RegionFlagsExtended = args.regionFlags; | 868 | flags |= RegionFlags.AllowDirectTeleport; |
863 | handshake.RegionInfo4[0].RegionProtocols = 0; // 1 here would indicate that SSB is supported | 869 | if (Scene.RegionInfo.EstateSettings.EstateSkipScripts) |
864 | 870 | flags |= RegionFlags.EstateSkipScripts; | |
865 | OutPacket(handshake, ThrottleOutPacketType.Unknown); | 871 | if (Scene.RegionInfo.RegionSettings.RestrictPushing) |
872 | flags |= RegionFlags.RestrictPushObject; | ||
873 | if (Scene.RegionInfo.EstateSettings.DenyAnonymous) | ||
874 | flags |= RegionFlags.DenyAnonymous; | ||
875 | //DenyIdentified unused | ||
876 | //DenyTransacted unused | ||
877 | if (Scene.RegionInfo.RegionSettings.AllowLandJoinDivide) | ||
878 | flags |= RegionFlags.AllowParcelChanges; | ||
879 | //AbuseEmailToEstateOwner -> block flyover | ||
880 | if (Scene.RegionInfo.EstateSettings.AllowVoice) | ||
881 | flags |= RegionFlags.AllowVoice; | ||
882 | if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) | ||
883 | flags |= RegionFlags.BlockParcelSearch; | ||
884 | if (Scene.RegionInfo.EstateSettings.DenyMinors) | ||
885 | flags |= RegionFlags.DenyAgeUnverified; | ||
886 | |||
887 | return (uint)flags; | ||
888 | } | ||
889 | |||
890 | // Region handshake may need a more detailed look | ||
891 | static private readonly byte[] RegionHandshakeHeader = new byte[] { | ||
892 | Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, | ||
893 | 0, 0, 0, 0, // sequence number | ||
894 | 0, // extra | ||
895 | //0xff, 0xff, 0, 148 // ID 148 (low frequency bigendian) | ||
896 | 0xff, 0xff, 0, 1, 148 // ID 148 (low frequency bigendian) zero encoded | ||
897 | }; | ||
898 | |||
899 | |||
900 | public void SendRegionHandshake() | ||
901 | { | ||
902 | RegionInfo regionInfo = m_scene.RegionInfo; | ||
903 | RegionSettings regionSettings = regionInfo.RegionSettings; | ||
904 | EstateSettings es = regionInfo.EstateSettings; | ||
905 | |||
906 | bool isEstateManager = m_scene.Permissions.IsEstateManager(AgentId); // go by oficial path | ||
907 | uint regionFlags = GetRegionFlags(); | ||
908 | |||
909 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
910 | Buffer.BlockCopy(RegionHandshakeHeader, 0, buf.Data, 0, 11); | ||
911 | |||
912 | // inline zeroencode | ||
913 | LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); | ||
914 | zc.Position = 11; | ||
915 | |||
916 | //RegionInfo Block | ||
917 | //RegionFlags U32 | ||
918 | zc.AddUInt(regionFlags); | ||
919 | //SimAccess U8 | ||
920 | zc.AddByte(regionInfo.AccessLevel); | ||
921 | //SimName | ||
922 | zc.AddShortString(regionInfo.RegionName, 255); | ||
923 | //SimOwner | ||
924 | zc.AddUUID(es.EstateOwner); | ||
925 | //IsEstateManager | ||
926 | zc.AddByte((byte)(isEstateManager ? 1 : 0)); | ||
927 | //WaterHeight | ||
928 | zc.AddFloat((float)regionSettings.WaterHeight); // why is this a double ?? | ||
929 | //BillableFactor | ||
930 | zc.AddFloat(es.BillableFactor); | ||
931 | //CacheID | ||
932 | zc.AddUUID(regionInfo.CacheID); | ||
933 | //TerrainBase0 | ||
934 | //TerrainBase1 | ||
935 | //TerrainBase2 | ||
936 | //TerrainBase3 | ||
937 | // this seem not obsolete, sending zero uuids | ||
938 | // we should send the basic low resolution default ? | ||
939 | zc.AddZeros(16 * 4); | ||
940 | //TerrainDetail0 | ||
941 | zc.AddUUID(regionSettings.TerrainTexture1); | ||
942 | //TerrainDetail1 | ||
943 | zc.AddUUID(regionSettings.TerrainTexture2); | ||
944 | //TerrainDetail2 | ||
945 | zc.AddUUID(regionSettings.TerrainTexture3); | ||
946 | //TerrainDetail3 | ||
947 | zc.AddUUID(regionSettings.TerrainTexture4); | ||
948 | //TerrainStartHeight00 | ||
949 | zc.AddFloat((float)regionSettings.Elevation1SW); | ||
950 | //TerrainStartHeight01 | ||
951 | zc.AddFloat((float)regionSettings.Elevation1NW); | ||
952 | //TerrainStartHeight10 | ||
953 | zc.AddFloat((float)regionSettings.Elevation1SE); | ||
954 | //TerrainStartHeight11 | ||
955 | zc.AddFloat((float)regionSettings.Elevation1NE); | ||
956 | //TerrainHeightRange00 | ||
957 | zc.AddFloat((float)regionSettings.Elevation2SW); | ||
958 | //TerrainHeightRange01 | ||
959 | zc.AddFloat((float)regionSettings.Elevation2NW); | ||
960 | //TerrainHeightRange10 | ||
961 | zc.AddFloat((float)regionSettings.Elevation2SE); | ||
962 | //TerrainHeightRange11 | ||
963 | zc.AddFloat((float)regionSettings.Elevation2NE); | ||
964 | |||
965 | //RegionInfo2 block | ||
966 | |||
967 | //region ID | ||
968 | zc.AddUUID(regionInfo.RegionID); | ||
969 | |||
970 | //RegionInfo3 block | ||
971 | |||
972 | //CPUClassID | ||
973 | zc.AddInt(9); | ||
974 | //CPURatio | ||
975 | zc.AddInt(1); | ||
976 | // ColoName (string) | ||
977 | // ProductSKU (string) | ||
978 | // both empty strings | ||
979 | zc.AddZeros(2); | ||
980 | //ProductName | ||
981 | zc.AddShortString(regionInfo.RegionType, 255); | ||
982 | |||
983 | //RegionInfo4 block | ||
984 | |||
985 | //RegionFlagsExtended | ||
986 | zc.AddZeros(1); // we dont have this | ||
987 | //zc.AddByte(1); | ||
988 | //zc.AddUInt64(regionFlags); // we have nothing other base flags | ||
989 | //RegionProtocols | ||
990 | //zc.AddUInt64(0); // bit 0 signals server side texture baking" | ||
991 | |||
992 | buf.DataLength = zc.Finish(); | ||
993 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown); | ||
866 | } | 994 | } |
867 | 995 | ||
996 | static private readonly byte[] AgentMovementCompleteHeader = new byte[] { | ||
997 | Helpers.MSG_RELIABLE, | ||
998 | 0, 0, 0, 0, // sequence number | ||
999 | 0, // extra | ||
1000 | 0xff, 0xff, 0, 250 // ID 250 (low frequency bigendian) | ||
1001 | }; | ||
868 | 1002 | ||
869 | public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) | 1003 | public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) |
870 | { | 1004 | { |
1005 | // reset agent update args | ||
871 | m_thisAgentUpdateArgs.CameraAtAxis.X = float.MinValue; | 1006 | m_thisAgentUpdateArgs.CameraAtAxis.X = float.MinValue; |
872 | m_thisAgentUpdateArgs.lastUpdateTS = 0; | 1007 | m_thisAgentUpdateArgs.lastUpdateTS = 0; |
873 | m_thisAgentUpdateArgs.ControlFlags = 0; | 1008 | m_thisAgentUpdateArgs.ControlFlags = 0; |
874 | 1009 | ||
875 | AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); | 1010 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
876 | mov.SimData.ChannelVersion = m_channelVersion; | 1011 | byte[] data = buf.Data; |
877 | mov.AgentData.SessionID = m_sessionId; | 1012 | |
878 | mov.AgentData.AgentID = AgentId; | 1013 | //setup header |
879 | mov.Data.RegionHandle = regInfo.RegionHandle; | 1014 | Buffer.BlockCopy(AgentMovementCompleteHeader, 0, data, 0, 10); |
880 | mov.Data.Timestamp = (uint)Util.UnixTimeSinceEpoch(); | 1015 | |
1016 | //AgentData block | ||
1017 | AgentId.ToBytes(data, 10); // 26 | ||
1018 | SessionId.ToBytes(data, 26); // 42 | ||
881 | 1019 | ||
1020 | //Data block | ||
882 | if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0)) | 1021 | if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0)) |
1022 | m_startpos.ToBytes(data, 42); //54 | ||
1023 | else | ||
1024 | pos.ToBytes(data, 42); //54 | ||
1025 | look.ToBytes(data, 54); // 66 | ||
1026 | Utils.UInt64ToBytesSafepos(regInfo.RegionHandle, data, 66); // 74 | ||
1027 | Utils.UIntToBytesSafepos((uint)Util.UnixTimeSinceEpoch(), data, 74); //78 | ||
1028 | |||
1029 | //SimData | ||
1030 | int len = m_regionChannelVersion.Length; | ||
1031 | if(len == 0) | ||
883 | { | 1032 | { |
884 | mov.Data.Position = m_startpos; | 1033 | data[78] = 0; |
1034 | data[79] = 0; | ||
885 | } | 1035 | } |
886 | else | 1036 | else |
887 | { | 1037 | { |
888 | mov.Data.Position = pos; | 1038 | data[78] = (byte)len; |
1039 | data[79] = (byte)(len >> 8); | ||
1040 | Buffer.BlockCopy(m_regionChannelVersion, 0, data, 80, len); | ||
889 | } | 1041 | } |
890 | mov.Data.LookAt = look; | ||
891 | 1042 | ||
892 | // Hack to get this out immediately and skip the throttles | 1043 | buf.DataLength = 80 + len; |
893 | OutPacket(mov, ThrottleOutPacketType.Unknown); | 1044 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown); |
894 | } | 1045 | } |
895 | 1046 | ||
896 | public void SendChatMessage( | 1047 | static private readonly byte[] ChatFromSimulatorHeader = new byte[] { |
897 | string message, byte type, Vector3 fromPos, string fromName, | 1048 | Helpers.MSG_RELIABLE, |
898 | UUID fromAgentID, UUID ownerID, byte source, byte audible) | 1049 | 0, 0, 0, 0, // sequence number |
1050 | 0, // extra | ||
1051 | 0xff, 0xff, 0, 139 // ID 139 (low frequency bigendian) | ||
1052 | }; | ||
1053 | |||
1054 | public void SendChatMessage(string message, byte chattype, Vector3 fromPos, string fromName, | ||
1055 | UUID sourceID, UUID ownerID, byte sourcetype, byte audible) | ||
899 | { | 1056 | { |
900 | ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); | 1057 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
901 | reply.ChatData.Audible = audible; | 1058 | byte[] data = buf.Data; |
902 | reply.ChatData.Message = Util.StringToBytes1024(message); | 1059 | |
903 | reply.ChatData.ChatType = type; | 1060 | //setup header |
904 | reply.ChatData.SourceType = source; | 1061 | Buffer.BlockCopy(ChatFromSimulatorHeader, 0, data, 0, 10); |
905 | reply.ChatData.Position = fromPos; | 1062 | |
906 | reply.ChatData.FromName = Util.StringToBytes256(fromName); | 1063 | byte[] fname = Util.StringToBytes256(fromName); |
907 | reply.ChatData.OwnerID = ownerID; | 1064 | int len = fname.Length; |
908 | reply.ChatData.SourceID = fromAgentID; | 1065 | int pos = 11; |
1066 | if (len == 0) | ||
1067 | data[10] = 0; | ||
1068 | else | ||
1069 | { | ||
1070 | data[10] = (byte)len; | ||
1071 | Buffer.BlockCopy(fname, 0, data, 11, len); | ||
1072 | pos += len; | ||
1073 | } | ||
1074 | |||
1075 | sourceID.ToBytes(data, pos); pos += 16; | ||
1076 | ownerID.ToBytes(data, pos); pos += 16; | ||
1077 | data[pos++] = sourcetype; | ||
1078 | data[pos++] = chattype; | ||
1079 | data[pos++] = audible; | ||
1080 | fromPos.ToBytes(data, pos); pos += 12; | ||
909 | 1081 | ||
910 | OutPacket(reply, ThrottleOutPacketType.Unknown); | 1082 | byte[] msg = Util.StringToBytes1024(message); |
1083 | len = msg.Length; | ||
1084 | if (len == 0) | ||
1085 | { | ||
1086 | data[pos++] = 0; | ||
1087 | data[pos++] = 0; | ||
1088 | } | ||
1089 | else | ||
1090 | { | ||
1091 | data[pos++] = (byte)len; | ||
1092 | data[pos++] = (byte)(len >> 8); | ||
1093 | Buffer.BlockCopy(msg, 0, data, pos, len); pos += len; | ||
1094 | } | ||
1095 | |||
1096 | buf.DataLength = pos; | ||
1097 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown); | ||
911 | } | 1098 | } |
912 | 1099 | ||
913 | /// <summary> | 1100 | /// <summary> |
914 | /// Send an instant message to this client | 1101 | /// Send an instant message to this client |
915 | /// </summary> | 1102 | /// </summary> |
916 | // | 1103 | // |
1104 | |||
1105 | static private readonly byte[] ImprovedInstantMessageHeader = new byte[] { | ||
1106 | Helpers.MSG_RELIABLE, //| Helpers.MSG_ZEROCODED, not doing spec zeroencode on this | ||
1107 | 0, 0, 0, 0, // sequence number | ||
1108 | 0, // extra | ||
1109 | 0xff, 0xff, 0, 254 // ID 139 (low frequency bigendian) | ||
1110 | }; | ||
1111 | |||
917 | public void SendInstantMessage(GridInstantMessage im) | 1112 | public void SendInstantMessage(GridInstantMessage im) |
918 | { | 1113 | { |
919 | if (((Scene)(m_scene)).Permissions.CanInstantMessage(new UUID(im.fromAgentID), new UUID(im.toAgentID))) | 1114 | UUID fromAgentID = new UUID(im.fromAgentID); |
1115 | UUID toAgentID = new UUID(im.toAgentID); | ||
1116 | |||
1117 | if (!m_scene.Permissions.CanInstantMessage(fromAgentID, toAgentID)) | ||
1118 | return; | ||
1119 | |||
1120 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
1121 | byte[] data = buf.Data; | ||
1122 | |||
1123 | //setup header | ||
1124 | Buffer.BlockCopy(ImprovedInstantMessageHeader, 0, data, 0, 10); | ||
1125 | |||
1126 | //agentdata block | ||
1127 | fromAgentID.ToBytes(data, 10); // 26 | ||
1128 | UUID.Zero.ToBytes(data, 26); // 42 sessionID zero?? TO check | ||
1129 | |||
1130 | int pos = 42; | ||
1131 | |||
1132 | //MessageBlock | ||
1133 | data[pos++] = (byte)((im.fromGroup) ? 1 : 0); | ||
1134 | toAgentID.ToBytes(data, pos); pos += 16; | ||
1135 | Utils.UIntToBytesSafepos(im.ParentEstateID, data, pos); pos += 4; | ||
1136 | (new UUID(im.RegionID)).ToBytes(data, pos); pos += 16; | ||
1137 | (im.Position).ToBytes(data, pos); pos += 12; | ||
1138 | data[pos++] = im.offline; | ||
1139 | data[pos++] = im.dialog; | ||
1140 | |||
1141 | // this is odd | ||
1142 | if (im.imSessionID == UUID.Zero.Guid) | ||
1143 | (fromAgentID ^ toAgentID).ToBytes(data, pos); | ||
1144 | else | ||
1145 | (new UUID(im.imSessionID)).ToBytes(data, pos); | ||
1146 | |||
1147 | pos += 16; | ||
1148 | |||
1149 | Utils.UIntToBytesSafepos(im.timestamp, data, pos); pos += 4; | ||
1150 | |||
1151 | byte[] tmp = Util.StringToBytes256(im.fromAgentName); | ||
1152 | int len = tmp.Length; | ||
1153 | data[pos++] = (byte)len; | ||
1154 | if(len > 0) | ||
1155 | Buffer.BlockCopy(tmp, 0, data, pos, len); pos += len; | ||
1156 | |||
1157 | tmp = Util.StringToBytes1024(im.message); | ||
1158 | len = tmp.Length; | ||
1159 | if (len == 0) | ||
1160 | { | ||
1161 | data[pos++] = 0; | ||
1162 | data[pos++] = 0; | ||
1163 | } | ||
1164 | else | ||
920 | { | 1165 | { |
921 | ImprovedInstantMessagePacket msg | 1166 | data[pos++] = (byte)len; |
922 | = (ImprovedInstantMessagePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedInstantMessage); | 1167 | data[pos++] = (byte)(len >> 8); |
1168 | Buffer.BlockCopy(tmp, 0, data, pos, len); pos += len; | ||
1169 | } | ||
923 | 1170 | ||
924 | msg.AgentData.AgentID = new UUID(im.fromAgentID); | 1171 | tmp = im.binaryBucket; |
925 | msg.AgentData.SessionID = UUID.Zero; | 1172 | if(tmp == null) |
926 | msg.MessageBlock.FromAgentName = Util.StringToBytes256(im.fromAgentName); | 1173 | { |
927 | msg.MessageBlock.Dialog = im.dialog; | 1174 | data[pos++] = 0; |
928 | msg.MessageBlock.FromGroup = im.fromGroup; | 1175 | data[pos++] = 0; |
929 | // this is odd | 1176 | } |
930 | if (im.imSessionID == UUID.Zero.Guid) | 1177 | else |
931 | msg.MessageBlock.ID = new UUID(im.fromAgentID) ^ new UUID(im.toAgentID); | 1178 | { |
1179 | len = tmp.Length; | ||
1180 | if (len == 0) | ||
1181 | { | ||
1182 | data[pos++] = 0; | ||
1183 | data[pos++] = 0; | ||
1184 | } | ||
932 | else | 1185 | else |
933 | msg.MessageBlock.ID = new UUID(im.imSessionID); | 1186 | { |
934 | msg.MessageBlock.Offline = im.offline; | 1187 | data[pos++] = (byte)len; |
935 | msg.MessageBlock.ParentEstateID = im.ParentEstateID; | 1188 | data[pos++] = (byte)(len >> 8); |
936 | msg.MessageBlock.Position = im.Position; | 1189 | Buffer.BlockCopy(tmp, 0, data, pos, len); pos += len; |
937 | msg.MessageBlock.RegionID = new UUID(im.RegionID); | 1190 | } |
938 | msg.MessageBlock.Timestamp = im.timestamp; | ||
939 | msg.MessageBlock.ToAgentID = new UUID(im.toAgentID); | ||
940 | msg.MessageBlock.Message = Util.StringToBytes1024(im.message); | ||
941 | msg.MessageBlock.BinaryBucket = im.binaryBucket; | ||
942 | |||
943 | OutPacket(msg, ThrottleOutPacketType.Task); | ||
944 | } | 1191 | } |
1192 | |||
1193 | //EstateBlock does not seem in use TODO | ||
1194 | //Utils.UIntToBytesSafepos(m_scene.RegionInfo.EstateSettings.EstateID, data, pos); pos += 4; | ||
1195 | data[pos++] = 0; | ||
1196 | data[pos++] = 0; | ||
1197 | data[pos++] = 0; | ||
1198 | data[pos++] = 0; | ||
1199 | |||
1200 | buf.DataLength = pos; | ||
1201 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown, null, false, true); | ||
1202 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Unknown); | ||
945 | } | 1203 | } |
946 | 1204 | ||
1205 | static private readonly byte[] GenericMessageHeader = new byte[] { | ||
1206 | Helpers.MSG_RELIABLE, //| Helpers.MSG_ZEROCODED, not doing spec zeroencode on this | ||
1207 | 0, 0, 0, 0, // sequence number | ||
1208 | 0, // extra | ||
1209 | 0xff, 0xff, 1, 5 // ID 261 (low frequency bigendian) | ||
1210 | }; | ||
1211 | |||
947 | public void SendGenericMessage(string method, UUID invoice, List<string> message) | 1212 | public void SendGenericMessage(string method, UUID invoice, List<string> message) |
948 | { | 1213 | { |
949 | GenericMessagePacket gmp = new GenericMessagePacket(); | 1214 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
1215 | byte[] data = buf.Data; | ||
950 | 1216 | ||
951 | gmp.AgentData.AgentID = AgentId; | 1217 | //setup header |
952 | gmp.AgentData.SessionID = m_sessionId; | 1218 | Buffer.BlockCopy(GenericMessageHeader, 0, data, 0, 10); |
953 | gmp.AgentData.TransactionID = invoice; | ||
954 | 1219 | ||
955 | gmp.MethodData.Method = Util.StringToBytes256(method); | 1220 | //agentdata block |
956 | gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count]; | 1221 | m_agentId.ToBytes(data, 10); // 26 |
957 | int i = 0; | 1222 | m_sessionId.ToBytes(data, 26); // 42 sessionID zero?? TO check |
958 | foreach (string val in message) | 1223 | UUID.Zero.ToBytes(data, 42); // 58 |
1224 | |||
1225 | int pos = 58; | ||
1226 | |||
1227 | //method block | ||
1228 | byte[] tmp = Util.StringToBytes256(method); | ||
1229 | int len = tmp.Length; | ||
1230 | data[pos++] = (byte)len; | ||
1231 | if (len > 0) | ||
1232 | Buffer.BlockCopy(tmp, 0, data, pos, len); pos += len; | ||
1233 | invoice.ToBytes(data, pos); pos += 16; | ||
1234 | |||
1235 | //ParamList block | ||
1236 | if (message.Count == 0) | ||
959 | { | 1237 | { |
960 | gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock(); | 1238 | data[pos++] = 0; |
961 | gmp.ParamList[i++].Parameter = Util.StringToBytes256(val); | 1239 | buf.DataLength = pos; |
1240 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); | ||
1241 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
1242 | return; | ||
962 | } | 1243 | } |
963 | 1244 | ||
964 | OutPacket(gmp, ThrottleOutPacketType.Task); | 1245 | int countpos = pos; |
1246 | ++pos; | ||
1247 | |||
1248 | int count = 0; | ||
1249 | foreach (string val in message) | ||
1250 | { | ||
1251 | tmp = Util.StringToBytes256(val); | ||
1252 | len = tmp.Length; | ||
1253 | |||
1254 | if (pos + len >= LLUDPServer.MAXPAYLOAD) | ||
1255 | { | ||
1256 | data[countpos] = (byte)count; | ||
1257 | buf.DataLength = pos; | ||
1258 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); | ||
1259 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
1260 | |||
1261 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
1262 | Buffer.BlockCopy(data, 0, newbuf.Data, 0, countpos); | ||
1263 | buf = newbuf; | ||
1264 | data = buf.Data; | ||
1265 | pos = countpos + 1; | ||
1266 | count = 1; | ||
1267 | } | ||
1268 | else | ||
1269 | ++count; | ||
1270 | |||
1271 | data[pos++] = (byte)len; | ||
1272 | if (len > 0) | ||
1273 | Buffer.BlockCopy(tmp, 0, data, pos, len); pos += len; | ||
1274 | } | ||
1275 | if (count > 0) | ||
1276 | { | ||
1277 | data[countpos] = (byte)count; | ||
1278 | buf.DataLength = pos; | ||
1279 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); | ||
1280 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
1281 | } | ||
965 | } | 1282 | } |
966 | 1283 | ||
967 | public void SendGenericMessage(string method, UUID invoice, List<byte[]> message) | 1284 | public void SendGenericMessage(string method, UUID invoice, List<byte[]> message) |
968 | { | 1285 | { |
969 | GenericMessagePacket gmp = new GenericMessagePacket(); | 1286 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
1287 | byte[] data = buf.Data; | ||
970 | 1288 | ||
971 | gmp.AgentData.AgentID = AgentId; | 1289 | //setup header |
972 | gmp.AgentData.SessionID = m_sessionId; | 1290 | Buffer.BlockCopy(GenericMessageHeader, 0, data, 0, 10); |
973 | gmp.AgentData.TransactionID = invoice; | ||
974 | 1291 | ||
975 | gmp.MethodData.Method = Util.StringToBytes256(method); | 1292 | //agentdata block |
976 | gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count]; | 1293 | m_agentId.ToBytes(data, 10); // 26 |
977 | int i = 0; | 1294 | m_sessionId.ToBytes(data, 26); // 42 sessionID zero?? TO check |
978 | foreach (byte[] val in message) | 1295 | UUID.Zero.ToBytes(data, 42); // 58 |
1296 | |||
1297 | int pos = 58; | ||
1298 | |||
1299 | //method block | ||
1300 | byte[] tmp = Util.StringToBytes256(method); | ||
1301 | int len = tmp.Length; | ||
1302 | data[pos++] = (byte)len; | ||
1303 | if (len > 0) | ||
1304 | Buffer.BlockCopy(tmp, 0, data, pos, len); pos += len; | ||
1305 | invoice.ToBytes(data, pos); pos += 16; | ||
1306 | |||
1307 | //ParamList block | ||
1308 | if (message.Count == 0) | ||
979 | { | 1309 | { |
980 | gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock(); | 1310 | data[pos++] = 0; |
981 | gmp.ParamList[i++].Parameter = val; | 1311 | buf.DataLength = pos; |
1312 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); | ||
1313 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
1314 | return; | ||
982 | } | 1315 | } |
983 | 1316 | ||
984 | OutPacket(gmp, ThrottleOutPacketType.Task); | 1317 | int countpos = pos; |
1318 | ++pos; | ||
1319 | |||
1320 | int count = 0; | ||
1321 | foreach (byte[] val in message) | ||
1322 | { | ||
1323 | len = val.Length; | ||
1324 | if(len > 255) | ||
1325 | len = 255; | ||
1326 | |||
1327 | if (pos + len >= LLUDPServer.MAXPAYLOAD) | ||
1328 | { | ||
1329 | data[countpos] = (byte)count; | ||
1330 | buf.DataLength = pos; | ||
1331 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); | ||
1332 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
1333 | |||
1334 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
1335 | Buffer.BlockCopy(data, 0, newbuf.Data, 0, countpos); | ||
1336 | buf = newbuf; | ||
1337 | data = buf.Data; | ||
1338 | pos = countpos + 1; | ||
1339 | count = 1; | ||
1340 | } | ||
1341 | else | ||
1342 | ++count; | ||
1343 | |||
1344 | data[pos++] = (byte)len; | ||
1345 | if (len > 0) | ||
1346 | Buffer.BlockCopy(val, 0, data, pos, len); pos += len; | ||
1347 | } | ||
1348 | if (count > 0) | ||
1349 | { | ||
1350 | data[countpos] = (byte)count; | ||
1351 | buf.DataLength = pos; | ||
1352 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); | ||
1353 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
1354 | } | ||
985 | } | 1355 | } |
986 | 1356 | ||
987 | public void SendGroupActiveProposals(UUID groupID, UUID transactionID, GroupActiveProposals[] Proposals) | 1357 | public void SendGroupActiveProposals(UUID groupID, UUID transactionID, GroupActiveProposals[] Proposals) |
@@ -1302,7 +1672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1302 | { | 1672 | { |
1303 | s = 2 * i; | 1673 | s = 2 * i; |
1304 | OpenSimTerrainCompressor.CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]); | 1674 | OpenSimTerrainCompressor.CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]); |
1305 | if (bitpack.BytePos > 950 && i != numberPatchs - 1) | 1675 | if (bitpack.BytePos > 900 && i != numberPatchs - 1) |
1306 | { | 1676 | { |
1307 | //finish this packet | 1677 | //finish this packet |
1308 | bitpack.PackBitsFromByte(END_OF_PATCHES); | 1678 | bitpack.PackBitsFromByte(END_OF_PATCHES); |
@@ -1313,7 +1683,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1313 | data[9] = (byte)(datasize >> 8); | 1683 | data[9] = (byte)(datasize >> 8); |
1314 | 1684 | ||
1315 | buf.DataLength = bitpack.BytePos + 1; | 1685 | buf.DataLength = bitpack.BytePos + 1; |
1316 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false); | 1686 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land); |
1317 | 1687 | ||
1318 | // start another | 1688 | // start another |
1319 | buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | 1689 | buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
@@ -1341,7 +1711,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1341 | data[9] = (byte)(datasize >> 8); | 1711 | data[9] = (byte)(datasize >> 8); |
1342 | 1712 | ||
1343 | buf.DataLength = bitpack.BytePos + 1; | 1713 | buf.DataLength = bitpack.BytePos + 1; |
1344 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land, null, false, false); | 1714 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land); |
1345 | 1715 | ||
1346 | } | 1716 | } |
1347 | catch (Exception e) | 1717 | catch (Exception e) |
@@ -1561,57 +1931,210 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1561 | OutPacket(newSimPack, ThrottleOutPacketType.Unknown); | 1931 | OutPacket(newSimPack, ThrottleOutPacketType.Unknown); |
1562 | } | 1932 | } |
1563 | 1933 | ||
1564 | internal void SendMapBlockSplit(List<MapBlockData> mapBlocks, uint flag) | 1934 | static private readonly byte[] MapBlockItemHeader = new byte[] { |
1935 | Helpers.MSG_RELIABLE, | ||
1936 | 0, 0, 0, 0, // sequence number | ||
1937 | 0, // extra | ||
1938 | 0xff, 0xff, 1, 155 // ID 411 (low frequency bigendian) | ||
1939 | }; | ||
1940 | |||
1941 | public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) | ||
1565 | { | 1942 | { |
1566 | MapBlockReplyPacket mapReply = (MapBlockReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapBlockReply); | 1943 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
1567 | // TODO: don't create new blocks if recycling an old packet | 1944 | byte[] data = buf.Data; |
1568 | 1945 | ||
1569 | MapBlockData[] mapBlocks2 = mapBlocks.ToArray(); | 1946 | //setup header and agentinfo block |
1947 | Buffer.BlockCopy(MapBlockItemHeader, 0, data, 0, 10); | ||
1948 | AgentId.ToBytes(data, 10); // 26 | ||
1949 | Utils.UIntToBytesSafepos(flags, data, 26); // 30 | ||
1570 | 1950 | ||
1571 | mapReply.AgentData.AgentID = AgentId; | 1951 | //RequestData block |
1572 | mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length]; | 1952 | Utils.UIntToBytesSafepos(mapitemtype, data, 30); // 34 |
1573 | mapReply.Size = new MapBlockReplyPacket.SizeBlock[mapBlocks2.Length]; | 1953 | |
1574 | mapReply.AgentData.Flags = flag; | 1954 | int countpos = 34; |
1575 | 1955 | int pos = 35; | |
1576 | for (int i = 0; i < mapBlocks2.Length; i++) | 1956 | int lastpos = 0; |
1577 | { | 1957 | |
1578 | mapReply.Data[i] = new MapBlockReplyPacket.DataBlock(); | 1958 | int capacity = LLUDPServer.MAXPAYLOAD - pos; |
1579 | mapReply.Data[i].MapImageID = mapBlocks2[i].MapImageId; | 1959 | |
1580 | //m_log.Warn(mapBlocks2[i].MapImageId.ToString()); | 1960 | int count = 0; |
1581 | mapReply.Data[i].X = mapBlocks2[i].X; | 1961 | |
1582 | mapReply.Data[i].Y = mapBlocks2[i].Y; | 1962 | mapItemReply mr; |
1583 | mapReply.Data[i].WaterHeight = mapBlocks2[i].WaterHeight; | 1963 | for (int k = 0; k < replies.Length; ++k) |
1584 | mapReply.Data[i].Name = Utils.StringToBytes(mapBlocks2[i].Name); | 1964 | { |
1585 | mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags; | 1965 | lastpos = pos; |
1586 | mapReply.Data[i].Access = mapBlocks2[i].Access; | 1966 | mr = replies[k]; |
1587 | mapReply.Data[i].Agents = mapBlocks2[i].Agents; | 1967 | |
1588 | 1968 | Utils.UIntToBytesSafepos(mr.x, data, pos); pos += 4; | |
1589 | mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock(); | 1969 | Utils.UIntToBytesSafepos(mr.y, data, pos); pos += 4; |
1590 | mapReply.Size[i].SizeX = mapBlocks2[i].SizeX; | 1970 | mr.id.ToBytes(data, pos); pos += 16; |
1591 | mapReply.Size[i].SizeY = mapBlocks2[i].SizeY; | 1971 | Utils.IntToBytesSafepos(mr.Extra, data, pos); pos += 4; |
1972 | Utils.IntToBytesSafepos(mr.Extra2, data, pos); pos += 4; | ||
1973 | byte[] itemName = Util.StringToBytes256(mr.name); | ||
1974 | data[pos++] = (byte)itemName.Length; | ||
1975 | if (itemName.Length > 0) | ||
1976 | Buffer.BlockCopy(itemName, 0, data, pos, itemName.Length); pos += itemName.Length; | ||
1977 | |||
1978 | if (pos < capacity) | ||
1979 | ++count; | ||
1980 | else | ||
1981 | { | ||
1982 | // prepare next packet | ||
1983 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
1984 | Buffer.BlockCopy(data, 0, newbuf.Data, 0, 34); | ||
1985 | |||
1986 | // copy the block we already did | ||
1987 | int alreadyDone = pos - lastpos; | ||
1988 | Buffer.BlockCopy(data, lastpos, newbuf.Data, 35, alreadyDone); // 34 is datablock size | ||
1989 | |||
1990 | // finish current | ||
1991 | data[countpos] = (byte)count; | ||
1992 | |||
1993 | buf.DataLength = lastpos; | ||
1994 | // send it | ||
1995 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land); | ||
1996 | |||
1997 | buf = newbuf; | ||
1998 | data = buf.Data; | ||
1999 | pos = alreadyDone + 35; | ||
2000 | capacity = LLUDPServer.MAXPAYLOAD - pos; | ||
2001 | |||
2002 | count = 1; | ||
2003 | } | ||
2004 | } | ||
2005 | |||
2006 | if (count > 0) | ||
2007 | { | ||
2008 | data[countpos] = (byte)count; | ||
2009 | |||
2010 | buf.DataLength = pos; | ||
2011 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land); | ||
1592 | } | 2012 | } |
1593 | OutPacket(mapReply, ThrottleOutPacketType.Land); | ||
1594 | } | 2013 | } |
1595 | 2014 | ||
1596 | public void SendMapBlock(List<MapBlockData> mapBlocks, uint flag) | 2015 | static private readonly byte[] MapBlockReplyHeader = new byte[] { |
2016 | Helpers.MSG_RELIABLE, | ||
2017 | 0, 0, 0, 0, // sequence number | ||
2018 | 0, // extra | ||
2019 | 0xff, 0xff, 1, 153 // ID 409 (low frequency bigendian) | ||
2020 | }; | ||
2021 | |||
2022 | public void SendMapBlock(List<MapBlockData> mapBlocks, uint flags) | ||
1597 | { | 2023 | { |
1598 | MapBlockData[] mapBlocks2 = mapBlocks.ToArray(); | 2024 | ushort[] sizes = new ushort[2 * mapBlocks.Count]; |
2025 | bool needSizes = false; | ||
2026 | int sizesptr = 0; | ||
2027 | |||
2028 | // check if we will need sizes block and get them aside | ||
2029 | int count = 0; | ||
2030 | ushort ut; | ||
2031 | foreach (MapBlockData md in mapBlocks) | ||
2032 | { | ||
2033 | ut = md.SizeX; | ||
2034 | sizes[count++] = ut; | ||
2035 | if (ut > 256) | ||
2036 | needSizes = true; | ||
2037 | |||
2038 | ut = md.SizeY; | ||
2039 | sizes[count++] = ut; | ||
2040 | if (ut > 256) | ||
2041 | needSizes = true; | ||
2042 | } | ||
1599 | 2043 | ||
1600 | int maxsend = 10; | 2044 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
2045 | byte[] data = buf.Data; | ||
1601 | 2046 | ||
1602 | //int packets = Math.Ceiling(mapBlocks2.Length / maxsend); | 2047 | //setup header and agentinfo block |
2048 | Buffer.BlockCopy(MapBlockReplyHeader, 0, data, 0, 10); | ||
2049 | AgentId.ToBytes(data, 10); // 26 | ||
2050 | Utils.UIntToBytesSafepos(flags, data, 26); // 30 | ||
1603 | 2051 | ||
1604 | List<MapBlockData> sendingBlocks = new List<MapBlockData>(); | 2052 | int countpos = 30; |
2053 | int pos = 31; | ||
2054 | int lastpos = 0; | ||
1605 | 2055 | ||
1606 | for (int i = 0; i < mapBlocks2.Length; i++) | 2056 | int capacity = LLUDPServer.MAXPAYLOAD - pos; |
2057 | |||
2058 | count = 0; | ||
2059 | |||
2060 | foreach (MapBlockData md in mapBlocks) | ||
1607 | { | 2061 | { |
1608 | sendingBlocks.Add(mapBlocks2[i]); | 2062 | lastpos = pos; |
1609 | if (((i + 1) == mapBlocks2.Length) || (((i + 1) % maxsend) == 0)) | 2063 | |
2064 | Utils.UInt16ToBytes(md.X, data, pos); pos += 2; | ||
2065 | Utils.UInt16ToBytes(md.Y, data, pos); pos += 2; | ||
2066 | byte[] regionName = Util.StringToBytes256(md.Name); | ||
2067 | data[pos++] = (byte)regionName.Length; | ||
2068 | if(regionName.Length > 0) | ||
2069 | Buffer.BlockCopy(regionName, 0, data, pos, regionName.Length); pos += regionName.Length; | ||
2070 | data[pos++] = md.Access; | ||
2071 | Utils.UIntToBytesSafepos(md.RegionFlags, data, pos); pos += 4; | ||
2072 | data[pos++] = md.WaterHeight; | ||
2073 | data[pos++] = md.Agents; | ||
2074 | md.MapImageId.ToBytes(data, pos); pos += 16; | ||
2075 | |||
2076 | if(needSizes) | ||
2077 | capacity -= 4; // 2 shorts per entry | ||
2078 | |||
2079 | if(pos < capacity) | ||
2080 | ++count; | ||
2081 | else | ||
1610 | { | 2082 | { |
1611 | SendMapBlockSplit(sendingBlocks, flag); | 2083 | // prepare next packet |
1612 | sendingBlocks = new List<MapBlockData>(); | 2084 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
2085 | Buffer.BlockCopy(data, 0, newbuf.Data, 0, 30); | ||
2086 | |||
2087 | // copy the block we already did | ||
2088 | int alreadyDone = pos - lastpos; | ||
2089 | Buffer.BlockCopy(data, lastpos, newbuf.Data, 31, alreadyDone); // 30 is datablock size | ||
2090 | |||
2091 | // finish current | ||
2092 | data[countpos] = (byte)count; | ||
2093 | if (needSizes) | ||
2094 | { | ||
2095 | data[lastpos++] = (byte)count; | ||
2096 | while (--count >= 0) | ||
2097 | { | ||
2098 | Utils.UInt16ToBytes(sizes[sizesptr++], data, lastpos); lastpos += 2; | ||
2099 | Utils.UInt16ToBytes(sizes[sizesptr++], data, lastpos); lastpos += 2; | ||
2100 | } | ||
2101 | } | ||
2102 | else | ||
2103 | data[lastpos++] = 0; | ||
2104 | |||
2105 | buf.DataLength = lastpos; | ||
2106 | // send it | ||
2107 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land); | ||
2108 | |||
2109 | buf = newbuf; | ||
2110 | data = buf.Data; | ||
2111 | pos = alreadyDone + 31; | ||
2112 | capacity = LLUDPServer.MAXPAYLOAD - pos; | ||
2113 | if (needSizes) | ||
2114 | capacity -= 4; // 2 shorts per entry | ||
2115 | |||
2116 | count = 1; | ||
1613 | } | 2117 | } |
1614 | } | 2118 | } |
2119 | |||
2120 | if (count > 0) | ||
2121 | { | ||
2122 | data[countpos] = (byte)count; | ||
2123 | if (needSizes) | ||
2124 | { | ||
2125 | data[pos++] = (byte)count; | ||
2126 | while (--count >= 0) | ||
2127 | { | ||
2128 | Utils.UInt16ToBytes(sizes[sizesptr++], data, pos); pos += 2; | ||
2129 | Utils.UInt16ToBytes(sizes[sizesptr++], data, pos); pos += 2; | ||
2130 | } | ||
2131 | } | ||
2132 | else | ||
2133 | data[pos++] = 0; | ||
2134 | |||
2135 | buf.DataLength = pos; | ||
2136 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Land); | ||
2137 | } | ||
1615 | } | 2138 | } |
1616 | 2139 | ||
1617 | public void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags) | 2140 | public void SendLocalTeleport(Vector3 position, Vector3 lookAt, uint flags) |
@@ -1738,19 +2261,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1738 | OutPacket(payPriceReply, ThrottleOutPacketType.Task); | 2261 | OutPacket(payPriceReply, ThrottleOutPacketType.Task); |
1739 | } | 2262 | } |
1740 | 2263 | ||
1741 | public void SendStartPingCheck(byte seq) | ||
1742 | { | ||
1743 | StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); | ||
1744 | pc.Header.Reliable = false; | ||
1745 | |||
1746 | pc.PingID.PingID = seq; | ||
1747 | // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit | ||
1748 | pc.PingID.OldestUnacked = 0; | ||
1749 | |||
1750 | OutPacket(pc, ThrottleOutPacketType.Unknown); | ||
1751 | UDPClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount(); | ||
1752 | } | ||
1753 | |||
1754 | public void SendKillObject(List<uint> localIDs) | 2264 | public void SendKillObject(List<uint> localIDs) |
1755 | { | 2265 | { |
1756 | // foreach (uint id in localIDs) | 2266 | // foreach (uint id in localIDs) |
@@ -1815,14 +2325,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1815 | { | 2325 | { |
1816 | // An inventory descendents packet consists of a single agent section and an inventory details | 2326 | // An inventory descendents packet consists of a single agent section and an inventory details |
1817 | // section for each inventory item. The size of each inventory item is approximately 550 bytes. | 2327 | // section for each inventory item. The size of each inventory item is approximately 550 bytes. |
1818 | // In theory, UDP has a maximum packet size of 64k, so it should be possible to send descendent | 2328 | // limit to what may fit on MTU |
1819 | // packets containing metadata for in excess of 100 items. But in practice, there may be other | ||
1820 | // factors (e.g. firewalls) restraining the maximum UDP packet size. See, | ||
1821 | // | ||
1822 | // http://opensimulator.org/mantis/view.php?id=226 | ||
1823 | // | ||
1824 | // for one example of this kind of thing. In fact, the Linden servers appear to only send about | ||
1825 | // 6 to 7 items at a time, so let's stick with 6 | ||
1826 | int MAX_ITEMS_PER_PACKET = 5; | 2329 | int MAX_ITEMS_PER_PACKET = 5; |
1827 | int MAX_FOLDERS_PER_PACKET = 6; | 2330 | int MAX_FOLDERS_PER_PACKET = 6; |
1828 | 2331 | ||
@@ -2349,34 +2852,102 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2349 | OutPacket(scriptcontrol, ThrottleOutPacketType.Task); | 2852 | OutPacket(scriptcontrol, ThrottleOutPacketType.Task); |
2350 | } | 2853 | } |
2351 | 2854 | ||
2855 | static private readonly byte[] ReplyTaskInventoryHeader = new byte[] { | ||
2856 | Helpers.MSG_RELIABLE, //| Helpers.MSG_ZEROCODED, not doing spec zeroencode on this | ||
2857 | 0, 0, 0, 0, // sequence number | ||
2858 | 0, // extra | ||
2859 | 0xff, 0xff, 1, 34 // ID 90 (low frequency bigendian) | ||
2860 | }; | ||
2861 | |||
2352 | public void SendTaskInventory(UUID taskID, short serial, byte[] fileName) | 2862 | public void SendTaskInventory(UUID taskID, short serial, byte[] fileName) |
2353 | { | 2863 | { |
2354 | ReplyTaskInventoryPacket replytask = (ReplyTaskInventoryPacket)PacketPool.Instance.GetPacket(PacketType.ReplyTaskInventory); | 2864 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
2355 | replytask.InventoryData.TaskID = taskID; | 2865 | byte[] data = buf.Data; |
2356 | replytask.InventoryData.Serial = serial; | 2866 | |
2357 | replytask.InventoryData.Filename = fileName; | 2867 | //setup header |
2358 | // OutPacket(replytask, ThrottleOutPacketType.Task); | 2868 | Buffer.BlockCopy(ReplyTaskInventoryHeader, 0, data, 0, 10); |
2359 | OutPacket(replytask, ThrottleOutPacketType.Asset); | 2869 | |
2870 | taskID.ToBytes(data, 10); // 26 | ||
2871 | Utils.Int16ToBytes(serial, data, 26); // 28 | ||
2872 | data[28] = (byte)fileName.Length; | ||
2873 | if(data[28] > 0) | ||
2874 | Buffer.BlockCopy(fileName, 0, data, 29, data[28]); | ||
2875 | |||
2876 | buf.DataLength = 29 + data[28]; | ||
2877 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); | ||
2878 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
2360 | } | 2879 | } |
2361 | 2880 | ||
2362 | public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory) | 2881 | |
2882 | static private readonly byte[] SendXferPacketHeader = new byte[] { | ||
2883 | 0, //Helpers.MSG_RELIABLE, Xfer control must provide reliabialty | ||
2884 | 0, 0, 0, 0, // sequence number | ||
2885 | 0, // extra | ||
2886 | 18 // ID (high frequency bigendian) | ||
2887 | }; | ||
2888 | |||
2889 | public void SendXferPacket(ulong xferID, uint packet, | ||
2890 | byte[] XferData, int XferDataOffset, int XferDatapktLen, bool isTaskInventory) | ||
2363 | { | 2891 | { |
2364 | ThrottleOutPacketType type = ThrottleOutPacketType.Asset; | 2892 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
2365 | // if (isTaskInventory) | 2893 | byte[] data = buf.Data; |
2366 | // type = ThrottleOutPacketType.Task; | 2894 | |
2895 | //setup header | ||
2896 | Buffer.BlockCopy(SendXferPacketHeader, 0, data, 0, 7); | ||
2367 | 2897 | ||
2368 | SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); | 2898 | Utils.UInt64ToBytesSafepos(xferID, data, 7); // 15 |
2369 | sendXfer.XferID.ID = xferID; | 2899 | Utils.UIntToBytesSafepos(packet, data, 15); // 19 |
2370 | sendXfer.XferID.Packet = packet; | 2900 | |
2371 | sendXfer.DataPacket.Data = data; | 2901 | int len = XferDatapktLen; |
2372 | OutPacket(sendXfer, type); | 2902 | if (XferDataOffset == 0) // first packet needs to send the total xfer data len |
2903 | len += 4; | ||
2904 | |||
2905 | if (len > LLUDPServer.MAXPAYLOAD) // should never happen | ||
2906 | len = LLUDPServer.MAXPAYLOAD; | ||
2907 | if (len == 0) | ||
2908 | { | ||
2909 | data[19] = 0; | ||
2910 | data[20] = 0; | ||
2911 | } | ||
2912 | else | ||
2913 | { | ||
2914 | data[19] = (byte)len; | ||
2915 | data[20] = (byte)(len >> 8); | ||
2916 | if(XferDataOffset == 0) | ||
2917 | { | ||
2918 | // need to send total xfer data len | ||
2919 | Utils.IntToBytesSafepos(XferData.Length, data, 21); | ||
2920 | if (XferDatapktLen > 0) | ||
2921 | Buffer.BlockCopy(XferData, XferDataOffset, data, 25, XferDatapktLen); | ||
2922 | } | ||
2923 | else | ||
2924 | Buffer.BlockCopy(XferData, XferDataOffset, data, 21, XferDatapktLen); | ||
2925 | } | ||
2926 | |||
2927 | buf.DataLength = 21 + len; | ||
2928 | m_udpServer.SendUDPPacket(m_udpClient, buf, isTaskInventory ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); | ||
2373 | } | 2929 | } |
2374 | 2930 | ||
2931 | static private readonly byte[] AbortXferHeader = new byte[] { | ||
2932 | Helpers.MSG_RELIABLE, | ||
2933 | 0, 0, 0, 0, // sequence number | ||
2934 | 0, // extra | ||
2935 | 0xff, 0xff, 0, 157 // ID 157 (low frequency bigendian) | ||
2936 | }; | ||
2937 | |||
2375 | public void SendAbortXferPacket(ulong xferID) | 2938 | public void SendAbortXferPacket(ulong xferID) |
2376 | { | 2939 | { |
2377 | AbortXferPacket xferItem = (AbortXferPacket)PacketPool.Instance.GetPacket(PacketType.AbortXfer); | 2940 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
2378 | xferItem.XferID.ID = xferID; | 2941 | byte[] data = buf.Data; |
2379 | OutPacket(xferItem, ThrottleOutPacketType.Asset); | 2942 | |
2943 | //setup header | ||
2944 | Buffer.BlockCopy(AbortXferHeader, 0, data, 0, 10); | ||
2945 | |||
2946 | Utils.UInt64ToBytesSafepos(xferID, data, 10); // 18 | ||
2947 | Utils.IntToBytesSafepos(0, data, 18); // 22 reason TODO | ||
2948 | |||
2949 | buf.DataLength = 22; | ||
2950 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Asset); | ||
2380 | } | 2951 | } |
2381 | 2952 | ||
2382 | public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, | 2953 | public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit, |
@@ -3405,28 +3976,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3405 | OutPacket(packet, ThrottleOutPacketType.Task); | 3976 | OutPacket(packet, ThrottleOutPacketType.Task); |
3406 | } | 3977 | } |
3407 | 3978 | ||
3408 | public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) | ||
3409 | { | ||
3410 | MapItemReplyPacket mirplk = new MapItemReplyPacket(); | ||
3411 | mirplk.AgentData.AgentID = AgentId; | ||
3412 | mirplk.RequestData.ItemType = mapitemtype; | ||
3413 | mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length]; | ||
3414 | for (int i = 0; i < replies.Length; i++) | ||
3415 | { | ||
3416 | MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock(); | ||
3417 | mrdata.X = replies[i].x; | ||
3418 | mrdata.Y = replies[i].y; | ||
3419 | mrdata.ID = replies[i].id; | ||
3420 | mrdata.Extra = replies[i].Extra; | ||
3421 | mrdata.Extra2 = replies[i].Extra2; | ||
3422 | mrdata.Name = Utils.StringToBytes(replies[i].name); | ||
3423 | mirplk.Data[i] = mrdata; | ||
3424 | } | ||
3425 | //m_log.Debug(mirplk.ToString()); | ||
3426 | OutPacket(mirplk, ThrottleOutPacketType.Task); | ||
3427 | |||
3428 | } | ||
3429 | |||
3430 | public void SendOfferCallingCard(UUID srcID, UUID transactionID) | 3979 | public void SendOfferCallingCard(UUID srcID, UUID transactionID) |
3431 | { | 3980 | { |
3432 | // a bit special, as this uses AgentID to store the source instead | 3981 | // a bit special, as this uses AgentID to store the source instead |
@@ -3871,96 +4420,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3871 | OutPacket(aw, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); | 4420 | OutPacket(aw, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); |
3872 | } | 4421 | } |
3873 | 4422 | ||
3874 | public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) | 4423 | static private readonly byte[] AvatarAppearanceHeader = new byte[] { |
3875 | { | 4424 | Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, |
3876 | // m_log.DebugFormat( | 4425 | 0, 0, 0, 0, // sequence number |
3877 | // "[LLCLIENTVIEW]: Sending avatar appearance for {0} with {1} bytes to {2} {3}", | 4426 | 0, // extra |
3878 | // agentID, textureEntry.Length, Name, AgentId); | 4427 | 0xff, 0xff, 0, 158 // ID 158 (low frequency bigendian) not zeroencoded |
3879 | 4428 | //0xff, 0xff, 0, 1, 158 // ID 158 (low frequency bigendian) zeroencoded | |
3880 | AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); | 4429 | }; |
3881 | // TODO: don't create new blocks if recycling an old packet | ||
3882 | avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[visualParams.Length]; | ||
3883 | avp.ObjectData.TextureEntry = textureEntry; | ||
3884 | |||
3885 | AvatarAppearancePacket.VisualParamBlock avblock = null; | ||
3886 | for (int i = 0; i < visualParams.Length; i++) | ||
3887 | { | ||
3888 | avblock = new AvatarAppearancePacket.VisualParamBlock(); | ||
3889 | avblock.ParamValue = visualParams[i]; | ||
3890 | avp.VisualParam[i] = avblock; | ||
3891 | } | ||
3892 | |||
3893 | avp.Sender.IsTrial = false; | ||
3894 | avp.Sender.ID = agentID; | ||
3895 | avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; | ||
3896 | avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0]; | ||
3897 | |||
3898 | // this need be use in future ? | ||
3899 | // avp.AppearanceData[0].AppearanceVersion = 0; | ||
3900 | // avp.AppearanceData[0].CofVersion = 0; | ||
3901 | |||
3902 | //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); | ||
3903 | OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); | ||
3904 | } | ||
3905 | 4430 | ||
3906 | /* | 4431 | public void SendAppearance(UUID targetID, byte[] visualParams, byte[] textureEntry) |
3907 | public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) | ||
3908 | { | 4432 | { |
3909 | // m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name); | 4433 | // doing post zero encode, because odds of beeing bad are not that low |
4434 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
4435 | Buffer.BlockCopy(AvatarAppearanceHeader, 0, buf.Data, 0, 10); | ||
4436 | byte[] data = buf.Data; | ||
4437 | int pos = 10; | ||
3910 | 4438 | ||
3911 | AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); | 4439 | //sender block |
3912 | // TODO: don't create new blocks if recycling an old packet | 4440 | targetID.ToBytes(data, pos); pos += 16; |
3913 | ani.Sender = new AvatarAnimationPacket.SenderBlock(); | 4441 | data[pos++] = 0;// is trial = false |
3914 | ani.Sender.ID = sourceAgentId; | ||
3915 | ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length]; | ||
3916 | ani.PhysicalAvatarEventList = new AvatarAnimationPacket.PhysicalAvatarEventListBlock[0]; | ||
3917 | 4442 | ||
3918 | //self animations | 4443 | // objectdata block ie texture |
3919 | if (sourceAgentId == AgentId) | 4444 | int len = textureEntry.Length; |
4445 | if (len == 0) | ||
3920 | { | 4446 | { |
3921 | List<int> withobjects = new List<int>(animations.Length); | 4447 | data[pos++] = 0; |
3922 | List<int> noobjects = new List<int>(animations.Length); | 4448 | data[pos++] = 0; |
3923 | for(int i = 0; i < animations.Length; ++i) | ||
3924 | { | ||
3925 | if(objectIDs[i] == sourceAgentId || objectIDs[i] == UUID.Zero) | ||
3926 | noobjects.Add(i); | ||
3927 | else | ||
3928 | withobjects.Add(i); | ||
3929 | } | ||
3930 | |||
3931 | ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[withobjects.Count]; | ||
3932 | int k = 0; | ||
3933 | foreach (int i in withobjects) | ||
3934 | { | ||
3935 | ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock(); | ||
3936 | ani.AnimationList[k].AnimID = animations[i]; | ||
3937 | ani.AnimationList[k].AnimSequenceID = seqs[i]; | ||
3938 | ani.AnimationSourceList[k] = new AvatarAnimationPacket.AnimationSourceListBlock(); | ||
3939 | ani.AnimationSourceList[k].ObjectID = objectIDs[i]; | ||
3940 | k++; | ||
3941 | } | ||
3942 | foreach (int i in noobjects) | ||
3943 | { | ||
3944 | ani.AnimationList[k] = new AvatarAnimationPacket.AnimationListBlock(); | ||
3945 | ani.AnimationList[k].AnimID = animations[i]; | ||
3946 | ani.AnimationList[k].AnimSequenceID = seqs[i]; | ||
3947 | k++; | ||
3948 | } | ||
3949 | } | 4449 | } |
3950 | else | 4450 | else |
3951 | { | 4451 | { |
3952 | ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[0]; | 4452 | data[pos++] = (byte)len; |
3953 | for (int i = 0; i < animations.Length; ++i) | 4453 | data[pos++] = (byte)(len >> 8); |
3954 | { | 4454 | Buffer.BlockCopy(textureEntry, 0, data, pos, len); pos += len; |
3955 | ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock(); | ||
3956 | ani.AnimationList[i].AnimID = animations[i]; | ||
3957 | ani.AnimationList[i].AnimSequenceID = seqs[i]; | ||
3958 | } | ||
3959 | } | 4455 | } |
3960 | 4456 | ||
3961 | OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); | 4457 | // visual parameters |
4458 | len = visualParams.Length; | ||
4459 | data[pos++] = (byte)len; | ||
4460 | if(len > 0) | ||
4461 | Buffer.BlockCopy(visualParams, 0, data, pos, len); pos += len; | ||
4462 | |||
4463 | // no AppearanceData | ||
4464 | data[pos++] = 0; | ||
4465 | // no AppearanceHover | ||
4466 | data[pos++] = 0; | ||
4467 | |||
4468 | buf.DataLength = pos; | ||
4469 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true); | ||
3962 | } | 4470 | } |
3963 | */ | ||
3964 | 4471 | ||
3965 | static private readonly byte[] AvatarAnimationHeader = new byte[] { | 4472 | static private readonly byte[] AvatarAnimationHeader = new byte[] { |
3966 | Helpers.MSG_RELIABLE, | 4473 | Helpers.MSG_RELIABLE, |
@@ -4030,8 +4537,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4030 | data[pos++] = 0; // no physical avatar events | 4537 | data[pos++] = 0; // no physical avatar events |
4031 | 4538 | ||
4032 | buf.DataLength = pos; | 4539 | buf.DataLength = pos; |
4033 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, | 4540 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); |
4034 | null, false, false); | ||
4035 | } | 4541 | } |
4036 | 4542 | ||
4037 | public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId) | 4543 | public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId) |
@@ -4088,84 +4594,102 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4088 | CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc); | 4594 | CreatePrimUpdateBlock(ent as SceneObjectPart, (ScenePresence)SceneAgent, zc); |
4089 | 4595 | ||
4090 | buf.DataLength = zc.Finish(); | 4596 | buf.DataLength = zc.Finish(); |
4091 | m_udpServer.SendUDPPacket(m_udpClient, buf, ptype , null, false, false); | 4597 | m_udpServer.SendUDPPacket(m_udpClient, buf, ptype); |
4092 | } | 4598 | } |
4093 | 4599 | ||
4094 | public void SendEntityTerseUpdateImmediate(ISceneEntity ent) | 4600 | public void SendEntityTerseUpdateImmediate(ISceneEntity ent) |
4095 | { | 4601 | { |
4096 | // m_log.DebugFormat( | ||
4097 | // "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}", | ||
4098 | // avatar.Name, avatar.UUID, Name, AgentId); | ||
4099 | |||
4100 | if (ent == null) | 4602 | if (ent == null) |
4101 | return; | 4603 | return; |
4102 | 4604 | ||
4103 | ImprovedTerseObjectUpdatePacket objupdate = | 4605 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
4104 | (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
4105 | objupdate.Header.Zerocoded = true; | ||
4106 | 4606 | ||
4107 | objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); | 4607 | //setup header and regioninfo block |
4108 | objupdate.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | 4608 | Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7); |
4609 | if (ent is ScenePresence) | ||
4610 | Utils.UInt64ToBytesSafepos(((ScenePresence)ent).RegionHandle, buf.Data, 7); | ||
4611 | else | ||
4612 | Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); | ||
4109 | 4613 | ||
4110 | if(ent is ScenePresence) | 4614 | Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), buf.Data, 15); |
4111 | { | 4615 | buf.Data[17] = 1; |
4112 | ScenePresence presence = ent as ScenePresence; | ||
4113 | objupdate.RegionData.RegionHandle = presence.RegionHandle; | ||
4114 | objupdate.ObjectData[0] = CreateImprovedTerseBlock(ent); | ||
4115 | } | ||
4116 | else if(ent is SceneObjectPart) | ||
4117 | { | ||
4118 | SceneObjectPart part = ent as SceneObjectPart; | ||
4119 | objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | ||
4120 | objupdate.ObjectData[0] = CreateImprovedTerseBlock(ent); | ||
4121 | } | ||
4122 | 4616 | ||
4123 | OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); | 4617 | int pos = 18; |
4618 | CreateImprovedTerseBlock(ent, buf.Data, ref pos, false); | ||
4124 | 4619 | ||
4125 | // We need to record the avatar local id since the root prim of an attachment points to this. | 4620 | buf.DataLength = pos; |
4126 | // m_attachmentsSent.Add(avatar.LocalId); | 4621 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); |
4127 | } | 4622 | } |
4128 | 4623 | ||
4624 | //UUID m_courseLocationPrey = UUID.Zero; | ||
4625 | bool m_couseLocationLastEmpty = false; | ||
4626 | |||
4627 | static private readonly byte[] CoarseLocationUpdateHeader = new byte[] { | ||
4628 | 0, // no acks plz | ||
4629 | 0, 0, 0, 0, // sequence number | ||
4630 | 0, // extra | ||
4631 | 0xff, 6 // ID 6 (medium frequency) | ||
4632 | }; | ||
4633 | |||
4129 | public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) | 4634 | public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) |
4130 | { | 4635 | { |
4131 | // We don't need to update inactive clients. | 4636 | // We don't need to update inactive clients. |
4132 | if (!IsActive) | 4637 | if (!IsActive) |
4133 | return; | 4638 | return; |
4134 | 4639 | ||
4135 | CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); | 4640 | int totalLocations = Math.Min(CoarseLocations.Count, 60); |
4136 | loc.Header.Reliable = false; | 4641 | if(totalLocations == 0) |
4642 | { | ||
4643 | if(m_couseLocationLastEmpty) | ||
4644 | return; | ||
4645 | m_couseLocationLastEmpty = true; | ||
4646 | } | ||
4647 | else | ||
4648 | m_couseLocationLastEmpty = false; | ||
4137 | 4649 | ||
4138 | // Each packet can only hold around 60 avatar positions and the client clears the mini-map each time | 4650 | int totalAgents = Math.Min(users.Count, 60); |
4139 | // a CoarseLocationUpdate packet is received. Oh well. | 4651 | if(totalAgents > totalLocations) |
4140 | int total = Math.Min(CoarseLocations.Count, 60); | 4652 | totalAgents = totalLocations; |
4141 | 4653 | ||
4142 | CoarseLocationUpdatePacket.IndexBlock ib = new CoarseLocationUpdatePacket.IndexBlock(); | 4654 | int selfindex = -1; |
4655 | int preyindex = -1; | ||
4143 | 4656 | ||
4144 | loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total]; | 4657 | //bool doprey = m_courseLocationPrey != UUID.Zero; |
4145 | loc.AgentData = new CoarseLocationUpdatePacket.AgentDataBlock[total]; | ||
4146 | 4658 | ||
4147 | int selfindex = -1; | 4659 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
4148 | for (int i = 0; i < total; i++) | 4660 | Buffer.BlockCopy(CoarseLocationUpdateHeader, 0, buf.Data, 0, 8); |
4149 | { | 4661 | byte[] data = buf.Data; |
4150 | CoarseLocationUpdatePacket.LocationBlock lb = | ||
4151 | new CoarseLocationUpdatePacket.LocationBlock(); | ||
4152 | 4662 | ||
4153 | lb.X = (byte)CoarseLocations[i].X; | 4663 | data[8] = (byte)totalLocations; |
4154 | lb.Y = (byte)CoarseLocations[i].Y; | 4664 | int pos = 9; |
4155 | 4665 | ||
4156 | lb.Z = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25f); | 4666 | for (int i = 0; i < totalLocations; ++i) |
4157 | loc.Location[i] = lb; | 4667 | { |
4158 | loc.AgentData[i] = new CoarseLocationUpdatePacket.AgentDataBlock(); | 4668 | data[pos++] = (byte)CoarseLocations[i].X; |
4159 | loc.AgentData[i].AgentID = users[i]; | 4669 | data[pos++] = (byte)CoarseLocations[i].Y; |
4160 | if (users[i] == AgentId) | 4670 | data[pos++] = CoarseLocations[i].Z > 1024 ? (byte)0 : (byte)(CoarseLocations[i].Z * 0.25f); |
4161 | selfindex = i; | 4671 | |
4672 | if (i < totalAgents) | ||
4673 | { | ||
4674 | if (users[i] == AgentId) | ||
4675 | selfindex = i; | ||
4676 | //if (doprey && users[i] == m_courseLocationPrey) | ||
4677 | // preyindex = i; | ||
4678 | } | ||
4162 | } | 4679 | } |
4163 | 4680 | ||
4164 | ib.You = (short)selfindex; | 4681 | Utils.Int16ToBytes((short)selfindex, data, pos); pos += 2; |
4165 | ib.Prey = -1; | 4682 | Utils.Int16ToBytes((short)preyindex, data, pos); pos += 2; |
4166 | loc.Index = ib; | 4683 | |
4684 | data[pos++] = (byte)totalAgents; | ||
4685 | for (int i = 0; i < totalAgents; ++i) | ||
4686 | { | ||
4687 | users[i].ToBytes(data, pos); | ||
4688 | pos += 16; | ||
4689 | } | ||
4167 | 4690 | ||
4168 | OutPacket(loc, ThrottleOutPacketType.Task); | 4691 | buf.DataLength = pos; |
4692 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
4169 | } | 4693 | } |
4170 | 4694 | ||
4171 | #endregion Avatar Packet/Data Sending Methods | 4695 | #endregion Avatar Packet/Data Sending Methods |
@@ -4178,20 +4702,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4178 | /// </summary> | 4702 | /// </summary> |
4179 | public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) | 4703 | public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) |
4180 | { | 4704 | { |
4181 | /* | ||
4182 | if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) | ||
4183 | { | ||
4184 | ImprovedTerseObjectUpdatePacket packet | ||
4185 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
4186 | |||
4187 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | ||
4188 | packet.RegionData.TimeDilation = Utils.FloatToUInt16(1, 0.0f, 1.0f); | ||
4189 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | ||
4190 | packet.ObjectData[0] = CreateImprovedTerseBlock(entity, false); | ||
4191 | OutPacket(packet, ThrottleOutPacketType.Unknown, true); | ||
4192 | return; | ||
4193 | } | ||
4194 | */ | ||
4195 | if (entity is SceneObjectPart) | 4705 | if (entity is SceneObjectPart) |
4196 | { | 4706 | { |
4197 | SceneObjectPart p = (SceneObjectPart)entity; | 4707 | SceneObjectPart p = (SceneObjectPart)entity; |
@@ -4210,7 +4720,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4210 | } | 4720 | } |
4211 | } | 4721 | } |
4212 | 4722 | ||
4213 | //double priority = m_prioritizer.GetUpdatePriority(this, entity); | ||
4214 | uint priority = m_prioritizer.GetUpdatePriority(this, entity); | 4723 | uint priority = m_prioritizer.GetUpdatePriority(this, entity); |
4215 | 4724 | ||
4216 | lock (m_entityUpdates.SyncRoot) | 4725 | lock (m_entityUpdates.SyncRoot) |
@@ -4273,6 +4782,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4273 | 15 // ID (high frequency) | 4782 | 15 // ID (high frequency) |
4274 | }; | 4783 | }; |
4275 | 4784 | ||
4785 | static private readonly byte[] ObjectAnimationHeader = new byte[] { | ||
4786 | Helpers.MSG_RELIABLE, | ||
4787 | 0, 0, 0, 0, // sequence number | ||
4788 | 0, // extra | ||
4789 | 30 // ID (high frequency) | ||
4790 | }; | ||
4791 | |||
4792 | static private readonly byte[] CompressedObjectHeader = new byte[] { | ||
4793 | Helpers.MSG_RELIABLE, | ||
4794 | 0, 0, 0, 0, // sequence number | ||
4795 | 0, // extra | ||
4796 | 13 // ID (high frequency) | ||
4797 | }; | ||
4798 | |||
4799 | static private readonly byte[] ObjectUpdateCachedHeader = new byte[] { | ||
4800 | Helpers.MSG_RELIABLE, | ||
4801 | 0, 0, 0, 0, // sequence number | ||
4802 | 0, // extra | ||
4803 | 14 // ID (high frequency) | ||
4804 | }; | ||
4805 | |||
4276 | private void ProcessEntityUpdates(int maxUpdatesBytes) | 4806 | private void ProcessEntityUpdates(int maxUpdatesBytes) |
4277 | { | 4807 | { |
4278 | if (!IsActive) | 4808 | if (!IsActive) |
@@ -4282,9 +4812,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4282 | if (mysp == null) | 4812 | if (mysp == null) |
4283 | return; | 4813 | return; |
4284 | 4814 | ||
4285 | // List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = null; | 4815 | |
4286 | List<EntityUpdate> objectUpdates = null; | 4816 | List<EntityUpdate> objectUpdates = null; |
4287 | // List<EntityUpdate> compressedUpdates = null; | 4817 | List<EntityUpdate> objectUpdateProbes = null; |
4818 | List<EntityUpdate> compressedUpdates = null; | ||
4288 | List<EntityUpdate> terseUpdates = null; | 4819 | List<EntityUpdate> terseUpdates = null; |
4289 | List<SceneObjectPart> ObjectAnimationUpdates = null; | 4820 | List<SceneObjectPart> ObjectAnimationUpdates = null; |
4290 | 4821 | ||
@@ -4296,6 +4827,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4296 | 4827 | ||
4297 | EntityUpdate update; | 4828 | EntityUpdate update; |
4298 | 4829 | ||
4830 | bool viewerCache = m_supportViewerCache;// && mysp.IsChildAgent; // only on child agents | ||
4299 | bool doCulling = m_scene.ObjectsCullingByDistance; | 4831 | bool doCulling = m_scene.ObjectsCullingByDistance; |
4300 | float cullingrange = 64.0f; | 4832 | float cullingrange = 64.0f; |
4301 | Vector3 mypos = Vector3.Zero; | 4833 | Vector3 mypos = Vector3.Zero; |
@@ -4304,7 +4836,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4304 | bool orderedDequeue = false; // temporary off | 4836 | bool orderedDequeue = false; // temporary off |
4305 | 4837 | ||
4306 | HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>(); | 4838 | HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>(); |
4307 | 4839 | bool useCompressUpdate = false; | |
4308 | 4840 | ||
4309 | if (doCulling) | 4841 | if (doCulling) |
4310 | { | 4842 | { |
@@ -4331,15 +4863,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4331 | } | 4863 | } |
4332 | } | 4864 | } |
4333 | 4865 | ||
4334 | PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; | 4866 | PrimUpdateFlags updateFlags = update.Flags; |
4335 | 4867 | ||
4336 | if(updateFlags.HasFlag(PrimUpdateFlags.Kill)) | 4868 | if (updateFlags.HasFlag(PrimUpdateFlags.Kill)) |
4337 | { | 4869 | { |
4338 | m_killRecord.Add(update.Entity.LocalId); | 4870 | m_killRecord.Add(update.Entity.LocalId); |
4339 | maxUpdatesBytes -= 30; | 4871 | maxUpdatesBytes -= 30; |
4340 | continue; | 4872 | continue; |
4341 | } | 4873 | } |
4342 | 4874 | ||
4875 | useCompressUpdate = false; | ||
4876 | bool istree = false; | ||
4877 | |||
4343 | if (update.Entity is SceneObjectPart) | 4878 | if (update.Entity is SceneObjectPart) |
4344 | { | 4879 | { |
4345 | SceneObjectPart part = (SceneObjectPart)update.Entity; | 4880 | SceneObjectPart part = (SceneObjectPart)update.Entity; |
@@ -4425,10 +4960,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4425 | if (dpos > maxview * maxview) | 4960 | if (dpos > maxview * maxview) |
4426 | continue; | 4961 | continue; |
4427 | 4962 | ||
4428 | GroupsNeedFullUpdate.Add(grp); | 4963 | if (!viewerCache || !updateFlags.HasFlag(PrimUpdateFlags.UpdateProbe)) |
4429 | continue; | 4964 | { |
4965 | GroupsNeedFullUpdate.Add(grp); | ||
4966 | continue; | ||
4967 | } | ||
4430 | } | 4968 | } |
4431 | } | 4969 | } |
4970 | |||
4971 | if (updateFlags.HasFlag(PrimUpdateFlags.UpdateProbe)) | ||
4972 | { | ||
4973 | if (objectUpdateProbes == null) | ||
4974 | { | ||
4975 | objectUpdateProbes = new List<EntityUpdate>(); | ||
4976 | maxUpdatesBytes -= 18; | ||
4977 | } | ||
4978 | objectUpdateProbes.Add(update); | ||
4979 | maxUpdatesBytes -= 12; | ||
4980 | continue; | ||
4981 | } | ||
4982 | |||
4983 | if (updateFlags == PrimUpdateFlags.Animations) | ||
4984 | { | ||
4985 | if (m_SupportObjectAnimations && part.Animations != null) | ||
4986 | { | ||
4987 | if (ObjectAnimationUpdates == null) | ||
4988 | ObjectAnimationUpdates = new List<SceneObjectPart>(); | ||
4989 | ObjectAnimationUpdates.Add(part); | ||
4990 | maxUpdatesBytes -= 20 * part.Animations.Count + 24; | ||
4991 | } | ||
4992 | continue; | ||
4993 | } | ||
4994 | |||
4995 | if(viewerCache) | ||
4996 | useCompressUpdate = grp.IsViewerCachable; | ||
4997 | |||
4998 | istree = (part.Shape.PCode == (byte)PCode.Grass || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Tree); | ||
4432 | } | 4999 | } |
4433 | else if (update.Entity is ScenePresence) | 5000 | else if (update.Entity is ScenePresence) |
4434 | { | 5001 | { |
@@ -4448,42 +5015,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4448 | 5015 | ||
4449 | #region UpdateFlags to packet type conversion | 5016 | #region UpdateFlags to packet type conversion |
4450 | 5017 | ||
4451 | // bool canUseCompressed = true; | ||
4452 | |||
4453 | if (update.Entity is SceneObjectPart) | ||
4454 | { | ||
4455 | if (m_SupportObjectAnimations && updateFlags.HasFlag(PrimUpdateFlags.Animations)) | ||
4456 | { | ||
4457 | SceneObjectPart sop = (SceneObjectPart)update.Entity; | ||
4458 | if ( sop.Animations != null) | ||
4459 | { | ||
4460 | if(ObjectAnimationUpdates == null) | ||
4461 | ObjectAnimationUpdates = new List<SceneObjectPart>(); | ||
4462 | ObjectAnimationUpdates.Add(sop); | ||
4463 | maxUpdatesBytes -= 20 * sop.Animations.Count + 24; | ||
4464 | } | ||
4465 | } | ||
4466 | } | ||
4467 | else | ||
4468 | { | ||
4469 | // canUseCompressed = false; | ||
4470 | } | ||
4471 | |||
4472 | updateFlags &= PrimUpdateFlags.FullUpdate; // clear other control bits already handled | 5018 | updateFlags &= PrimUpdateFlags.FullUpdate; // clear other control bits already handled |
4473 | if(updateFlags == PrimUpdateFlags.None) | 5019 | if(updateFlags == PrimUpdateFlags.None) |
4474 | continue; | 5020 | continue; |
4475 | 5021 | ||
4476 | /* | ||
4477 | const PrimUpdateFlags canNotUseCompressedMask = | ||
4478 | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | | ||
4479 | PrimUpdateFlags.CollisionPlane | PrimUpdateFlags.Joint; | ||
4480 | |||
4481 | if ((updateFlags & canNotUseCompressedMask) != 0) | ||
4482 | { | ||
4483 | canUseCompressed = false; | ||
4484 | } | ||
4485 | */ | ||
4486 | |||
4487 | const PrimUpdateFlags canNotUseImprovedMask = ~( | 5022 | const PrimUpdateFlags canNotUseImprovedMask = ~( |
4488 | PrimUpdateFlags.AttachmentPoint | | 5023 | PrimUpdateFlags.AttachmentPoint | |
4489 | PrimUpdateFlags.Position | | 5024 | PrimUpdateFlags.Position | |
@@ -4499,19 +5034,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4499 | 5034 | ||
4500 | #region Block Construction | 5035 | #region Block Construction |
4501 | 5036 | ||
4502 | // TODO: Remove this once we can build compressed updates | ||
4503 | /* | ||
4504 | if (canUseCompressed) | ||
4505 | { | ||
4506 | ObjectUpdateCompressedPacket.ObjectDataBlock ablock = | ||
4507 | CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags); | ||
4508 | compressedUpdateBlocks.Add(ablock); | ||
4509 | compressedUpdates.Value.Add(update); | ||
4510 | maxUpdatesBytes -= ablock.Length; | ||
4511 | } | ||
4512 | else if (canUseImproved) | ||
4513 | */ | ||
4514 | |||
4515 | if ((updateFlags & canNotUseImprovedMask) == 0) | 5037 | if ((updateFlags & canNotUseImprovedMask) == 0) |
4516 | { | 5038 | { |
4517 | if (terseUpdates == null) | 5039 | if (terseUpdates == null) |
@@ -4534,16 +5056,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4534 | else | 5056 | else |
4535 | { | 5057 | { |
4536 | if (update.Entity is ScenePresence) | 5058 | if (update.Entity is ScenePresence) |
5059 | { | ||
4537 | maxUpdatesBytes -= 150; // crude estimation | 5060 | maxUpdatesBytes -= 150; // crude estimation |
4538 | else | ||
4539 | maxUpdatesBytes -= 300; | ||
4540 | 5061 | ||
4541 | if(objectUpdates == null) | 5062 | if (objectUpdates == null) |
5063 | { | ||
5064 | objectUpdates = new List<EntityUpdate>(); | ||
5065 | maxUpdatesBytes -= 18; | ||
5066 | } | ||
5067 | objectUpdates.Add(update); | ||
5068 | } | ||
5069 | else | ||
4542 | { | 5070 | { |
4543 | objectUpdates = new List<EntityUpdate>(); | 5071 | if (useCompressUpdate) |
4544 | maxUpdatesBytes -= 18; | 5072 | { |
5073 | if (istree) | ||
5074 | maxUpdatesBytes -= 64; | ||
5075 | else | ||
5076 | maxUpdatesBytes -= 120; // crude estimation | ||
5077 | |||
5078 | if (compressedUpdates == null) | ||
5079 | { | ||
5080 | compressedUpdates = new List<EntityUpdate>(); | ||
5081 | maxUpdatesBytes -= 18; | ||
5082 | } | ||
5083 | compressedUpdates.Add(update); | ||
5084 | } | ||
5085 | else | ||
5086 | { | ||
5087 | if (istree) | ||
5088 | maxUpdatesBytes -= 70; | ||
5089 | else | ||
5090 | maxUpdatesBytes -= 150; // crude estimation | ||
5091 | |||
5092 | if (objectUpdates == null) | ||
5093 | { | ||
5094 | objectUpdates = new List<EntityUpdate>(); | ||
5095 | maxUpdatesBytes -= 18; | ||
5096 | } | ||
5097 | objectUpdates.Add(update); | ||
5098 | } | ||
4545 | } | 5099 | } |
4546 | objectUpdates.Add(update); | ||
4547 | } | 5100 | } |
4548 | 5101 | ||
4549 | #endregion Block Construction | 5102 | #endregion Block Construction |
@@ -4560,7 +5113,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4560 | 5113 | ||
4561 | if(objectUpdates != null) | 5114 | if(objectUpdates != null) |
4562 | { | 5115 | { |
4563 | int blocks = objectUpdates.Count; | ||
4564 | List<EntityUpdate> tau = new List<EntityUpdate>(30); | 5116 | List<EntityUpdate> tau = new List<EntityUpdate>(30); |
4565 | 5117 | ||
4566 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | 5118 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
@@ -4570,7 +5122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4570 | zc.Position = 7; | 5122 | zc.Position = 7; |
4571 | 5123 | ||
4572 | zc.AddUInt64(m_scene.RegionInfo.RegionHandle); | 5124 | zc.AddUInt64(m_scene.RegionInfo.RegionHandle); |
4573 | zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f)); | 5125 | zc.AddUInt16(timeDilation); |
4574 | 5126 | ||
4575 | zc.AddByte(1); // tmp block count | 5127 | zc.AddByte(1); // tmp block count |
4576 | 5128 | ||
@@ -4587,14 +5139,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4587 | if (eu.Entity is ScenePresence) | 5139 | if (eu.Entity is ScenePresence) |
4588 | CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc); | 5140 | CreateAvatarUpdateBlock((ScenePresence)eu.Entity, zc); |
4589 | else | 5141 | else |
4590 | CreatePrimUpdateBlock((SceneObjectPart)eu.Entity, mysp, zc); | 5142 | { |
4591 | if (zc.Position < LLUDPServer.MAXPAYLOAD) | 5143 | SceneObjectPart part = (SceneObjectPart)eu.Entity; |
5144 | if (eu.Flags.HasFlag(PrimUpdateFlags.Animations)) | ||
5145 | { | ||
5146 | if (m_SupportObjectAnimations && part.Animations != null) | ||
5147 | { | ||
5148 | if (ObjectAnimationUpdates == null) | ||
5149 | ObjectAnimationUpdates = new List<SceneObjectPart>(); | ||
5150 | ObjectAnimationUpdates.Add(part); | ||
5151 | } | ||
5152 | eu.Flags &= ~PrimUpdateFlags.Animations; | ||
5153 | } | ||
5154 | CreatePrimUpdateBlock(part, mysp, zc); | ||
5155 | } | ||
5156 | if (zc.Position < LLUDPServer.MAXPAYLOAD - 300) | ||
4592 | { | 5157 | { |
4593 | tau.Add(eu); | 5158 | tau.Add(eu); |
4594 | ++count; | 5159 | ++count; |
4595 | --blocks; | ||
4596 | } | 5160 | } |
4597 | else if (blocks > 0) | 5161 | else |
4598 | { | 5162 | { |
4599 | // we need more packets | 5163 | // we need more packets |
4600 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | 5164 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
@@ -4610,7 +5174,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4610 | buf.DataLength = lastpos; | 5174 | buf.DataLength = lastpos; |
4611 | 5175 | ||
4612 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | 5176 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, |
4613 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | 5177 | //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); |
5178 | null, false, false); | ||
4614 | 5179 | ||
4615 | buf = newbuf; | 5180 | buf = newbuf; |
4616 | zc.Data = buf.Data; | 5181 | zc.Data = buf.Data; |
@@ -4625,7 +5190,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4625 | tau = new List<EntityUpdate>(30); | 5190 | tau = new List<EntityUpdate>(30); |
4626 | tau.Add(eu); | 5191 | tau.Add(eu); |
4627 | count = 1; | 5192 | count = 1; |
4628 | --blocks; | ||
4629 | } | 5193 | } |
4630 | } | 5194 | } |
4631 | 5195 | ||
@@ -4634,22 +5198,232 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4634 | buf.Data[countposition] = (byte)count; | 5198 | buf.Data[countposition] = (byte)count; |
4635 | buf.DataLength = zc.Finish(); | 5199 | buf.DataLength = zc.Finish(); |
4636 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | 5200 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, |
5201 | //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | ||
5202 | null, false, false); | ||
5203 | } | ||
5204 | } | ||
5205 | |||
5206 | /* no zero encode compressed updates | ||
5207 | if(compressedUpdates != null) | ||
5208 | { | ||
5209 | List<EntityUpdate> tau = new List<EntityUpdate>(30); | ||
5210 | |||
5211 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
5212 | byte[] data = buf.Data; | ||
5213 | |||
5214 | Buffer.BlockCopy(CompressedObjectHeader, 0, data , 0, 7); | ||
5215 | |||
5216 | Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, data, 7); // 15 | ||
5217 | Utils.UInt16ToBytes(timeDilation, data, 15); // 17 | ||
5218 | |||
5219 | int countposition = 17; // blocks count position | ||
5220 | int pos = 18; | ||
5221 | |||
5222 | int lastpos = 0; | ||
5223 | |||
5224 | int count = 0; | ||
5225 | foreach (EntityUpdate eu in compressedUpdates) | ||
5226 | { | ||
5227 | SceneObjectPart sop = (SceneObjectPart)eu.Entity; | ||
5228 | if (sop.ParentGroup == null || sop.ParentGroup.IsDeleted) | ||
5229 | continue; | ||
5230 | lastpos = pos; | ||
5231 | CreateCompressedUpdateBlock(sop, mysp, data, ref pos); | ||
5232 | if (pos < LLUDPServer.MAXPAYLOAD) | ||
5233 | { | ||
5234 | tau.Add(eu); | ||
5235 | ++count; | ||
5236 | } | ||
5237 | else | ||
5238 | { | ||
5239 | // we need more packets | ||
5240 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
5241 | Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same | ||
5242 | |||
5243 | buf.Data[countposition] = (byte)count; | ||
5244 | |||
5245 | buf.DataLength = lastpos; | ||
5246 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | ||
5247 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | ||
5248 | |||
5249 | buf = newbuf; | ||
5250 | data = buf.Data; | ||
5251 | |||
5252 | pos = 18; | ||
5253 | // im lazy now, just do last again | ||
5254 | CreateCompressedUpdateBlock(sop, mysp, data, ref pos); | ||
5255 | tau = new List<EntityUpdate>(30); | ||
5256 | tau.Add(eu); | ||
5257 | count = 1; | ||
5258 | } | ||
5259 | } | ||
5260 | |||
5261 | if (count > 0) | ||
5262 | { | ||
5263 | buf.Data[countposition] = (byte)count; | ||
5264 | buf.DataLength = pos; | ||
5265 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | ||
4637 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | 5266 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); |
4638 | } | 5267 | } |
4639 | } | 5268 | } |
5269 | */ | ||
4640 | 5270 | ||
4641 | /* | 5271 | if (compressedUpdates != null) |
4642 | if (compressedUpdateBlocks != null) | ||
4643 | { | 5272 | { |
4644 | ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); | 5273 | List<EntityUpdate> tau = new List<EntityUpdate>(30); |
4645 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 5274 | |
4646 | packet.RegionData.TimeDilation = timeDilation; | 5275 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
4647 | packet.ObjectData = compressedUpdateBlocks.ToArray(); | 5276 | byte[] data = buf.Data; |
4648 | compressedUpdateBlocks.Clear(); | 5277 | |
5278 | Buffer.BlockCopy(CompressedObjectHeader, 0, data, 0, 7); | ||
5279 | data[0] |= Helpers.MSG_ZEROCODED; | ||
5280 | |||
5281 | LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); | ||
5282 | zc.Position = 7; | ||
4649 | 5283 | ||
4650 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); }); | 5284 | zc.AddUInt64(m_scene.RegionInfo.RegionHandle); |
5285 | zc.AddUInt16(timeDilation); | ||
5286 | |||
5287 | zc.AddByte(1); // tmp block count | ||
5288 | |||
5289 | int countposition = zc.Position - 1; | ||
5290 | |||
5291 | int lastpos = 0; | ||
5292 | int lastzc = 0; | ||
5293 | |||
5294 | int count = 0; | ||
5295 | foreach (EntityUpdate eu in compressedUpdates) | ||
5296 | { | ||
5297 | SceneObjectPart sop = (SceneObjectPart)eu.Entity; | ||
5298 | if (sop.ParentGroup == null || sop.ParentGroup.IsDeleted) | ||
5299 | continue; | ||
5300 | |||
5301 | if (eu.Flags.HasFlag(PrimUpdateFlags.Animations)) | ||
5302 | { | ||
5303 | if (m_SupportObjectAnimations && sop.Animations != null) | ||
5304 | { | ||
5305 | if (ObjectAnimationUpdates == null) | ||
5306 | ObjectAnimationUpdates = new List<SceneObjectPart>(); | ||
5307 | ObjectAnimationUpdates.Add(sop); | ||
5308 | } | ||
5309 | eu.Flags &= ~PrimUpdateFlags.Animations; | ||
5310 | } | ||
5311 | |||
5312 | lastpos = zc.Position; | ||
5313 | lastzc = zc.ZeroCount; | ||
5314 | |||
5315 | CreateCompressedUpdateBlockZC(sop, mysp, zc); | ||
5316 | if (zc.Position < LLUDPServer.MAXPAYLOAD - 200) | ||
5317 | { | ||
5318 | //tau.Add(eu); | ||
5319 | ++count; | ||
5320 | } | ||
5321 | else | ||
5322 | { | ||
5323 | // we need more packets | ||
5324 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
5325 | Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same | ||
5326 | |||
5327 | buf.Data[countposition] = (byte)count; | ||
5328 | // get pending zeros at cut point | ||
5329 | if (lastzc > 0) | ||
5330 | { | ||
5331 | buf.Data[lastpos++] = 0; | ||
5332 | buf.Data[lastpos++] = (byte)lastzc; | ||
5333 | } | ||
5334 | buf.DataLength = lastpos; | ||
5335 | |||
5336 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | ||
5337 | //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | ||
5338 | null, false, false); | ||
5339 | |||
5340 | buf = newbuf; | ||
5341 | zc.Data = buf.Data; | ||
5342 | |||
5343 | data[0] |= Helpers.MSG_ZEROCODED; | ||
5344 | |||
5345 | zc.ZeroCount = 0; | ||
5346 | zc.Position = countposition + 1; | ||
5347 | |||
5348 | // im lazy now, just do last again | ||
5349 | CreateCompressedUpdateBlockZC(sop, mysp, zc); | ||
5350 | tau = new List<EntityUpdate>(30); | ||
5351 | //tau.Add(eu); | ||
5352 | count = 1; | ||
5353 | } | ||
5354 | } | ||
5355 | |||
5356 | if (count > 0) | ||
5357 | { | ||
5358 | buf.Data[countposition] = (byte)count; | ||
5359 | buf.DataLength = zc.Finish(); | ||
5360 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | ||
5361 | //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | ||
5362 | null, false, false); | ||
5363 | } | ||
4651 | } | 5364 | } |
4652 | */ | 5365 | |
5366 | if (objectUpdateProbes != null) | ||
5367 | { | ||
5368 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
5369 | byte[] data = buf.Data; | ||
5370 | |||
5371 | Buffer.BlockCopy(ObjectUpdateCachedHeader, 0, data, 0, 7); | ||
5372 | |||
5373 | Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, data, 7); // 15 | ||
5374 | Utils.UInt16ToBytes(timeDilation, data, 15); // 17 | ||
5375 | |||
5376 | int countposition = 17; // blocks count position | ||
5377 | int pos = 18; | ||
5378 | |||
5379 | int count = 0; | ||
5380 | foreach (EntityUpdate eu in objectUpdateProbes) | ||
5381 | { | ||
5382 | SceneObjectPart sop = (SceneObjectPart)eu.Entity; | ||
5383 | if (sop.ParentGroup == null || sop.ParentGroup.IsDeleted) | ||
5384 | continue; | ||
5385 | uint primflags = m_scene.Permissions.GenerateClientFlags(sop, mysp); | ||
5386 | if (mysp.UUID != sop.OwnerID) | ||
5387 | primflags &= ~(uint)PrimFlags.CreateSelected; | ||
5388 | else | ||
5389 | { | ||
5390 | if (sop.CreateSelected) | ||
5391 | primflags |= (uint)PrimFlags.CreateSelected; | ||
5392 | else | ||
5393 | primflags &= ~(uint)PrimFlags.CreateSelected; | ||
5394 | } | ||
5395 | |||
5396 | Utils.UIntToBytes(sop.LocalId, data, pos); pos += 4; | ||
5397 | Utils.UIntToBytes((uint)sop.ParentGroup.PseudoCRC, data, pos); pos += 4; //WRONG | ||
5398 | Utils.UIntToBytes(primflags, data, pos); pos += 4; | ||
5399 | |||
5400 | if (pos < (LLUDPServer.MAXPAYLOAD - 12)) | ||
5401 | ++count; | ||
5402 | else | ||
5403 | { | ||
5404 | // we need more packets | ||
5405 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
5406 | Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same | ||
5407 | |||
5408 | buf.Data[countposition] = (byte)count; | ||
5409 | buf.DataLength = pos; | ||
5410 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false); | ||
5411 | |||
5412 | buf = newbuf; | ||
5413 | data = buf.Data; | ||
5414 | pos = 18; | ||
5415 | count = 0; | ||
5416 | } | ||
5417 | } | ||
5418 | |||
5419 | if (count > 0) | ||
5420 | { | ||
5421 | buf.Data[countposition] = (byte)count; | ||
5422 | buf.DataLength = pos; | ||
5423 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false); | ||
5424 | } | ||
5425 | } | ||
5426 | |||
4653 | if (terseUpdates != null) | 5427 | if (terseUpdates != null) |
4654 | { | 5428 | { |
4655 | int blocks = terseUpdates.Count; | 5429 | int blocks = terseUpdates.Count; |
@@ -4691,7 +5465,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4691 | buf.DataLength = lastpos; | 5465 | buf.DataLength = lastpos; |
4692 | // zero encode is not as spec | 5466 | // zero encode is not as spec |
4693 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | 5467 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, |
4694 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true); | 5468 | //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true); |
5469 | null, false, true); | ||
4695 | 5470 | ||
4696 | tau = new List<EntityUpdate>(30); | 5471 | tau = new List<EntityUpdate>(30); |
4697 | tau.Add(eu); | 5472 | tau.Add(eu); |
@@ -4706,7 +5481,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4706 | buf.Data[17] = (byte)count; | 5481 | buf.Data[17] = (byte)count; |
4707 | buf.DataLength = pos; | 5482 | buf.DataLength = pos; |
4708 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | 5483 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, |
4709 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true); | 5484 | //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true); |
5485 | null, false, true); | ||
4710 | } | 5486 | } |
4711 | } | 5487 | } |
4712 | 5488 | ||
@@ -4716,6 +5492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4716 | { | 5492 | { |
4717 | if (sop.Animations == null) | 5493 | if (sop.Animations == null) |
4718 | continue; | 5494 | continue; |
5495 | |||
4719 | SceneObjectGroup sog = sop.ParentGroup; | 5496 | SceneObjectGroup sog = sop.ParentGroup; |
4720 | if (sog == null || sog.IsDeleted) | 5497 | if (sog == null || sog.IsDeleted) |
4721 | continue; | 5498 | continue; |
@@ -4728,18 +5505,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4728 | int[] seqs = null; | 5505 | int[] seqs = null; |
4729 | int count = sop.GetAnimations(out ids, out seqs); | 5506 | int count = sop.GetAnimations(out ids, out seqs); |
4730 | 5507 | ||
4731 | ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation); | 5508 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
4732 | ani.Sender = new ObjectAnimationPacket.SenderBlock(); | 5509 | byte[] data = buf.Data; |
4733 | ani.Sender.ID = sop.UUID; | 5510 | |
4734 | ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[count]; | 5511 | //setup header |
5512 | Buffer.BlockCopy(ObjectAnimationHeader, 0, data , 0, 7); | ||
4735 | 5513 | ||
4736 | for(int i = 0; i< count; i++) | 5514 | // sender block |
5515 | sop.UUID.ToBytes(data, 7); // 23 | ||
5516 | |||
5517 | //animations block | ||
5518 | if (count > 255) | ||
5519 | count = 255; | ||
5520 | |||
5521 | data[23] = (byte)count; | ||
5522 | |||
5523 | int pos = 24; | ||
5524 | for(int i = 0; i < count; i++) | ||
4737 | { | 5525 | { |
4738 | ani.AnimationList[i] = new ObjectAnimationPacket.AnimationListBlock(); | 5526 | ids[i].ToBytes(data, pos); pos += 16; |
4739 | ani.AnimationList[i].AnimID = ids[i]; | 5527 | Utils.IntToBytesSafepos(seqs[i], data, pos); pos += 4; |
4740 | ani.AnimationList[i].AnimSequenceID = seqs[i]; | ||
4741 | } | 5528 | } |
4742 | OutPacket(ani, ThrottleOutPacketType.Task, true); | 5529 | |
5530 | buf.DataLength = pos; | ||
5531 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
4743 | } | 5532 | } |
4744 | } | 5533 | } |
4745 | 5534 | ||
@@ -4758,8 +5547,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4758 | { | 5547 | { |
4759 | lock (GroupsInView) | 5548 | lock (GroupsInView) |
4760 | GroupsInView.Add(grp); | 5549 | GroupsInView.Add(grp); |
5550 | PrimUpdateFlags flags = PrimUpdateFlags.CancelKill; | ||
5551 | if(viewerCache && grp.IsViewerCachable) | ||
5552 | flags |= PrimUpdateFlags.UpdateProbe; | ||
4761 | foreach (SceneObjectPart p in grp.Parts) | 5553 | foreach (SceneObjectPart p in grp.Parts) |
4762 | SendEntityUpdate(p, PrimUpdateFlags.CancelKill); | 5554 | SendEntityUpdate(p, flags); |
4763 | } | 5555 | } |
4764 | } | 5556 | } |
4765 | 5557 | ||
@@ -4838,27 +5630,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4838 | if (e != null && e is SceneObjectGroup) | 5630 | if (e != null && e is SceneObjectGroup) |
4839 | { | 5631 | { |
4840 | SceneObjectGroup grp = (SceneObjectGroup)e; | 5632 | SceneObjectGroup grp = (SceneObjectGroup)e; |
4841 | if(grp.IsDeleted || grp.IsAttachment) | 5633 | if(grp.IsDeleted || grp.IsAttachment ) |
4842 | continue; | 5634 | continue; |
4843 | 5635 | ||
4844 | bool inviewgroups; | 5636 | bool inviewgroups; |
4845 | lock (GroupsInView) | 5637 | lock (GroupsInView) |
4846 | inviewgroups = GroupsInView.Contains(grp); | 5638 | inviewgroups = GroupsInView.Contains(grp); |
4847 | 5639 | ||
4848 | Vector3 grppos = grp.getCenterOffset(); | 5640 | //temp handling of sits |
4849 | float dpos = (grppos - mypos).LengthSquared(); | 5641 | if(grp.GetSittingAvatarsCount() > 0) |
4850 | |||
4851 | float maxview = grp.GetBoundsRadius() + cullingrange; | ||
4852 | if (dpos > maxview * maxview) | ||
4853 | { | 5642 | { |
4854 | if(inviewgroups) | 5643 | if (!inviewgroups) |
4855 | kills.Add(grp); | 5644 | GroupsNeedFullUpdate.Add(grp); |
5645 | NewGroupsInView.Add(grp); | ||
4856 | } | 5646 | } |
4857 | else | 5647 | else |
4858 | { | 5648 | { |
4859 | if(!inviewgroups) | 5649 | Vector3 grppos = grp.getCenterOffset(); |
4860 | GroupsNeedFullUpdate.Add(grp); | 5650 | float dpos = (grppos - mypos).LengthSquared(); |
4861 | NewGroupsInView.Add(grp); | 5651 | |
5652 | float maxview = grp.GetBoundsRadius() + cullingrange; | ||
5653 | if (dpos > maxview * maxview) | ||
5654 | { | ||
5655 | if(inviewgroups) | ||
5656 | kills.Add(grp); | ||
5657 | } | ||
5658 | else | ||
5659 | { | ||
5660 | if (!inviewgroups) | ||
5661 | GroupsNeedFullUpdate.Add(grp); | ||
5662 | NewGroupsInView.Add(grp); | ||
5663 | } | ||
4862 | } | 5664 | } |
4863 | } | 5665 | } |
4864 | } | 5666 | } |
@@ -4890,13 +5692,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4890 | 5692 | ||
4891 | if(GroupsNeedFullUpdate.Count > 0) | 5693 | if(GroupsNeedFullUpdate.Count > 0) |
4892 | { | 5694 | { |
4893 | foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) | 5695 | bool sendProbes = m_supportViewerCache && (m_viewerHandShakeFlags & 2) == 0; |
5696 | |||
5697 | if(sendProbes) | ||
4894 | { | 5698 | { |
4895 | foreach(SceneObjectPart p in grp.Parts) | 5699 | foreach (SceneObjectGroup grp in GroupsNeedFullUpdate) |
4896 | SendEntityUpdate(p, PrimUpdateFlags.CancelKill); | 5700 | { |
5701 | PrimUpdateFlags flags = PrimUpdateFlags.CancelKill; | ||
5702 | if (grp.IsViewerCachable) | ||
5703 | flags |= PrimUpdateFlags.UpdateProbe; | ||
5704 | foreach (SceneObjectPart p in grp.Parts) | ||
5705 | SendEntityUpdate(p, flags); | ||
5706 | } | ||
5707 | } | ||
5708 | else | ||
5709 | { | ||
5710 | m_viewerHandShakeFlags &= ~2U; // nexttime send probes | ||
5711 | PrimUpdateFlags flags = PrimUpdateFlags.CancelKill; | ||
5712 | foreach (SceneObjectGroup grp in GroupsNeedFullUpdate) | ||
5713 | { | ||
5714 | foreach (SceneObjectPart p in grp.Parts) | ||
5715 | SendEntityUpdate(p, flags); | ||
5716 | } | ||
4897 | } | 5717 | } |
4898 | } | 5718 | } |
4899 | |||
4900 | CheckGroupsInViewBusy = false; | 5719 | CheckGroupsInViewBusy = false; |
4901 | } | 5720 | } |
4902 | 5721 | ||
@@ -5044,20 +5863,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5044 | OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); | 5863 | OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); |
5045 | } | 5864 | } |
5046 | 5865 | ||
5866 | static private readonly byte[] SimStatsHeader = new byte[] { | ||
5867 | 0, | ||
5868 | 0, 0, 0, 0, // sequence number | ||
5869 | 0, // extra | ||
5870 | 0xff, 0xff, 0, 140 // ID 140 (low frequency bigendian) | ||
5871 | }; | ||
5872 | |||
5047 | public void SendSimStats(SimStats stats) | 5873 | public void SendSimStats(SimStats stats) |
5048 | { | 5874 | { |
5049 | SimStatsPacket pack = new SimStatsPacket(); | 5875 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
5050 | pack.Region = new SimStatsPacket.RegionBlock(); | 5876 | byte[] data = buf.Data; |
5051 | pack.Region.RegionX = stats.RegionX; | 5877 | |
5052 | pack.Region.RegionY = stats.RegionY; | 5878 | //setup header |
5053 | pack.Region.RegionFlags = stats.RegionFlags; | 5879 | Buffer.BlockCopy(SimStatsHeader, 0, data, 0, 10); |
5054 | pack.Region.ObjectCapacity = stats.ObjectCapacity; | 5880 | |
5055 | //pack.Region = //stats.RegionBlock; | 5881 | // Region Block |
5056 | pack.Stat = stats.StatsBlock; | 5882 | Utils.UIntToBytesSafepos(stats.RegionX, data, 10); |
5057 | 5883 | Utils.UIntToBytesSafepos(stats.RegionY, data, 14); | |
5058 | pack.Header.Reliable = false; | 5884 | Utils.UIntToBytesSafepos(stats.RegionFlags, data, 18); |
5059 | pack.RegionInfo = new SimStatsPacket.RegionInfoBlock[0]; | 5885 | Utils.UIntToBytesSafepos(stats.ObjectCapacity, data, 22); // 26 |
5060 | OutPacket(pack, ThrottleOutPacketType.Task); | 5886 | |
5887 | // stats | ||
5888 | data[26] = (byte)stats.StatsBlock.Length; | ||
5889 | int pos = 27; | ||
5890 | |||
5891 | stats.StatsBlock[15].StatValue /= 1024; // unack is in KB | ||
5892 | for (int i = 0; i< stats.StatsBlock.Length; ++i) | ||
5893 | { | ||
5894 | Utils.UIntToBytesSafepos(stats.StatsBlock[i].StatID, data, pos); pos += 4; | ||
5895 | Utils.FloatToBytesSafepos(stats.StatsBlock[i].StatValue, data, pos); pos += 4; | ||
5896 | } | ||
5897 | |||
5898 | //no PID | ||
5899 | Utils.IntToBytesSafepos(0, data, pos); pos += 4; | ||
5900 | |||
5901 | // no regioninfo (extended flags) | ||
5902 | data[pos++] = 0; // = 1; | ||
5903 | //Utils.UInt64ToBytesSafepos(RegionFlagsExtended, data, pos); pos += 8; | ||
5904 | |||
5905 | buf.DataLength = pos; | ||
5906 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
5061 | } | 5907 | } |
5062 | 5908 | ||
5063 | private class ObjectPropertyUpdate : EntityUpdate | 5909 | private class ObjectPropertyUpdate : EntityUpdate |
@@ -5121,14 +5967,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5121 | m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true)); | 5967 | m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true)); |
5122 | } | 5968 | } |
5123 | 5969 | ||
5970 | static private readonly byte[] ObjectPropertyUpdateHeader = new byte[] { | ||
5971 | Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, | ||
5972 | 0, 0, 0, 0, // sequence number | ||
5973 | 0, // extra | ||
5974 | 0xff, 9 // ID (medium frequency) | ||
5975 | }; | ||
5976 | |||
5977 | static private readonly byte[] ObjectFamilyUpdateHeader = new byte[] { | ||
5978 | Helpers.MSG_RELIABLE | Helpers.MSG_ZEROCODED, | ||
5979 | 0, 0, 0, 0, // sequence number | ||
5980 | 0, // extra | ||
5981 | 0xff, 10 // ID (medium frequency) | ||
5982 | }; | ||
5983 | |||
5124 | private void ProcessEntityPropertyRequests(int maxUpdateBytes) | 5984 | private void ProcessEntityPropertyRequests(int maxUpdateBytes) |
5125 | { | 5985 | { |
5126 | List<ObjectPropertiesFamilyPacket.ObjectDataBlock> objectFamilyBlocks = null; | 5986 | List<ObjectPropertyUpdate> objectPropertiesUpdates = null; |
5127 | List<ObjectPropertiesPacket.ObjectDataBlock> objectPropertiesBlocks = null; | 5987 | List<ObjectPropertyUpdate> objectPropertiesFamilyUpdates = null; |
5128 | List<SceneObjectPart> needPhysics = null; | 5988 | List<SceneObjectPart> needPhysics = null; |
5129 | 5989 | ||
5130 | bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; | 5990 | // bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; |
5131 | 5991 | bool orderedDequeue = false; // for now | |
5132 | EntityUpdate iupdate; | 5992 | EntityUpdate iupdate; |
5133 | 5993 | ||
5134 | while (maxUpdateBytes > 0) | 5994 | while (maxUpdateBytes > 0) |
@@ -5153,11 +6013,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5153 | if (update.Entity is SceneObjectPart) | 6013 | if (update.Entity is SceneObjectPart) |
5154 | { | 6014 | { |
5155 | SceneObjectPart sop = (SceneObjectPart)update.Entity; | 6015 | SceneObjectPart sop = (SceneObjectPart)update.Entity; |
5156 | ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); | 6016 | if(objectPropertiesFamilyUpdates == null) |
5157 | if(objectFamilyBlocks == null) | 6017 | objectPropertiesFamilyUpdates = new List<ObjectPropertyUpdate>(); |
5158 | objectFamilyBlocks = new List<ObjectPropertiesFamilyPacket.ObjectDataBlock>(); | 6018 | objectPropertiesFamilyUpdates.Add(update); |
5159 | objectFamilyBlocks.Add(objPropDB); | 6019 | maxUpdateBytes -= 100; |
5160 | maxUpdateBytes -= objPropDB.Length; | ||
5161 | } | 6020 | } |
5162 | } | 6021 | } |
5163 | 6022 | ||
@@ -5169,58 +6028,107 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5169 | if(needPhysics == null) | 6028 | if(needPhysics == null) |
5170 | needPhysics = new List<SceneObjectPart>(); | 6029 | needPhysics = new List<SceneObjectPart>(); |
5171 | needPhysics.Add(sop); | 6030 | needPhysics.Add(sop); |
5172 | ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); | 6031 | if(objectPropertiesUpdates == null) |
5173 | if(objectPropertiesBlocks == null) | 6032 | objectPropertiesUpdates = new List<ObjectPropertyUpdate>(); |
5174 | objectPropertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>(); | 6033 | objectPropertiesUpdates.Add(update); |
5175 | objectPropertiesBlocks.Add(objPropDB); | 6034 | maxUpdateBytes -= 200; // aprox |
5176 | maxUpdateBytes -= objPropDB.Length; | ||
5177 | } | 6035 | } |
5178 | } | 6036 | } |
5179 | } | 6037 | } |
5180 | 6038 | ||
5181 | if (objectPropertiesBlocks != null) | 6039 | if (objectPropertiesUpdates != null) |
5182 | { | 6040 | { |
5183 | ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | 6041 | int blocks = objectPropertiesUpdates.Count; |
5184 | packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[objectPropertiesBlocks.Count]; | 6042 | //List<EntityUpdate> tau = new List<EntityUpdate>(30); |
5185 | for (int i = 0; i < objectPropertiesBlocks.Count; i++) | ||
5186 | packet.ObjectData[i] = objectPropertiesBlocks[i]; | ||
5187 | 6043 | ||
5188 | // Pass in the delegate so that if this packet needs to be resent, we send the current properties | 6044 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
5189 | // of the object rather than the properties when the packet was created | 6045 | Buffer.BlockCopy(ObjectPropertyUpdateHeader, 0, buf.Data, 0, 8); |
5190 | // HACK : Remove intelligent resending until it's fixed in core | 6046 | |
5191 | //OutPacket(packet, ThrottleOutPacketType.Task, true, | 6047 | LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); |
5192 | // delegate(OutgoingPacket oPacket) | 6048 | zc.Position = 8; |
5193 | // { | 6049 | |
5194 | // ResendPropertyUpdates(propertyUpdates.Value, oPacket); | 6050 | zc.AddByte(1); // tmp block count |
5195 | // }); | 6051 | |
5196 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 6052 | int countposition = zc.Position - 1; |
6053 | |||
6054 | int lastpos = 0; | ||
6055 | int lastzc = 0; | ||
6056 | |||
6057 | int count = 0; | ||
6058 | foreach (EntityUpdate eu in objectPropertiesUpdates) | ||
6059 | { | ||
6060 | lastpos = zc.Position; | ||
6061 | lastzc = zc.ZeroCount; | ||
6062 | CreateObjectPropertiesBlock((SceneObjectPart)eu.Entity, zc); | ||
6063 | if (zc.Position < LLUDPServer.MAXPAYLOAD) | ||
6064 | { | ||
6065 | //tau.Add(eu); | ||
6066 | ++count; | ||
6067 | --blocks; | ||
6068 | } | ||
6069 | else if (blocks > 0) | ||
6070 | { | ||
6071 | // we need more packets | ||
6072 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
6073 | Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same | ||
6074 | |||
6075 | buf.Data[countposition] = (byte)count; | ||
6076 | // get pending zeros at cut point | ||
6077 | if (lastzc > 0) | ||
6078 | { | ||
6079 | buf.Data[lastpos++] = 0; | ||
6080 | buf.Data[lastpos++] = (byte)lastzc; | ||
6081 | } | ||
6082 | buf.DataLength = lastpos; | ||
6083 | |||
6084 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | ||
6085 | // delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | ||
6086 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
6087 | buf = newbuf; | ||
6088 | zc.Data = buf.Data; | ||
6089 | zc.ZeroCount = 0; | ||
6090 | zc.Position = countposition + 1; | ||
6091 | // im lazy now, just do last again | ||
6092 | CreateObjectPropertiesBlock((SceneObjectPart)eu.Entity, zc); | ||
6093 | |||
6094 | //tau = new List<EntityUpdate>(30); | ||
6095 | //tau.Add(eu); | ||
6096 | count = 1; | ||
6097 | --blocks; | ||
6098 | } | ||
6099 | } | ||
6100 | |||
6101 | if (count > 0) | ||
6102 | { | ||
6103 | buf.Data[countposition] = (byte)count; | ||
6104 | buf.DataLength = zc.Finish(); | ||
6105 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | ||
6106 | // delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | ||
6107 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); | ||
6108 | } | ||
5197 | } | 6109 | } |
5198 | 6110 | ||
5199 | if (objectFamilyBlocks != null) | 6111 | if (objectPropertiesFamilyUpdates != null) |
5200 | { | 6112 | { |
5201 | // one packet per object block... uggh... | 6113 | foreach (EntityUpdate eu in objectPropertiesFamilyUpdates) |
5202 | for (int i = 0; i < objectFamilyBlocks.Count; i++) | ||
5203 | { | 6114 | { |
5204 | ObjectPropertiesFamilyPacket packet = | 6115 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
5205 | (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); | 6116 | Buffer.BlockCopy(ObjectFamilyUpdateHeader, 0, buf.Data, 0, 8); |
5206 | 6117 | ||
5207 | packet.ObjectData = objectFamilyBlocks[i]; | 6118 | LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data); |
6119 | zc.Position = 8; | ||
5208 | 6120 | ||
5209 | // Pass in the delegate so that if this packet needs to be resent, we send the current properties | 6121 | CreateObjectPropertiesFamilyBlock((SceneObjectPart)eu.Entity, eu.Flags, zc); |
5210 | // of the object rather than the properties when the packet was created | 6122 | buf.DataLength = zc.Finish(); |
5211 | // List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); | 6123 | //List<EntityUpdate> tau = new List<EntityUpdate>(1); |
5212 | // updates.Add(familyUpdates.Value[i]); | 6124 | //tau.Add(new ObjectPropertyUpdate((ISceneEntity) eu, (uint)eu.Flags, true, false)); |
5213 | // HACK : Remove intelligent resending until it's fixed in core | 6125 | //m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, |
5214 | //OutPacket(packet, ThrottleOutPacketType.Task, true, | 6126 | // delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); |
5215 | // delegate(OutgoingPacket oPacket) | 6127 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task); |
5216 | // { | ||
5217 | // ResendPropertyUpdates(updates, oPacket); | ||
5218 | // }); | ||
5219 | OutPacket(packet, ThrottleOutPacketType.Task, true); | ||
5220 | } | 6128 | } |
5221 | } | 6129 | } |
5222 | 6130 | ||
5223 | if(needPhysics != null) | 6131 | if (needPhysics != null) |
5224 | { | 6132 | { |
5225 | IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>(); | 6133 | IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>(); |
5226 | if(eq != null) | 6134 | if(eq != null) |
@@ -5245,101 +6153,98 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5245 | } | 6153 | } |
5246 | } | 6154 | } |
5247 | 6155 | ||
5248 | private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, PrimUpdateFlags requestFlags) | 6156 | private void CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, PrimUpdateFlags requestFlags, LLUDPZeroEncoder zc) |
5249 | { | 6157 | { |
5250 | ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); | 6158 | SceneObjectPart root = sop.ParentGroup.RootPart; |
5251 | 6159 | ||
5252 | block.RequestFlags = (uint)requestFlags; | 6160 | zc.AddUInt((uint)requestFlags); |
5253 | block.ObjectID = sop.UUID; | 6161 | zc.AddUUID(sop.UUID); |
5254 | if (sop.OwnerID == sop.GroupID) | 6162 | if (sop.OwnerID == sop.GroupID) |
5255 | block.OwnerID = UUID.Zero; | 6163 | zc.AddZeros(16); |
5256 | else | 6164 | else |
5257 | block.OwnerID = sop.OwnerID; | 6165 | zc.AddUUID(sop.OwnerID); |
5258 | block.GroupID = sop.GroupID; | 6166 | zc.AddUUID(sop.GroupID); |
5259 | block.BaseMask = sop.BaseMask; | ||
5260 | block.OwnerMask = sop.OwnerMask; | ||
5261 | block.GroupMask = sop.GroupMask; | ||
5262 | block.EveryoneMask = sop.EveryoneMask; | ||
5263 | block.NextOwnerMask = sop.NextOwnerMask; | ||
5264 | 6167 | ||
5265 | // TODO: More properties are needed in SceneObjectPart! | 6168 | zc.AddUInt(root.BaseMask); |
5266 | block.OwnershipCost = sop.OwnershipCost; | 6169 | zc.AddUInt(root.OwnerMask); |
5267 | block.SaleType = sop.ObjectSaleType; | 6170 | zc.AddUInt(root.GroupMask); |
5268 | block.SalePrice = sop.SalePrice; | 6171 | zc.AddUInt(root.EveryoneMask); |
5269 | block.Category = sop.Category; | 6172 | zc.AddUInt(root.NextOwnerMask); |
5270 | block.LastOwnerID = sop.LastOwnerID; | ||
5271 | block.Name = Util.StringToBytes256(sop.Name); | ||
5272 | block.Description = Util.StringToBytes256(sop.Description); | ||
5273 | 6173 | ||
5274 | return block; | 6174 | zc.AddZeros(4); // int ownership cost |
5275 | } | ||
5276 | 6175 | ||
5277 | private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop) | 6176 | //sale info block |
5278 | { | 6177 | zc.AddByte(root.ObjectSaleType); |
5279 | //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | 6178 | zc.AddInt(root.SalePrice); |
5280 | // TODO: don't create new blocks if recycling an old packet | 6179 | |
6180 | zc.AddUInt(sop.Category); //Category | ||
5281 | 6181 | ||
5282 | ObjectPropertiesPacket.ObjectDataBlock block = | 6182 | zc.AddUUID(sop.LastOwnerID); |
5283 | new ObjectPropertiesPacket.ObjectDataBlock(); | ||
5284 | 6183 | ||
5285 | block.ObjectID = sop.UUID; | 6184 | //name |
5286 | block.Name = Util.StringToBytes256(sop.Name); | 6185 | zc.AddShortString(sop.Name, 64); |
5287 | block.Description = Util.StringToBytes256(sop.Description); | ||
5288 | 6186 | ||
5289 | block.CreationDate = (ulong)sop.CreationDate * 1000000; // viewer wants date in microseconds | 6187 | //Description |
5290 | block.CreatorID = sop.CreatorID; | 6188 | zc.AddShortString(sop.Description, 128); |
5291 | block.GroupID = sop.GroupID; | 6189 | } |
5292 | block.LastOwnerID = sop.LastOwnerID; | 6190 | |
6191 | private void CreateObjectPropertiesBlock(SceneObjectPart sop, LLUDPZeroEncoder zc) | ||
6192 | { | ||
6193 | SceneObjectPart root = sop.ParentGroup.RootPart; | ||
6194 | |||
6195 | zc.AddUUID(sop.UUID); | ||
6196 | zc.AddUUID(sop.CreatorID); | ||
5293 | if (sop.OwnerID == sop.GroupID) | 6197 | if (sop.OwnerID == sop.GroupID) |
5294 | block.OwnerID = UUID.Zero; | 6198 | zc.AddZeros(16); |
5295 | else | 6199 | else |
5296 | block.OwnerID = sop.OwnerID; | 6200 | zc.AddUUID(sop.OwnerID); |
6201 | zc.AddUUID(sop.GroupID); | ||
5297 | 6202 | ||
5298 | block.ItemID = sop.FromUserInventoryItemID; | 6203 | zc.AddUInt64((ulong)sop.CreationDate * 1000000UL); |
5299 | block.FolderID = UUID.Zero; // sog.FromFolderID ?? | ||
5300 | block.FromTaskID = UUID.Zero; // ??? | ||
5301 | block.InventorySerial = (short)sop.InventorySerial; | ||
5302 | 6204 | ||
5303 | SceneObjectPart root = sop.ParentGroup.RootPart; | 6205 | zc.AddUInt(root.BaseMask); |
6206 | zc.AddUInt(root.OwnerMask); | ||
6207 | zc.AddUInt(root.GroupMask); | ||
6208 | zc.AddUInt(root.EveryoneMask); | ||
6209 | zc.AddUInt(root.NextOwnerMask); | ||
5304 | 6210 | ||
5305 | block.TouchName = Util.StringToBytes256(root.TouchName); | 6211 | zc.AddZeros(4); // int ownership cost |
5306 | 6212 | ||
5307 | // SL 3.3.4, at least, appears to read this information as a concatenated byte[] stream of UUIDs but | 6213 | //sale info block |
5308 | // it's not yet clear whether this is actually used. If this is done in the future then a pre-cached | 6214 | zc.AddByte(root.ObjectSaleType); |
5309 | // copy is really needed since it's less efficient to be constantly recreating this byte array. | 6215 | zc.AddInt(root.SalePrice); |
5310 | // using (MemoryStream memStream = new MemoryStream()) | 6216 | |
5311 | // { | 6217 | //aggregated perms we may will need to fix this |
5312 | // using (BinaryWriter binWriter = new BinaryWriter(memStream)) | 6218 | zc.AddByte(0); //AggregatePerms |
5313 | // { | 6219 | zc.AddByte(0); //AggregatePermTextures; |
5314 | // for (int i = 0; i < sop.GetNumberOfSides(); i++) | 6220 | zc.AddByte(0); //AggregatePermTexturesOwner |
5315 | // { | 6221 | |
5316 | // Primitive.TextureEntryFace teFace = sop.Shape.Textures.FaceTextures[i]; | 6222 | //inventory info |
5317 | // | 6223 | zc.AddUInt(sop.Category); //Category |
5318 | // UUID textureID; | 6224 | zc.AddInt16((short)sop.InventorySerial); |
5319 | // | 6225 | zc.AddUUID(sop.FromUserInventoryItemID); |
5320 | // if (teFace != null) | 6226 | zc.AddUUID(UUID.Zero); //FolderID |
5321 | // textureID = teFace.TextureID; | 6227 | zc.AddUUID(UUID.Zero); //FromTaskID |
5322 | // else | 6228 | |
5323 | // textureID = sop.Shape.Textures.DefaultTexture.TextureID; | 6229 | zc.AddUUID(sop.LastOwnerID); |
5324 | // | ||
5325 | // binWriter.Write(textureID.GetBytes()); | ||
5326 | // } | ||
5327 | // | ||
5328 | // block.TextureID = memStream.ToArray(); | ||
5329 | // } | ||
5330 | // } | ||
5331 | 6230 | ||
5332 | block.TextureID = new byte[0]; // TextureID ??? | 6231 | //name |
5333 | block.SitName = Util.StringToBytes256(root.SitName); | 6232 | zc.AddShortString(sop.Name, 64); |
5334 | block.OwnerMask = root.OwnerMask; | ||
5335 | block.NextOwnerMask = root.NextOwnerMask; | ||
5336 | block.GroupMask = root.GroupMask; | ||
5337 | block.EveryoneMask = root.EveryoneMask; | ||
5338 | block.BaseMask = root.BaseMask; | ||
5339 | block.SaleType = root.ObjectSaleType; | ||
5340 | block.SalePrice = root.SalePrice; | ||
5341 | 6233 | ||
5342 | return block; | 6234 | //Description |
6235 | zc.AddShortString(sop.Description, 128); | ||
6236 | |||
6237 | // touch name | ||
6238 | zc.AddShortString(root.TouchName, 9, 37); | ||
6239 | |||
6240 | // sit name | ||
6241 | zc.AddShortString(root.SitName, 9, 37); | ||
6242 | |||
6243 | //texture ids block | ||
6244 | // still not sending, not clear the impact on viewers, if any. | ||
6245 | // does seem redundant | ||
6246 | // to send we will need proper list of face texture ids without having to unpack texture entry all the time | ||
6247 | zc.AddZeros(1); | ||
5343 | } | 6248 | } |
5344 | 6249 | ||
5345 | #region Estate Data Sending Methods | 6250 | #region Estate Data Sending Methods |
@@ -5442,7 +6347,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5442 | rinfopack.AgentData.SessionID = SessionId; | 6347 | rinfopack.AgentData.SessionID = SessionId; |
5443 | rinfoblk.BillableFactor = args.billableFactor; | 6348 | rinfoblk.BillableFactor = args.billableFactor; |
5444 | rinfoblk.EstateID = args.estateID; | 6349 | rinfoblk.EstateID = args.estateID; |
5445 | rinfoblk.MaxAgents = args.maxAgents; | 6350 | rinfoblk.MaxAgents = (byte)args.maxAgents; |
5446 | rinfoblk.ObjectBonusFactor = args.objectBonusFactor; | 6351 | rinfoblk.ObjectBonusFactor = args.objectBonusFactor; |
5447 | rinfoblk.ParentEstateID = args.parentEstateID; | 6352 | rinfoblk.ParentEstateID = args.parentEstateID; |
5448 | rinfoblk.PricePerMeter = args.pricePerMeter; | 6353 | rinfoblk.PricePerMeter = args.pricePerMeter; |
@@ -5458,9 +6363,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5458 | rinfoblk.SimName = Utils.StringToBytes(args.simName); | 6363 | rinfoblk.SimName = Utils.StringToBytes(args.simName); |
5459 | 6364 | ||
5460 | rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); | 6365 | rinfopack.RegionInfo2 = new RegionInfoPacket.RegionInfo2Block(); |
5461 | rinfopack.RegionInfo2.HardMaxAgents = uint.MaxValue; | 6366 | rinfopack.RegionInfo2.HardMaxAgents = (uint)args.AgentCapacity; |
5462 | rinfopack.RegionInfo2.HardMaxObjects = uint.MaxValue; | 6367 | rinfopack.RegionInfo2.HardMaxObjects = (uint)args.ObjectsCapacity; |
5463 | rinfopack.RegionInfo2.MaxAgents32 = uint.MaxValue; | 6368 | rinfopack.RegionInfo2.MaxAgents32 = (uint)args.maxAgents; |
5464 | rinfopack.RegionInfo2.ProductName = Util.StringToBytes256(args.regionType); | 6369 | rinfopack.RegionInfo2.ProductName = Util.StringToBytes256(args.regionType); |
5465 | rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; | 6370 | rinfopack.RegionInfo2.ProductSKU = Utils.EmptyBytes; |
5466 | 6371 | ||
@@ -5808,121 +6713,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5808 | } | 6713 | } |
5809 | } | 6714 | } |
5810 | 6715 | ||
5811 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity) | ||
5812 | { | ||
5813 | #region ScenePresence/SOP Handling | ||
5814 | |||
5815 | bool avatar = (entity is ScenePresence); | ||
5816 | uint localID = entity.LocalId; | ||
5817 | uint attachPoint; | ||
5818 | Vector4 collisionPlane; | ||
5819 | Vector3 position, velocity, acceleration, angularVelocity; | ||
5820 | Quaternion rotation; | ||
5821 | |||
5822 | if (avatar) | ||
5823 | { | ||
5824 | ScenePresence presence = (ScenePresence)entity; | ||
5825 | |||
5826 | position = presence.OffsetPosition; | ||
5827 | velocity = presence.Velocity; | ||
5828 | acceleration = Vector3.Zero; | ||
5829 | rotation = presence.Rotation; | ||
5830 | // tpvs can only see rotations around Z in some cases | ||
5831 | if(!presence.Flying && !presence.IsSatOnObject) | ||
5832 | { | ||
5833 | rotation.X = 0f; | ||
5834 | rotation.Y = 0f; | ||
5835 | } | ||
5836 | rotation.Normalize(); | ||
5837 | angularVelocity = presence.AngularVelocity; | ||
5838 | |||
5839 | // m_log.DebugFormat( | ||
5840 | // "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name); | ||
5841 | |||
5842 | attachPoint = presence.State; | ||
5843 | collisionPlane = presence.CollisionPlane; | ||
5844 | } | ||
5845 | else | ||
5846 | { | ||
5847 | SceneObjectPart part = (SceneObjectPart)entity; | ||
5848 | |||
5849 | attachPoint = part.ParentGroup.AttachmentPoint; | ||
5850 | attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16)); | ||
5851 | // m_log.DebugFormat( | ||
5852 | // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", | ||
5853 | // attachPoint, part.Name, part.LocalId, Name); | ||
5854 | |||
5855 | collisionPlane = Vector4.Zero; | ||
5856 | position = part.RelativePosition; | ||
5857 | velocity = part.Velocity; | ||
5858 | acceleration = part.Acceleration; | ||
5859 | angularVelocity = part.AngularVelocity; | ||
5860 | rotation = part.RotationOffset; | ||
5861 | } | ||
5862 | |||
5863 | #endregion ScenePresence/SOP Handling | ||
5864 | |||
5865 | int pos = 0; | ||
5866 | byte[] data = new byte[(avatar ? 60 : 44)]; | ||
5867 | |||
5868 | // LocalID | ||
5869 | Utils.UIntToBytes(localID, data, pos); | ||
5870 | pos += 4; | ||
5871 | |||
5872 | // Avatar/CollisionPlane | ||
5873 | data[pos++] = (byte) attachPoint; | ||
5874 | if (avatar) | ||
5875 | { | ||
5876 | data[pos++] = 1; | ||
5877 | |||
5878 | if (collisionPlane == Vector4.Zero) | ||
5879 | collisionPlane = Vector4.UnitW; | ||
5880 | //m_log.DebugFormat("CollisionPlane: {0}",collisionPlane); | ||
5881 | collisionPlane.ToBytes(data, pos); | ||
5882 | pos += 16; | ||
5883 | } | ||
5884 | else | ||
5885 | { | ||
5886 | ++pos; | ||
5887 | } | ||
5888 | |||
5889 | // Position | ||
5890 | position.ToBytes(data, pos); | ||
5891 | pos += 12; | ||
5892 | |||
5893 | // Velocity | ||
5894 | ClampVectorForUint(ref velocity, 128f); | ||
5895 | Utils.FloatToUInt16Bytes(velocity.X, 128.0f, data, pos); pos += 2; | ||
5896 | Utils.FloatToUInt16Bytes(velocity.Y, 128.0f, data, pos); pos += 2; | ||
5897 | Utils.FloatToUInt16Bytes(velocity.Z, 128.0f, data, pos); pos += 2; | ||
5898 | |||
5899 | // Acceleration | ||
5900 | ClampVectorForUint(ref acceleration, 64f); | ||
5901 | Utils.FloatToUInt16Bytes(acceleration.X, 64.0f, data, pos); pos += 2; | ||
5902 | Utils.FloatToUInt16Bytes(acceleration.Y, 64.0f, data, pos); pos += 2; | ||
5903 | Utils.FloatToUInt16Bytes(acceleration.Z, 64.0f, data, pos); pos += 2; | ||
5904 | |||
5905 | // Rotation | ||
5906 | Utils.FloatToUInt16Bytes(rotation.X, 1.0f, data, pos); pos += 2; | ||
5907 | Utils.FloatToUInt16Bytes(rotation.Y, 1.0f, data, pos); pos += 2; | ||
5908 | Utils.FloatToUInt16Bytes(rotation.Z, 1.0f, data, pos); pos += 2; | ||
5909 | Utils.FloatToUInt16Bytes(rotation.W, 1.0f, data, pos); pos += 2; | ||
5910 | |||
5911 | // Angular Velocity | ||
5912 | ClampVectorForUint(ref angularVelocity, 64f); | ||
5913 | Utils.FloatToUInt16Bytes(angularVelocity.X, 64.0f, data, pos); pos += 2; | ||
5914 | Utils.FloatToUInt16Bytes(angularVelocity.Y, 64.0f, data, pos); pos += 2; | ||
5915 | Utils.FloatToUInt16Bytes(angularVelocity.Z, 64.0f, data, pos); pos += 2; | ||
5916 | |||
5917 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block | ||
5918 | = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); | ||
5919 | |||
5920 | block.Data = data; | ||
5921 | block.TextureEntry = Utils.EmptyBytes; | ||
5922 | |||
5923 | return block; | ||
5924 | } | ||
5925 | |||
5926 | protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture) | 6716 | protected void CreateImprovedTerseBlock(ISceneEntity entity, byte[] data, ref int pos, bool includeTexture) |
5927 | { | 6717 | { |
5928 | #region ScenePresence/SOP Handling | 6718 | #region ScenePresence/SOP Handling |
@@ -6059,73 +6849,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6059 | // total size 63 or 47 + (texture size + 4) | 6849 | // total size 63 or 47 + (texture size + 4) |
6060 | } | 6850 | } |
6061 | 6851 | ||
6062 | protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) | ||
6063 | { | ||
6064 | Quaternion rotation = data.Rotation; | ||
6065 | // tpvs can only see rotations around Z in some cases | ||
6066 | if(!data.Flying && !data.IsSatOnObject) | ||
6067 | { | ||
6068 | rotation.X = 0f; | ||
6069 | rotation.Y = 0f; | ||
6070 | } | ||
6071 | rotation.Normalize(); | ||
6072 | |||
6073 | // m_log.DebugFormat( | ||
6074 | // "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); | ||
6075 | |||
6076 | byte[] objectData = new byte[76]; | ||
6077 | |||
6078 | //Vector3 velocity = Vector3.Zero; | ||
6079 | Vector3 acceleration = Vector3.Zero; | ||
6080 | Vector3 angularvelocity = Vector3.Zero; | ||
6081 | |||
6082 | data.CollisionPlane.ToBytes(objectData, 0); | ||
6083 | data.OffsetPosition.ToBytes(objectData, 16); | ||
6084 | data.Velocity.ToBytes(objectData, 28); | ||
6085 | acceleration.ToBytes(objectData, 40); | ||
6086 | rotation.ToBytes(objectData, 52); | ||
6087 | angularvelocity.ToBytes(objectData, 64); | ||
6088 | |||
6089 | ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); | ||
6090 | |||
6091 | update.Data = Utils.EmptyBytes; | ||
6092 | update.ExtraParams = Utils.EmptyBytes; | ||
6093 | update.FullID = data.UUID; | ||
6094 | update.ID = data.LocalId; | ||
6095 | update.Material = (byte)Material.Flesh; | ||
6096 | update.MediaURL = Utils.EmptyBytes; | ||
6097 | update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + | ||
6098 | data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); | ||
6099 | update.ObjectData = objectData; | ||
6100 | |||
6101 | SceneObjectPart parentPart = data.ParentPart; | ||
6102 | if (parentPart != null) | ||
6103 | update.ParentID = parentPart.ParentGroup.LocalId; | ||
6104 | else | ||
6105 | update.ParentID = 0; | ||
6106 | |||
6107 | update.PathCurve = 16; | ||
6108 | update.PathScaleX = 100; | ||
6109 | update.PathScaleY = 100; | ||
6110 | update.PCode = (byte)PCode.Avatar; | ||
6111 | update.ProfileCurve = 1; | ||
6112 | update.PSBlock = Utils.EmptyBytes; | ||
6113 | update.Scale = data.Appearance.AvatarSize; | ||
6114 | // update.Scale.Z -= 0.2f; | ||
6115 | |||
6116 | update.Text = Utils.EmptyBytes; | ||
6117 | update.TextColor = new byte[4]; | ||
6118 | |||
6119 | // Don't send texture anim for avatars - this has no meaning for them. | ||
6120 | update.TextureAnim = Utils.EmptyBytes; | ||
6121 | |||
6122 | // Don't send texture entry for avatars here - this is accomplished via the AvatarAppearance packet | ||
6123 | update.TextureEntry = Utils.EmptyBytes; | ||
6124 | update.UpdateFlags = 0; | ||
6125 | |||
6126 | return update; | ||
6127 | } | ||
6128 | |||
6129 | protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos) | 6852 | protected void CreateAvatarUpdateBlock(ScenePresence data, byte[] dest, ref int pos) |
6130 | { | 6853 | { |
6131 | Quaternion rotation = data.Rotation; | 6854 | Quaternion rotation = data.Rotation; |
@@ -6278,150 +7001,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6278 | zc.AddZeros(lastzeros); | 7001 | zc.AddZeros(lastzeros); |
6279 | } | 7002 | } |
6280 | 7003 | ||
6281 | protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) | ||
6282 | { | ||
6283 | byte[] objectData = new byte[60]; | ||
6284 | part.RelativePosition.ToBytes(objectData, 0); | ||
6285 | part.Velocity.ToBytes(objectData, 12); | ||
6286 | part.Acceleration.ToBytes(objectData, 24); | ||
6287 | |||
6288 | Quaternion rotation = part.RotationOffset; | ||
6289 | rotation.Normalize(); | ||
6290 | rotation.ToBytes(objectData, 36); | ||
6291 | part.AngularVelocity.ToBytes(objectData, 48); | ||
6292 | |||
6293 | ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); | ||
6294 | update.ClickAction = (byte)part.ClickAction; | ||
6295 | update.CRC = 0; | ||
6296 | update.ExtraParams = part.Shape.ExtraParams ?? Utils.EmptyBytes; | ||
6297 | update.FullID = part.UUID; | ||
6298 | update.ID = part.LocalId; | ||
6299 | //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated | ||
6300 | //update.JointPivot = Vector3.Zero; | ||
6301 | //update.JointType = 0; | ||
6302 | update.Material = part.Material; | ||
6303 | |||
6304 | if (part.ParentGroup.IsAttachment) | ||
6305 | { | ||
6306 | if (part.IsRoot) | ||
6307 | { | ||
6308 | update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); | ||
6309 | } | ||
6310 | else | ||
6311 | update.NameValue = Utils.EmptyBytes; | ||
6312 | |||
6313 | int st = (int)part.ParentGroup.AttachmentPoint; | ||
6314 | update.State = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; | ||
6315 | } | ||
6316 | else | ||
6317 | { | ||
6318 | update.NameValue = Utils.EmptyBytes; | ||
6319 | update.State = part.Shape.State; // not sure about this | ||
6320 | } | ||
6321 | |||
6322 | update.ObjectData = objectData; | ||
6323 | update.ParentID = part.ParentID; | ||
6324 | update.PathBegin = part.Shape.PathBegin; | ||
6325 | update.PathCurve = part.Shape.PathCurve; | ||
6326 | update.PathEnd = part.Shape.PathEnd; | ||
6327 | update.PathRadiusOffset = part.Shape.PathRadiusOffset; | ||
6328 | update.PathRevolutions = part.Shape.PathRevolutions; | ||
6329 | update.PathScaleX = part.Shape.PathScaleX; | ||
6330 | update.PathScaleY = part.Shape.PathScaleY; | ||
6331 | update.PathShearX = part.Shape.PathShearX; | ||
6332 | update.PathShearY = part.Shape.PathShearY; | ||
6333 | update.PathSkew = part.Shape.PathSkew; | ||
6334 | update.PathTaperX = part.Shape.PathTaperX; | ||
6335 | update.PathTaperY = part.Shape.PathTaperY; | ||
6336 | update.PathTwist = part.Shape.PathTwist; | ||
6337 | update.PathTwistBegin = part.Shape.PathTwistBegin; | ||
6338 | update.PCode = part.Shape.PCode; | ||
6339 | update.ProfileBegin = part.Shape.ProfileBegin; | ||
6340 | update.ProfileCurve = part.Shape.ProfileCurve; | ||
6341 | |||
6342 | ushort profileBegin = part.Shape.ProfileBegin; | ||
6343 | ushort profileHollow = part.Shape.ProfileHollow; | ||
6344 | |||
6345 | if(part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack | ||
6346 | { | ||
6347 | update.ProfileCurve = (byte)(part.Shape.ProfileCurve & 0x0f); | ||
6348 | // fix old values that confused viewers | ||
6349 | if(profileBegin == 1) | ||
6350 | profileBegin = 9375; | ||
6351 | if(profileHollow == 1) | ||
6352 | profileHollow = 27500; | ||
6353 | // fix torus hole size Y that also confuse some viewers | ||
6354 | if(update.ProfileCurve == (byte)ProfileShape.Circle && update.PathScaleY < 150) | ||
6355 | update.PathScaleY = 150; | ||
6356 | } | ||
6357 | else | ||
6358 | { | ||
6359 | update.ProfileCurve = part.Shape.ProfileCurve; | ||
6360 | } | ||
6361 | |||
6362 | update.ProfileHollow = profileHollow; | ||
6363 | update.ProfileBegin = profileBegin; | ||
6364 | update.ProfileEnd = part.Shape.ProfileEnd; | ||
6365 | update.PSBlock = part.ParticleSystem ?? Utils.EmptyBytes; | ||
6366 | update.TextColor = part.GetTextColor().GetBytes(false); | ||
6367 | update.TextureAnim = part.TextureAnimation ?? Utils.EmptyBytes; | ||
6368 | update.TextureEntry = part.Shape.TextureEntry ?? Utils.EmptyBytes; | ||
6369 | update.Scale = part.Shape.Scale; | ||
6370 | update.Text = Util.StringToBytes(part.Text, 255); | ||
6371 | update.MediaURL = Util.StringToBytes(part.MediaUrl, 255); | ||
6372 | |||
6373 | #region PrimFlags | ||
6374 | |||
6375 | PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp); | ||
6376 | |||
6377 | // Don't send the CreateSelected flag to everyone | ||
6378 | flags &= ~PrimFlags.CreateSelected; | ||
6379 | |||
6380 | if (sp.UUID == part.OwnerID) | ||
6381 | { | ||
6382 | if (part.CreateSelected) | ||
6383 | { | ||
6384 | // Only send this flag once, then unset it | ||
6385 | flags |= PrimFlags.CreateSelected; | ||
6386 | part.CreateSelected = false; | ||
6387 | } | ||
6388 | } | ||
6389 | |||
6390 | // m_log.DebugFormat( | ||
6391 | // "[LLCLIENTVIEW]: Constructing client update for part {0} {1} with flags {2}, localId {3}", | ||
6392 | // data.Name, update.FullID, flags, update.ID); | ||
6393 | |||
6394 | update.UpdateFlags = (uint)flags; | ||
6395 | |||
6396 | #endregion PrimFlags | ||
6397 | |||
6398 | bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0; | ||
6399 | if (hassound) | ||
6400 | { | ||
6401 | update.Sound = part.Sound; | ||
6402 | update.Gain = (float)part.SoundGain; | ||
6403 | update.Radius = (float)part.SoundRadius; | ||
6404 | update.Flags = part.SoundFlags; | ||
6405 | } | ||
6406 | |||
6407 | if(hassound || update.PSBlock.Length > 1) | ||
6408 | update.OwnerID = part.OwnerID; | ||
6409 | |||
6410 | switch ((PCode)part.Shape.PCode) | ||
6411 | { | ||
6412 | case PCode.Grass: | ||
6413 | case PCode.Tree: | ||
6414 | case PCode.NewTree: | ||
6415 | update.Data = new byte[] { part.Shape.State }; | ||
6416 | break; | ||
6417 | default: | ||
6418 | update.Data = Utils.EmptyBytes; | ||
6419 | break; | ||
6420 | } | ||
6421 | |||
6422 | return update; | ||
6423 | } | ||
6424 | |||
6425 | protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc) | 7004 | protected void CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc) |
6426 | { | 7005 | { |
6427 | // prepare data | 7006 | // prepare data |
@@ -6453,7 +7032,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6453 | zc.AddUInt(part.LocalId); | 7032 | zc.AddUInt(part.LocalId); |
6454 | zc.AddByte(state); // state | 7033 | zc.AddByte(state); // state |
6455 | zc.AddUUID(part.UUID); | 7034 | zc.AddUUID(part.UUID); |
6456 | zc.AddZeros(4); // crc unused | 7035 | zc.AddUInt((uint)part.ParentGroup.PseudoCRC); |
6457 | zc.AddByte((byte)pcode); | 7036 | zc.AddByte((byte)pcode); |
6458 | // material 1 | 7037 | // material 1 |
6459 | // clickaction 1 | 7038 | // clickaction 1 |
@@ -6565,7 +7144,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6565 | zc.AddUInt(part.LocalId); | 7144 | zc.AddUInt(part.LocalId); |
6566 | zc.AddByte(state); // state | 7145 | zc.AddByte(state); // state |
6567 | zc.AddUUID(part.UUID); | 7146 | zc.AddUUID(part.UUID); |
6568 | zc.AddZeros(4); // crc unused | 7147 | zc.AddUInt((uint)part.ParentGroup.PseudoCRC); |
6569 | zc.AddByte((byte)pcode); | 7148 | zc.AddByte((byte)pcode); |
6570 | zc.AddByte(part.Material); | 7149 | zc.AddByte(part.Material); |
6571 | zc.AddByte(part.ClickAction); // clickaction | 7150 | zc.AddByte(part.ClickAction); // clickaction |
@@ -6654,10 +7233,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6654 | zc.AddZeros(5); | 7233 | zc.AddZeros(5); |
6655 | else | 7234 | else |
6656 | { | 7235 | { |
6657 | byte[] tbuf = Util.StringToBytes(part.Text, 254); | 7236 | zc.AddShortString(part.Text, 255); |
6658 | int len = tbuf.Length; | ||
6659 | zc.AddByte((byte)len); | ||
6660 | zc.AddBytes(tbuf, len); | ||
6661 | 7237 | ||
6662 | //textcolor | 7238 | //textcolor |
6663 | byte[] tc = part.GetTextColor().GetBytes(false); | 7239 | byte[] tc = part.GetTextColor().GetBytes(false); |
@@ -6668,12 +7244,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6668 | if (part.MediaUrl == null || part.MediaUrl.Length == 0) | 7244 | if (part.MediaUrl == null || part.MediaUrl.Length == 0) |
6669 | zc.AddZeros(1); | 7245 | zc.AddZeros(1); |
6670 | else | 7246 | else |
6671 | { | 7247 | zc.AddShortString(part.MediaUrl, 255); |
6672 | byte[] tbuf = Util.StringToBytes(part.MediaUrl, 255); | ||
6673 | int len = tbuf.Length; | ||
6674 | zc.AddByte((byte)len); | ||
6675 | zc.AddBytes(tbuf, len); | ||
6676 | } | ||
6677 | 7248 | ||
6678 | bool hasps = false; | 7249 | bool hasps = false; |
6679 | //particle system | 7250 | //particle system |
@@ -6724,10 +7295,581 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6724 | zc.AddZeros(lastzeros); | 7295 | zc.AddZeros(lastzeros); |
6725 | } | 7296 | } |
6726 | 7297 | ||
6727 | protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags) | 7298 | [Flags] |
7299 | private enum CompressedFlags : uint | ||
7300 | { | ||
7301 | None = 0x00, | ||
7302 | /// <summary>Unknown</summary> | ||
7303 | ScratchPad = 0x01, | ||
7304 | /// <summary>Whether the object has a TreeSpecies</summary> | ||
7305 | Tree = 0x02, | ||
7306 | /// <summary>Whether the object has floating text ala llSetText</summary> | ||
7307 | HasText = 0x04, | ||
7308 | /// <summary>Whether the object has an active particle system</summary> | ||
7309 | HasParticlesLegacy = 0x08, | ||
7310 | /// <summary>Whether the object has sound attached to it</summary> | ||
7311 | HasSound = 0x10, | ||
7312 | /// <summary>Whether the object is attached to a root object or not</summary> | ||
7313 | HasParent = 0x20, | ||
7314 | /// <summary>Whether the object has texture animation settings</summary> | ||
7315 | TextureAnimation = 0x40, | ||
7316 | /// <summary>Whether the object has an angular velocity</summary> | ||
7317 | HasAngularVelocity = 0x80, | ||
7318 | /// <summary>Whether the object has a name value pairs string</summary> | ||
7319 | HasNameValues = 0x100, | ||
7320 | /// <summary>Whether the object has a Media URL set</summary> | ||
7321 | MediaURL = 0x200, | ||
7322 | HasParticlesNew = 0x400 | ||
7323 | } | ||
7324 | |||
7325 | /* | ||
7326 | protected void CreateCompressedUpdateBlock(SceneObjectPart part, ScenePresence sp, byte[] dest, ref int pos) | ||
6728 | { | 7327 | { |
6729 | // TODO: Implement this | 7328 | // prepare data |
6730 | return null; | 7329 | CompressedFlags cflags = CompressedFlags.None; |
7330 | |||
7331 | // prim/update flags | ||
7332 | |||
7333 | PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp); | ||
7334 | // Don't send the CreateSelected flag to everyone | ||
7335 | primflags &= ~PrimFlags.CreateSelected; | ||
7336 | if (sp.UUID == part.OwnerID) | ||
7337 | { | ||
7338 | if (part.CreateSelected) | ||
7339 | { | ||
7340 | // Only send this flag once, then unset it | ||
7341 | primflags |= PrimFlags.CreateSelected; | ||
7342 | part.CreateSelected = false; | ||
7343 | } | ||
7344 | } | ||
7345 | |||
7346 | byte state = part.Shape.State; | ||
7347 | PCode pcode = (PCode)part.Shape.PCode; | ||
7348 | |||
7349 | bool hastree = false; | ||
7350 | if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree) | ||
7351 | { | ||
7352 | cflags |= CompressedFlags.Tree; | ||
7353 | hastree = true; | ||
7354 | } | ||
7355 | |||
7356 | //NameValue and state | ||
7357 | byte[] nv = null; | ||
7358 | if (part.ParentGroup.IsAttachment) | ||
7359 | { | ||
7360 | if (part.IsRoot) | ||
7361 | nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); | ||
7362 | |||
7363 | int st = (int)part.ParentGroup.AttachmentPoint; | ||
7364 | state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; | ||
7365 | } | ||
7366 | |||
7367 | bool hastext = part.Text != null && part.Text.Length > 0; | ||
7368 | bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0; | ||
7369 | bool hasps = part.ParticleSystem != null && part.ParticleSystem.Length > 1; | ||
7370 | bool hastexanim = part.TextureAnimation != null && part.TextureAnimation.Length > 0; | ||
7371 | bool hasangvel = part.AngularVelocity.LengthSquared() > 1e-8f; | ||
7372 | bool hasmediaurl = part.MediaUrl != null && part.MediaUrl.Length > 1; | ||
7373 | |||
7374 | bool haspsnew = false; | ||
7375 | if (hastext) | ||
7376 | cflags |= CompressedFlags.HasText; | ||
7377 | if (hasps) | ||
7378 | { | ||
7379 | if(part.ParticleSystem.Length > 86) | ||
7380 | { | ||
7381 | hasps= false; | ||
7382 | cflags |= CompressedFlags.HasParticlesNew; | ||
7383 | haspsnew = true; | ||
7384 | } | ||
7385 | else | ||
7386 | cflags |= CompressedFlags.HasParticlesLegacy; | ||
7387 | } | ||
7388 | if (hassound) | ||
7389 | cflags |= CompressedFlags.HasSound; | ||
7390 | if (part.ParentID != 0) | ||
7391 | cflags |= CompressedFlags.HasParent; | ||
7392 | if (hastexanim) | ||
7393 | cflags |= CompressedFlags.TextureAnimation; | ||
7394 | if (hasangvel) | ||
7395 | cflags |= CompressedFlags.HasAngularVelocity; | ||
7396 | if (hasmediaurl) | ||
7397 | cflags |= CompressedFlags.MediaURL; | ||
7398 | if (nv != null) | ||
7399 | cflags |= CompressedFlags.HasNameValues; | ||
7400 | |||
7401 | // filter out mesh faces hack | ||
7402 | ushort profileBegin = part.Shape.ProfileBegin; | ||
7403 | ushort profileHollow = part.Shape.ProfileHollow; | ||
7404 | byte profileCurve = part.Shape.ProfileCurve; | ||
7405 | byte pathScaleY = part.Shape.PathScaleY; | ||
7406 | |||
7407 | if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack | ||
7408 | { | ||
7409 | profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f); | ||
7410 | // fix old values that confused viewers | ||
7411 | if (profileBegin == 1) | ||
7412 | profileBegin = 9375; | ||
7413 | if (profileHollow == 1) | ||
7414 | profileHollow = 27500; | ||
7415 | // fix torus hole size Y that also confuse some viewers | ||
7416 | if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150) | ||
7417 | pathScaleY = 150; | ||
7418 | } | ||
7419 | |||
7420 | // first is primFlags | ||
7421 | Utils.UIntToBytesSafepos((uint)primflags, dest, pos); pos += 4; | ||
7422 | |||
7423 | // datablock len to fill later | ||
7424 | int lenpos = pos; | ||
7425 | pos += 2; | ||
7426 | |||
7427 | // data block | ||
7428 | part.UUID.ToBytes(dest, pos); pos += 16; | ||
7429 | Utils.UIntToBytesSafepos(part.LocalId, dest, pos); pos += 4; | ||
7430 | dest[pos++] = (byte)pcode; | ||
7431 | dest[pos++] = state; | ||
7432 | |||
7433 | Utils.UIntToBytesSafepos((uint)part.ParentGroup.PseudoCRC, dest, pos); pos += 4; | ||
7434 | dest[pos++] = part.Material; | ||
7435 | dest[pos++] = part.ClickAction; | ||
7436 | part.Shape.Scale.ToBytes(dest, pos); pos += 12; | ||
7437 | part.RelativePosition.ToBytes(dest, pos); pos += 12; | ||
7438 | if(pcode == PCode.Grass) | ||
7439 | Vector3.Zero.ToBytes(dest, pos); | ||
7440 | else | ||
7441 | { | ||
7442 | Quaternion rotation = part.RotationOffset; | ||
7443 | rotation.Normalize(); | ||
7444 | rotation.ToBytes(dest, pos); | ||
7445 | } | ||
7446 | pos += 12; | ||
7447 | |||
7448 | Utils.UIntToBytesSafepos((uint)cflags, dest, pos); pos += 4; | ||
7449 | |||
7450 | if (hasps || haspsnew || hassound) | ||
7451 | part.OwnerID.ToBytes(dest, pos); | ||
7452 | else | ||
7453 | UUID.Zero.ToBytes(dest, pos); | ||
7454 | pos += 16; | ||
7455 | |||
7456 | if (hasangvel) | ||
7457 | { | ||
7458 | part.AngularVelocity.ToBytes(dest, pos); pos += 12; | ||
7459 | } | ||
7460 | if (part.ParentID != 0) | ||
7461 | { | ||
7462 | Utils.UIntToBytesSafepos(part.ParentID, dest, pos); pos += 4; | ||
7463 | } | ||
7464 | if (hastree) | ||
7465 | dest[pos++] = state; | ||
7466 | if (hastext) | ||
7467 | { | ||
7468 | byte[] text = Util.StringToBytes256(part.Text); // must be null term | ||
7469 | Buffer.BlockCopy(text, 0, dest, pos, text.Length); pos += text.Length; | ||
7470 | byte[] tc = part.GetTextColor().GetBytes(false); | ||
7471 | Buffer.BlockCopy(tc, 0, dest, pos, tc.Length); pos += tc.Length; | ||
7472 | } | ||
7473 | if (hasmediaurl) | ||
7474 | { | ||
7475 | byte[] mu = Util.StringToBytes256(part.MediaUrl); // must be null term | ||
7476 | Buffer.BlockCopy(mu, 0, dest, pos, mu.Length); pos += mu.Length; | ||
7477 | } | ||
7478 | if (hasps) | ||
7479 | { | ||
7480 | byte[] ps = part.ParticleSystem; | ||
7481 | Buffer.BlockCopy(ps, 0, dest, pos, ps.Length); pos += ps.Length; | ||
7482 | } | ||
7483 | byte[] ex = part.Shape.ExtraParams; | ||
7484 | if (ex == null || ex.Length < 2) | ||
7485 | dest[pos++] = 0; | ||
7486 | else | ||
7487 | { | ||
7488 | Buffer.BlockCopy(ex, 0, dest, pos, ex.Length); pos += ex.Length; | ||
7489 | } | ||
7490 | if (hassound) | ||
7491 | { | ||
7492 | part.Sound.ToBytes(dest, pos); pos += 16; | ||
7493 | Utils.FloatToBytesSafepos((float)part.SoundGain, dest, pos); pos += 4; | ||
7494 | dest[pos++] = part.SoundFlags; | ||
7495 | Utils.FloatToBytesSafepos((float)part.SoundRadius, dest, pos); pos += 4; | ||
7496 | } | ||
7497 | if (nv != null) | ||
7498 | { | ||
7499 | Buffer.BlockCopy(nv, 0, dest, pos, nv.Length); pos += nv.Length; | ||
7500 | } | ||
7501 | |||
7502 | dest[pos++] = part.Shape.PathCurve; | ||
7503 | Utils.UInt16ToBytes(part.Shape.PathBegin, dest, pos); pos += 2; | ||
7504 | Utils.UInt16ToBytes(part.Shape.PathEnd, dest, pos); pos += 2; | ||
7505 | dest[pos++] = part.Shape.PathScaleX; | ||
7506 | dest[pos++] = pathScaleY; | ||
7507 | dest[pos++] = part.Shape.PathShearX; | ||
7508 | dest[pos++] = part.Shape.PathShearY; | ||
7509 | dest[pos++] = (byte)part.Shape.PathTwist; | ||
7510 | dest[pos++] = (byte)part.Shape.PathTwistBegin; | ||
7511 | dest[pos++] = (byte)part.Shape.PathRadiusOffset; | ||
7512 | dest[pos++] = (byte)part.Shape.PathTaperX; | ||
7513 | dest[pos++] = (byte)part.Shape.PathTaperY; | ||
7514 | dest[pos++] = part.Shape.PathRevolutions; | ||
7515 | dest[pos++] = (byte)part.Shape.PathSkew; | ||
7516 | dest[pos++] = profileCurve; | ||
7517 | Utils.UInt16ToBytes(profileBegin, dest, pos); pos += 2; | ||
7518 | Utils.UInt16ToBytes(part.Shape.ProfileEnd, dest, pos); pos += 2; | ||
7519 | Utils.UInt16ToBytes(profileHollow, dest, pos); pos += 2; | ||
7520 | |||
7521 | byte[] te = part.Shape.TextureEntry; | ||
7522 | if (te == null) | ||
7523 | { | ||
7524 | dest[pos++] = 0; | ||
7525 | dest[pos++] = 0; | ||
7526 | dest[pos++] = 0; | ||
7527 | dest[pos++] = 0; | ||
7528 | } | ||
7529 | else | ||
7530 | { | ||
7531 | int len = te.Length & 0x7fff; | ||
7532 | dest[pos++] = (byte)len; | ||
7533 | dest[pos++] = (byte)(len >> 8); | ||
7534 | dest[pos++] = 0; | ||
7535 | dest[pos++] = 0; | ||
7536 | Buffer.BlockCopy(te, 0, dest, pos, len); | ||
7537 | pos += len; | ||
7538 | } | ||
7539 | if (hastexanim) | ||
7540 | { | ||
7541 | byte[] ta = part.TextureAnimation; | ||
7542 | int len = ta.Length & 0x7fff; | ||
7543 | dest[pos++] = (byte)len; | ||
7544 | dest[pos++] = (byte)(len >> 8); | ||
7545 | dest[pos++] = 0; | ||
7546 | dest[pos++] = 0; | ||
7547 | Buffer.BlockCopy(ta, 0, dest, pos, len); | ||
7548 | pos += len; | ||
7549 | } | ||
7550 | |||
7551 | if (haspsnew) | ||
7552 | { | ||
7553 | byte[] ps = part.ParticleSystem; | ||
7554 | Buffer.BlockCopy(ps, 0, dest, pos, ps.Length); pos += ps.Length; | ||
7555 | } | ||
7556 | |||
7557 | int totlen = pos - lenpos - 2; | ||
7558 | dest[lenpos++] = (byte)totlen; | ||
7559 | dest[lenpos++] = (byte)(totlen >> 8); | ||
7560 | } | ||
7561 | */ | ||
7562 | |||
7563 | protected void CreateCompressedUpdateBlockZC(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc) | ||
7564 | { | ||
7565 | // prepare data | ||
7566 | CompressedFlags cflags = CompressedFlags.None; | ||
7567 | |||
7568 | // prim/update flags | ||
7569 | |||
7570 | PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp); | ||
7571 | // Don't send the CreateSelected flag to everyone | ||
7572 | primflags &= ~PrimFlags.CreateSelected; | ||
7573 | if (sp.UUID == part.OwnerID) | ||
7574 | { | ||
7575 | if (part.CreateSelected) | ||
7576 | { | ||
7577 | // Only send this flag once, then unset it | ||
7578 | primflags |= PrimFlags.CreateSelected; | ||
7579 | part.CreateSelected = false; | ||
7580 | } | ||
7581 | } | ||
7582 | |||
7583 | byte state = part.Shape.State; | ||
7584 | PCode pcode = (PCode)part.Shape.PCode; | ||
7585 | |||
7586 | // trees and grass are a lot more compact | ||
7587 | if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree) | ||
7588 | { | ||
7589 | // first is primFlags | ||
7590 | zc.AddUInt((uint)primflags); | ||
7591 | |||
7592 | // datablock len | ||
7593 | zc.AddByte(113); | ||
7594 | zc.AddZeros(1); | ||
7595 | |||
7596 | // data block | ||
7597 | zc.AddUUID(part.UUID); | ||
7598 | zc.AddUInt(part.LocalId); | ||
7599 | zc.AddByte((byte)pcode); | ||
7600 | zc.AddByte(state); | ||
7601 | |||
7602 | zc.AddUInt((uint)part.ParentGroup.PseudoCRC); | ||
7603 | |||
7604 | zc.AddZeros(2); // material and click action | ||
7605 | |||
7606 | zc.AddVector3(part.Shape.Scale); | ||
7607 | zc.AddVector3(part.RelativePosition); | ||
7608 | if (pcode == PCode.Grass) | ||
7609 | zc.AddZeros(12); | ||
7610 | else | ||
7611 | { | ||
7612 | Quaternion rotation = part.RotationOffset; | ||
7613 | rotation.Normalize(); | ||
7614 | zc.AddNormQuat(rotation); | ||
7615 | } | ||
7616 | |||
7617 | zc.AddUInt((uint)CompressedFlags.Tree); // cflags | ||
7618 | |||
7619 | zc.AddZeros(16); // owner id | ||
7620 | |||
7621 | zc.AddByte(state); // tree parameter | ||
7622 | |||
7623 | zc.AddZeros(28); //extraparameters 1, pbs 23, texture 4 | ||
7624 | |||
7625 | return; | ||
7626 | } | ||
7627 | |||
7628 | //NameValue and state | ||
7629 | byte[] nv = null; | ||
7630 | if (part.ParentGroup.IsAttachment) | ||
7631 | { | ||
7632 | if (part.IsRoot) | ||
7633 | nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); | ||
7634 | |||
7635 | int st = (int)part.ParentGroup.AttachmentPoint; | ||
7636 | state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; | ||
7637 | } | ||
7638 | |||
7639 | bool hastext = false; | ||
7640 | bool hassound = false; | ||
7641 | bool hasps = false; | ||
7642 | bool hastexanim = false; | ||
7643 | bool hasangvel = false; | ||
7644 | bool hasmediaurl = false; | ||
7645 | bool haspsnew = false; | ||
7646 | |||
7647 | int BlockLengh = 111; | ||
7648 | |||
7649 | byte[] extraParamBytes = part.Shape.ExtraParams; | ||
7650 | if (extraParamBytes == null || extraParamBytes.Length < 2) | ||
7651 | { | ||
7652 | ++BlockLengh; | ||
7653 | extraParamBytes = null; | ||
7654 | } | ||
7655 | else | ||
7656 | BlockLengh += extraParamBytes.Length; | ||
7657 | |||
7658 | byte[] hoverText = null; | ||
7659 | byte[] hoverTextColor = null; | ||
7660 | if (part.Text != null && part.Text.Length > 0) | ||
7661 | { | ||
7662 | cflags |= CompressedFlags.HasText; | ||
7663 | hoverText = Util.StringToBytes256(part.Text); | ||
7664 | BlockLengh += hoverText.Length; | ||
7665 | hoverTextColor = part.GetTextColor().GetBytes(false); | ||
7666 | BlockLengh += hoverTextColor.Length; | ||
7667 | hastext = true; | ||
7668 | } | ||
7669 | |||
7670 | if (part.ParticleSystem != null && part.ParticleSystem.Length > 1) | ||
7671 | { | ||
7672 | BlockLengh += part.ParticleSystem.Length; | ||
7673 | if (part.ParticleSystem.Length > 86) | ||
7674 | { | ||
7675 | hasps = false; | ||
7676 | cflags |= CompressedFlags.HasParticlesNew; | ||
7677 | haspsnew = true; | ||
7678 | } | ||
7679 | else | ||
7680 | { | ||
7681 | cflags |= CompressedFlags.HasParticlesLegacy; | ||
7682 | hasps = true; | ||
7683 | } | ||
7684 | } | ||
7685 | |||
7686 | if (part.Sound != UUID.Zero || part.SoundFlags != 0) | ||
7687 | { | ||
7688 | BlockLengh += 25; | ||
7689 | cflags |= CompressedFlags.HasSound; | ||
7690 | hassound = true; | ||
7691 | } | ||
7692 | |||
7693 | if (part.ParentID != 0) | ||
7694 | { | ||
7695 | BlockLengh += 4; | ||
7696 | cflags |= CompressedFlags.HasParent; | ||
7697 | } | ||
7698 | |||
7699 | if (part.TextureAnimation != null && part.TextureAnimation.Length > 0) | ||
7700 | { | ||
7701 | BlockLengh += part.TextureAnimation.Length + 4; | ||
7702 | cflags |= CompressedFlags.TextureAnimation; | ||
7703 | hastexanim = true; | ||
7704 | } | ||
7705 | |||
7706 | if (part.AngularVelocity.LengthSquared() > 1e-8f) | ||
7707 | { | ||
7708 | BlockLengh += 12; | ||
7709 | cflags |= CompressedFlags.HasAngularVelocity; | ||
7710 | hasangvel = true; | ||
7711 | } | ||
7712 | |||
7713 | byte[] mediaURLBytes = null; | ||
7714 | if (part.MediaUrl != null && part.MediaUrl.Length > 1) | ||
7715 | { | ||
7716 | mediaURLBytes = Util.StringToBytes256(part.MediaUrl); // must be null term | ||
7717 | BlockLengh += mediaURLBytes.Length; | ||
7718 | cflags |= CompressedFlags.MediaURL; | ||
7719 | hasmediaurl = true; | ||
7720 | } | ||
7721 | |||
7722 | if (nv != null) | ||
7723 | { | ||
7724 | BlockLengh += nv.Length; | ||
7725 | cflags |= CompressedFlags.HasNameValues; | ||
7726 | } | ||
7727 | |||
7728 | byte[] textureEntry = part.Shape.TextureEntry; | ||
7729 | if(textureEntry != null) | ||
7730 | BlockLengh += textureEntry.Length; | ||
7731 | |||
7732 | // filter out mesh faces hack | ||
7733 | ushort profileBegin = part.Shape.ProfileBegin; | ||
7734 | ushort profileHollow = part.Shape.ProfileHollow; | ||
7735 | byte profileCurve = part.Shape.ProfileCurve; | ||
7736 | byte pathScaleY = part.Shape.PathScaleY; | ||
7737 | |||
7738 | if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack | ||
7739 | { | ||
7740 | profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f); | ||
7741 | // fix old values that confused viewers | ||
7742 | if (profileBegin == 1) | ||
7743 | profileBegin = 9375; | ||
7744 | if (profileHollow == 1) | ||
7745 | profileHollow = 27500; | ||
7746 | // fix torus hole size Y that also confuse some viewers | ||
7747 | if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150) | ||
7748 | pathScaleY = 150; | ||
7749 | } | ||
7750 | |||
7751 | |||
7752 | // first is primFlags | ||
7753 | zc.AddUInt((uint)primflags); | ||
7754 | |||
7755 | // datablock len | ||
7756 | zc.AddByte((byte)BlockLengh); | ||
7757 | zc.AddByte((byte)(BlockLengh >> 8)); | ||
7758 | |||
7759 | // data block | ||
7760 | zc.AddUUID(part.UUID); | ||
7761 | zc.AddUInt(part.LocalId); | ||
7762 | zc.AddByte((byte)pcode); | ||
7763 | zc.AddByte(state); | ||
7764 | |||
7765 | zc.AddUInt((uint)part.ParentGroup.PseudoCRC); | ||
7766 | |||
7767 | zc.AddByte(part.Material); | ||
7768 | zc.AddByte(part.ClickAction); | ||
7769 | zc.AddVector3(part.Shape.Scale); | ||
7770 | zc.AddVector3(part.RelativePosition); | ||
7771 | if (pcode == PCode.Grass) | ||
7772 | zc.AddZeros(12); | ||
7773 | else | ||
7774 | { | ||
7775 | Quaternion rotation = part.RotationOffset; | ||
7776 | rotation.Normalize(); | ||
7777 | zc.AddNormQuat(rotation); | ||
7778 | } | ||
7779 | |||
7780 | zc.AddUInt((uint)cflags); | ||
7781 | |||
7782 | if (hasps || haspsnew || hassound) | ||
7783 | zc.AddUUID(part.OwnerID); | ||
7784 | else | ||
7785 | zc.AddZeros(16); | ||
7786 | |||
7787 | if (hasangvel) | ||
7788 | { | ||
7789 | zc.AddVector3(part.AngularVelocity); | ||
7790 | } | ||
7791 | if (part.ParentID != 0) | ||
7792 | { | ||
7793 | zc.AddUInt(part.ParentID); | ||
7794 | } | ||
7795 | if (hastext) | ||
7796 | { | ||
7797 | zc.AddBytes(hoverText, hoverText.Length); | ||
7798 | zc.AddBytes(hoverTextColor, hoverTextColor.Length); | ||
7799 | } | ||
7800 | if (hasmediaurl) | ||
7801 | { | ||
7802 | zc.AddBytes(mediaURLBytes, mediaURLBytes.Length); | ||
7803 | } | ||
7804 | if (hasps) | ||
7805 | { | ||
7806 | byte[] ps = part.ParticleSystem; | ||
7807 | zc.AddBytes(ps, ps.Length); | ||
7808 | } | ||
7809 | if (extraParamBytes == null) | ||
7810 | zc.AddZeros(1); | ||
7811 | else | ||
7812 | { | ||
7813 | zc.AddBytes(extraParamBytes, extraParamBytes.Length); | ||
7814 | } | ||
7815 | if (hassound) | ||
7816 | { | ||
7817 | zc.AddUUID(part.Sound); | ||
7818 | zc.AddFloat((float)part.SoundGain); | ||
7819 | zc.AddByte(part.SoundFlags); | ||
7820 | zc.AddFloat((float)part.SoundRadius); | ||
7821 | } | ||
7822 | if (nv != null) | ||
7823 | { | ||
7824 | zc.AddBytes(nv, nv.Length); | ||
7825 | } | ||
7826 | |||
7827 | zc.AddByte(part.Shape.PathCurve); | ||
7828 | zc.AddUInt16(part.Shape.PathBegin); | ||
7829 | zc.AddUInt16(part.Shape.PathEnd); | ||
7830 | zc.AddByte(part.Shape.PathScaleX); | ||
7831 | zc.AddByte(pathScaleY); | ||
7832 | zc.AddByte(part.Shape.PathShearX); | ||
7833 | zc.AddByte(part.Shape.PathShearY); | ||
7834 | zc.AddByte((byte)part.Shape.PathTwist); | ||
7835 | zc.AddByte((byte)part.Shape.PathTwistBegin); | ||
7836 | zc.AddByte((byte)part.Shape.PathRadiusOffset); | ||
7837 | zc.AddByte((byte)part.Shape.PathTaperX); | ||
7838 | zc.AddByte((byte)part.Shape.PathTaperY); | ||
7839 | zc.AddByte(part.Shape.PathRevolutions); | ||
7840 | zc.AddByte((byte)part.Shape.PathSkew); | ||
7841 | zc.AddByte(profileCurve); | ||
7842 | zc.AddUInt16(profileBegin); | ||
7843 | zc.AddUInt16(part.Shape.ProfileEnd); | ||
7844 | zc.AddUInt16(profileHollow); | ||
7845 | |||
7846 | if (textureEntry == null) | ||
7847 | { | ||
7848 | zc.AddZeros(4); | ||
7849 | } | ||
7850 | else | ||
7851 | { | ||
7852 | int len = textureEntry.Length; | ||
7853 | zc.AddByte((byte)len); | ||
7854 | zc.AddByte((byte)(len >> 8)); | ||
7855 | zc.AddZeros(2); | ||
7856 | zc.AddBytes(textureEntry, len); | ||
7857 | } | ||
7858 | if (hastexanim) | ||
7859 | { | ||
7860 | byte[] ta = part.TextureAnimation; | ||
7861 | int len = ta.Length; | ||
7862 | zc.AddByte((byte)len); | ||
7863 | zc.AddByte((byte)(len >> 8)); | ||
7864 | zc.AddZeros(2); | ||
7865 | zc.AddBytes(ta, len); | ||
7866 | } | ||
7867 | |||
7868 | if (haspsnew) | ||
7869 | { | ||
7870 | byte[] ps = part.ParticleSystem; | ||
7871 | zc.AddBytes(ps, ps.Length); | ||
7872 | } | ||
6731 | } | 7873 | } |
6732 | 7874 | ||
6733 | public void SendNameReply(UUID profileId, string firstname, string lastname) | 7875 | public void SendNameReply(UUID profileId, string firstname, string lastname) |
@@ -6871,7 +8013,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6871 | AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); | 8013 | AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); |
6872 | AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); | 8014 | AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); |
6873 | AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket); | 8015 | AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket); |
6874 | AddLocalPacketHandler(PacketType.ConfirmXferPacket, HandleConfirmXferPacket); | 8016 | AddLocalPacketHandler(PacketType.ConfirmXferPacket, HandleConfirmXferPacket, false); |
6875 | AddLocalPacketHandler(PacketType.AbortXfer, HandleAbortXfer); | 8017 | AddLocalPacketHandler(PacketType.AbortXfer, HandleAbortXfer); |
6876 | AddLocalPacketHandler(PacketType.CreateInventoryFolder, HandleCreateInventoryFolder); | 8018 | AddLocalPacketHandler(PacketType.CreateInventoryFolder, HandleCreateInventoryFolder); |
6877 | AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder); | 8019 | AddLocalPacketHandler(PacketType.UpdateInventoryFolder, HandleUpdateInventoryFolder); |
@@ -7669,15 +8811,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
7669 | TrackAgentPacket TrackAgent = | 8811 | TrackAgentPacket TrackAgent = |
7670 | (TrackAgentPacket)Packet; | 8812 | (TrackAgentPacket)Packet; |
7671 | 8813 | ||
8814 | if(TrackAgent.AgentData.AgentID != AgentId || TrackAgent.AgentData.SessionID != SessionId) | ||
8815 | return false; | ||
8816 | |||
7672 | TrackAgentUpdate TrackAgentHandler = OnTrackAgent; | 8817 | TrackAgentUpdate TrackAgentHandler = OnTrackAgent; |
7673 | if (TrackAgentHandler != null) | 8818 | if (TrackAgentHandler != null) |
7674 | { | 8819 | { |
7675 | TrackAgentHandler(this, | 8820 | TrackAgentHandler(this, |
7676 | TrackAgent.AgentData.AgentID, | 8821 | TrackAgent.AgentData.AgentID, |
7677 | TrackAgent.TargetData.PreyID); | 8822 | TrackAgent.TargetData.PreyID); |
7678 | return true; | ||
7679 | } | 8823 | } |
7680 | return false; | 8824 | // else |
8825 | // m_courseLocationPrey = TrackAgent.TargetData.PreyID; | ||
8826 | return true; | ||
7681 | } | 8827 | } |
7682 | 8828 | ||
7683 | private bool HandlerRezObject(IClientAPI sender, Packet Pack) | 8829 | private bool HandlerRezObject(IClientAPI sender, Packet Pack) |
@@ -7828,13 +8974,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
7828 | return true; | 8974 | return true; |
7829 | } | 8975 | } |
7830 | 8976 | ||
8977 | public uint m_viewerHandShakeFlags = 0; | ||
8978 | |||
7831 | private bool HandlerRegionHandshakeReply(IClientAPI sender, Packet Pack) | 8979 | private bool HandlerRegionHandshakeReply(IClientAPI sender, Packet Pack) |
7832 | { | 8980 | { |
7833 | Action<IClientAPI> handlerRegionHandShakeReply = OnRegionHandShakeReply; | 8981 | Action<IClientAPI> handlerRegionHandShakeReply = OnRegionHandShakeReply; |
7834 | if (handlerRegionHandShakeReply != null) | 8982 | if (handlerRegionHandShakeReply == null) |
7835 | { | 8983 | return true; // silence the warning |
7836 | handlerRegionHandShakeReply(this); | 8984 | |
7837 | } | 8985 | RegionHandshakeReplyPacket rsrpkt = (RegionHandshakeReplyPacket)Pack; |
8986 | if(rsrpkt.AgentData.AgentID != m_agentId || rsrpkt.AgentData.SessionID != m_sessionId) | ||
8987 | return false; | ||
8988 | |||
8989 | if(m_supportViewerCache) | ||
8990 | m_viewerHandShakeFlags = rsrpkt.RegionInfo.Flags; | ||
8991 | else | ||
8992 | m_viewerHandShakeFlags = 0; | ||
8993 | |||
8994 | handlerRegionHandShakeReply(this); | ||
7838 | 8995 | ||
7839 | return true; | 8996 | return true; |
7840 | } | 8997 | } |
@@ -8078,19 +9235,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
8078 | return true; | 9235 | return true; |
8079 | } | 9236 | } |
8080 | 9237 | ||
8081 | private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) | 9238 | private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) |
8082 | { | 9239 | { |
8083 | m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement"); | 9240 | //m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement"); |
8084 | 9241 | ||
8085 | Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion; | 9242 | Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion; |
8086 | if (handlerCompleteMovementToRegion != null) | 9243 | if (handlerCompleteMovementToRegion == null) |
8087 | { | 9244 | return false; |
8088 | handlerCompleteMovementToRegion(sender, true); | ||
8089 | } | ||
8090 | else | ||
8091 | m_log.Debug("HandleCompleteAgentMovement NULL handler"); | ||
8092 | 9245 | ||
8093 | handlerCompleteMovementToRegion = null; | 9246 | CompleteAgentMovementPacket cmp = (CompleteAgentMovementPacket)Pack; |
9247 | if(cmp.AgentData.AgentID != m_agentId || cmp.AgentData.SessionID != m_sessionId || cmp.AgentData.CircuitCode != m_circuitCode) | ||
9248 | return false; | ||
9249 | |||
9250 | handlerCompleteMovementToRegion(sender, true); | ||
8094 | 9251 | ||
8095 | return true; | 9252 | return true; |
8096 | } | 9253 | } |
@@ -8358,7 +9515,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
8358 | private bool HandleAgentResume(IClientAPI sender, Packet Pack) | 9515 | private bool HandleAgentResume(IClientAPI sender, Packet Pack) |
8359 | { | 9516 | { |
8360 | m_udpClient.IsPaused = false; | 9517 | m_udpClient.IsPaused = false; |
8361 | SendStartPingCheck(m_udpClient.CurrentPingSequence++); | 9518 | m_udpServer.SendPing(m_udpClient); |
8362 | return true; | 9519 | return true; |
8363 | } | 9520 | } |
8364 | 9521 | ||
@@ -8562,6 +9719,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
8562 | 9719 | ||
8563 | private bool HandleRequestMultipleObjects(IClientAPI sender, Packet Pack) | 9720 | private bool HandleRequestMultipleObjects(IClientAPI sender, Packet Pack) |
8564 | { | 9721 | { |
9722 | ObjectRequest handlerObjectRequest = OnObjectRequest; | ||
9723 | if (handlerObjectRequest == null) | ||
9724 | return false; | ||
9725 | |||
8565 | RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; | 9726 | RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; |
8566 | 9727 | ||
8567 | #region Packet Session and User Check | 9728 | #region Packet Session and User Check |
@@ -8570,16 +9731,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
8570 | return true; | 9731 | return true; |
8571 | #endregion | 9732 | #endregion |
8572 | 9733 | ||
8573 | ObjectRequest handlerObjectRequest = null; | ||
8574 | |||
8575 | for (int i = 0; i < incomingRequest.ObjectData.Length; i++) | 9734 | for (int i = 0; i < incomingRequest.ObjectData.Length; i++) |
8576 | { | ||
8577 | handlerObjectRequest = OnObjectRequest; | ||
8578 | if (handlerObjectRequest != null) | ||
8579 | { | ||
8580 | handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); | 9735 | handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); |
8581 | } | ||
8582 | } | ||
8583 | return true; | 9736 | return true; |
8584 | } | 9737 | } |
8585 | 9738 | ||
@@ -9483,12 +10636,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9483 | { | 10636 | { |
9484 | RequestXferPacket xferReq = (RequestXferPacket)Pack; | 10637 | RequestXferPacket xferReq = (RequestXferPacket)Pack; |
9485 | 10638 | ||
9486 | RequestXfer handlerRequestXfer = OnRequestXfer; | 10639 | OnRequestXfer?.Invoke(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); |
9487 | |||
9488 | if (handlerRequestXfer != null) | ||
9489 | { | ||
9490 | handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename)); | ||
9491 | } | ||
9492 | return true; | 10640 | return true; |
9493 | } | 10641 | } |
9494 | 10642 | ||
@@ -9496,11 +10644,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9496 | { | 10644 | { |
9497 | SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; | 10645 | SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; |
9498 | 10646 | ||
9499 | XferReceive handlerXferReceive = OnXferReceive; | 10647 | OnXferReceive?.Invoke(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); |
9500 | if (handlerXferReceive != null) | ||
9501 | { | ||
9502 | handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); | ||
9503 | } | ||
9504 | return true; | 10648 | return true; |
9505 | } | 10649 | } |
9506 | 10650 | ||
@@ -9508,23 +10652,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
9508 | { | 10652 | { |
9509 | ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; | 10653 | ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; |
9510 | 10654 | ||
9511 | ConfirmXfer handlerConfirmXfer = OnConfirmXfer; | 10655 | OnConfirmXfer?.Invoke(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); |
9512 | if (handlerConfirmXfer != null) | ||
9513 | { | ||
9514 | handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); | ||
9515 | } | ||
9516 | return true; | 10656 | return true; |
9517 | } | 10657 | } |
9518 | 10658 | ||
9519 | private bool HandleAbortXfer(IClientAPI sender, Packet Pack) | 10659 | private bool HandleAbortXfer(IClientAPI sender, Packet Pack) |
9520 | { | 10660 | { |
9521 | AbortXferPacket abortXfer = (AbortXferPacket)Pack; | 10661 | AbortXferPacket abortXfer = (AbortXferPacket)Pack; |
9522 | AbortXfer handlerAbortXfer = OnAbortXfer; | ||
9523 | if (handlerAbortXfer != null) | ||
9524 | { | ||
9525 | handlerAbortXfer(this, abortXfer.XferID.ID); | ||
9526 | } | ||
9527 | 10662 | ||
10663 | OnAbortXfer?.Invoke(this, abortXfer.XferID.ID); | ||
9528 | return true; | 10664 | return true; |
9529 | } | 10665 | } |
9530 | 10666 | ||
@@ -11602,7 +12738,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11602 | 12738 | ||
11603 | private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) | 12739 | private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) |
11604 | { | 12740 | { |
12741 | /* | ||
12742 | UseCircuitCodePacket uccp = (UseCircuitCodePacket)Pack; | ||
12743 | if(uccp.CircuitCode.ID == m_agentId && | ||
12744 | uccp.CircuitCode.SessionID == m_sessionId && | ||
12745 | uccp.CircuitCode.Code == m_circuitCode && | ||
12746 | SceneAgent != null && | ||
12747 | !((ScenePresence)SceneAgent).IsDeleted | ||
12748 | ) | ||
12749 | SendRegionHandshake(); // possible someone returning | ||
12750 | */ | ||
11605 | return true; | 12751 | return true; |
12752 | |||
11606 | } | 12753 | } |
11607 | 12754 | ||
11608 | private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack) | 12755 | private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack) |
@@ -13996,38 +15143,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
13996 | { | 15143 | { |
13997 | if (p is ScenePresence) | 15144 | if (p is ScenePresence) |
13998 | { | 15145 | { |
13999 | // m_log.DebugFormat( | 15146 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
14000 | // "[LLCLIENTVIEW]: Immediately sending terse agent update for {0} to {1} in {2}", | ||
14001 | // p.Name, Name, Scene.Name); | ||
14002 | |||
14003 | // It turns out to get the agent to stop flying, you have to feed it stop flying velocities | ||
14004 | // There's no explicit message to send the client to tell it to stop flying.. it relies on the | ||
14005 | // velocity, collision plane and avatar height | ||
14006 | |||
14007 | // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air | ||
14008 | // when the avatar stands up | ||
14009 | |||
14010 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = | ||
14011 | CreateImprovedTerseBlock(p); | ||
14012 | |||
14013 | // const float TIME_DILATION = 1.0f; | ||
14014 | ushort timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);; | ||
14015 | |||
14016 | ImprovedTerseObjectUpdatePacket packet | ||
14017 | = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( | ||
14018 | PacketType.ImprovedTerseObjectUpdate); | ||
14019 | |||
14020 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | ||
14021 | packet.RegionData.TimeDilation = timeDilation; | ||
14022 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; | ||
14023 | |||
14024 | packet.ObjectData[0] = block; | ||
14025 | 15147 | ||
14026 | OutPacket(packet, ThrottleOutPacketType.Task, true); | 15148 | //setup header and regioninfo block |
15149 | Buffer.BlockCopy(terseUpdateHeader, 0, buf.Data, 0, 7); | ||
15150 | Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, buf.Data, 7); | ||
15151 | Utils.UInt16ToBytes(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f), buf.Data, 15); | ||
15152 | buf.Data[17] = 1; | ||
15153 | int pos = 18; | ||
15154 | CreateImprovedTerseBlock(p, buf.Data, ref pos, false); | ||
15155 | buf.DataLength = pos; | ||
15156 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); | ||
14027 | } | 15157 | } |
14028 | |||
14029 | //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, | ||
14030 | // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); | ||
14031 | } | 15158 | } |
14032 | 15159 | ||
14033 | public void SendPlacesReply(UUID queryID, UUID transactionID, | 15160 | public void SendPlacesReply(UUID queryID, UUID transactionID, |
@@ -14275,15 +15402,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
14275 | return new HashSet<string>(m_inPacketsToDrop); | 15402 | return new HashSet<string>(m_inPacketsToDrop); |
14276 | } | 15403 | } |
14277 | 15404 | ||
14278 | public void CheckViewerCaps() | 15405 | public uint GetViewerCaps() |
14279 | { | 15406 | { |
14280 | m_SupportObjectAnimations = false; | 15407 | m_SupportObjectAnimations = false; |
15408 | uint ret; | ||
15409 | if(m_supportViewerCache) | ||
15410 | ret = m_viewerHandShakeFlags; | ||
15411 | else | ||
15412 | ret = (m_viewerHandShakeFlags & 4) | 2; // disable probes | ||
15413 | |||
14281 | if (m_scene.CapsModule != null) | 15414 | if (m_scene.CapsModule != null) |
14282 | { | 15415 | { |
14283 | Caps cap = m_scene.CapsModule.GetCapsForUser(CircuitCode); | 15416 | Caps cap = m_scene.CapsModule.GetCapsForUser(CircuitCode); |
14284 | if (cap != null && (cap.Flags & Caps.CapsFlags.ObjectAnim) != 0) | 15417 | if(cap != null) |
14285 | m_SupportObjectAnimations = true; | 15418 | { |
15419 | if((cap.Flags & Caps.CapsFlags.SentSeeds) != 0) | ||
15420 | ret |= 0x1000; | ||
15421 | if ((cap.Flags & Caps.CapsFlags.ObjectAnim) != 0) | ||
15422 | { | ||
15423 | m_SupportObjectAnimations = true; | ||
15424 | ret |= 0x2000; | ||
15425 | } | ||
15426 | } | ||
14286 | } | 15427 | } |
15428 | return ret; // ??? | ||
14287 | } | 15429 | } |
14288 | } | 15430 | } |
14289 | } | 15431 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 2981337..4e9cf1c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | |||
@@ -148,7 +148,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
148 | /// milliseconds or longer will be resent</summary> | 148 | /// milliseconds or longer will be resent</summary> |
149 | /// <remarks>Calculated from <seealso cref="SRTT"/> and <seealso cref="RTTVAR"/> using the | 149 | /// <remarks>Calculated from <seealso cref="SRTT"/> and <seealso cref="RTTVAR"/> using the |
150 | /// guidelines in RFC 2988</remarks> | 150 | /// guidelines in RFC 2988</remarks> |
151 | public int RTO; | 151 | public int m_RTO; |
152 | /// <summary>Number of bytes received since the last acknowledgement was sent out. This is used | 152 | /// <summary>Number of bytes received since the last acknowledgement was sent out. This is used |
153 | /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2)</summary> | 153 | /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2)</summary> |
154 | public int BytesSinceLastACK; | 154 | public int BytesSinceLastACK; |
@@ -190,12 +190,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
190 | private byte[] m_packedThrottles; | 190 | private byte[] m_packedThrottles; |
191 | 191 | ||
192 | private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC | 192 | private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC |
193 | private int m_maxRTO = 60000; | 193 | private int m_maxRTO = 10000; |
194 | public bool m_deliverPackets = true; | 194 | public bool m_deliverPackets = true; |
195 | 195 | ||
196 | private float m_burstTime; | 196 | private float m_burstTime; |
197 | 197 | ||
198 | public int m_lastStartpingTimeMS; | 198 | public double m_lastStartpingTimeMS; |
199 | public int m_pingMS; | 199 | public int m_pingMS; |
200 | 200 | ||
201 | public int PingTimeMS | 201 | public int PingTimeMS |
@@ -242,7 +242,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
242 | if (maxRTO != 0) | 242 | if (maxRTO != 0) |
243 | m_maxRTO = maxRTO; | 243 | m_maxRTO = maxRTO; |
244 | 244 | ||
245 | m_burstTime = rates.BrustTime; | 245 | m_burstTime = rates.BurstTime; |
246 | float m_burst = rates.ClientMaxRate * m_burstTime; | 246 | float m_burst = rates.ClientMaxRate * m_burstTime; |
247 | 247 | ||
248 | // Create a token bucket throttle for this client that has the scene token bucket as a parent | 248 | // Create a token bucket throttle for this client that has the scene token bucket as a parent |
@@ -251,7 +251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
251 | // Create an array of token buckets for this clients different throttle categories | 251 | // Create an array of token buckets for this clients different throttle categories |
252 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; | 252 | m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; |
253 | 253 | ||
254 | m_burst = rates.Total * rates.BrustTime; | 254 | m_burst = rates.Total * rates.BurstTime; |
255 | 255 | ||
256 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) | 256 | for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) |
257 | { | 257 | { |
@@ -260,11 +260,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
260 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens | 260 | // Initialize the packet outboxes, where packets sit while they are waiting for tokens |
261 | m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>(); | 261 | m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>(); |
262 | // Initialize the token buckets that control the throttling for each category | 262 | // Initialize the token buckets that control the throttling for each category |
263 | m_throttleCategories[i] = new TokenBucket(m_throttleClient, rates.GetRate(type), m_burst); | 263 | //m_throttleCategories[i] = new TokenBucket(m_throttleClient, rates.GetRate(type), m_burst); |
264 | float rate = rates.GetRate(type); | ||
265 | float burst = rate * rates.BurstTime; | ||
266 | m_throttleCategories[i] = new TokenBucket(m_throttleClient, rate , burst); | ||
264 | } | 267 | } |
265 | 268 | ||
266 | // Default the retransmission timeout to one second | 269 | // Default the retransmission timeout to one second |
267 | RTO = m_defaultRTO; | 270 | m_RTO = m_defaultRTO; |
268 | 271 | ||
269 | // Initialize this to a sane value to prevent early disconnects | 272 | // Initialize this to a sane value to prevent early disconnects |
270 | TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; | 273 | TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; |
@@ -443,7 +446,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
443 | 446 | ||
444 | int total = resend + land + wind + cloud + task + texture + asset; | 447 | int total = resend + land + wind + cloud + task + texture + asset; |
445 | 448 | ||
446 | float m_burst = total * m_burstTime; | 449 | //float m_burst = total * m_burstTime; |
447 | 450 | ||
448 | if (ThrottleDebugLevel > 0) | 451 | if (ThrottleDebugLevel > 0) |
449 | { | 452 | { |
@@ -453,7 +456,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
453 | } | 456 | } |
454 | 457 | ||
455 | TokenBucket bucket; | 458 | TokenBucket bucket; |
456 | 459 | /* | |
457 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; | 460 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; |
458 | bucket.RequestedDripRate = resend; | 461 | bucket.RequestedDripRate = resend; |
459 | bucket.RequestedBurst = m_burst; | 462 | bucket.RequestedBurst = m_burst; |
@@ -481,6 +484,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
481 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; | 484 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; |
482 | bucket.RequestedDripRate = texture; | 485 | bucket.RequestedDripRate = texture; |
483 | bucket.RequestedBurst = m_burst; | 486 | bucket.RequestedBurst = m_burst; |
487 | */ | ||
488 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; | ||
489 | bucket.RequestedDripRate = resend; | ||
490 | bucket.RequestedBurst = resend * m_burstTime; | ||
491 | |||
492 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land]; | ||
493 | bucket.RequestedDripRate = land; | ||
494 | bucket.RequestedBurst = land * m_burstTime; | ||
495 | |||
496 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind]; | ||
497 | bucket.RequestedDripRate = wind; | ||
498 | bucket.RequestedBurst = wind * m_burstTime; | ||
499 | |||
500 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud]; | ||
501 | bucket.RequestedDripRate = cloud; | ||
502 | bucket.RequestedBurst = cloud * m_burstTime; | ||
503 | |||
504 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset]; | ||
505 | bucket.RequestedDripRate = asset; | ||
506 | bucket.RequestedBurst = asset * m_burstTime; | ||
507 | |||
508 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; | ||
509 | bucket.RequestedDripRate = task; | ||
510 | bucket.RequestedBurst = task * m_burstTime; | ||
511 | |||
512 | bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; | ||
513 | bucket.RequestedDripRate = texture; | ||
514 | bucket.RequestedBurst = texture * m_burstTime; | ||
484 | 515 | ||
485 | // Reset the packed throttles cached data | 516 | // Reset the packed throttles cached data |
486 | m_packedThrottles = null; | 517 | m_packedThrottles = null; |
@@ -719,57 +750,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
719 | } | 750 | } |
720 | 751 | ||
721 | /// <summary> | 752 | /// <summary> |
722 | /// Called when an ACK packet is received and a round-trip time for a | 753 | /// Called when we get a ping update |
723 | /// packet is calculated. This is used to calculate the smoothed | ||
724 | /// round-trip time, round trip time variance, and finally the | ||
725 | /// retransmission timeout | ||
726 | /// </summary> | 754 | /// </summary> |
727 | /// <param name="r">Round-trip time of a single packet and its | 755 | /// <param name="r"> ping time in ms |
728 | /// acknowledgement</param> | 756 | /// acknowledgement</param> |
729 | public void UpdateRoundTrip(float r) | 757 | public void UpdateRoundTrip(int p) |
730 | { | ||
731 | const float ALPHA = 0.125f; | ||
732 | const float BETA = 0.25f; | ||
733 | const float K = 4.0f; | ||
734 | |||
735 | if (RTTVAR == 0.0f) | ||
736 | { | ||
737 | // First RTT measurement | ||
738 | SRTT = r; | ||
739 | RTTVAR = r * 0.5f; | ||
740 | } | ||
741 | else | ||
742 | { | ||
743 | // Subsequence RTT measurement | ||
744 | RTTVAR = (1.0f - BETA) * RTTVAR + BETA * Math.Abs(SRTT - r); | ||
745 | SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r; | ||
746 | } | ||
747 | |||
748 | int rto = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR)); | ||
749 | |||
750 | // Clamp the retransmission timeout to manageable values | ||
751 | rto = Utils.Clamp(rto, m_defaultRTO, m_maxRTO); | ||
752 | |||
753 | RTO = rto; | ||
754 | |||
755 | //if (RTO != rto) | ||
756 | // m_log.Debug("[LLUDPCLIENT]: Setting RTO to " + RTO + "ms from " + rto + "ms with an RTTVAR of " + | ||
757 | //RTTVAR + " based on new RTT of " + r + "ms"); | ||
758 | } | ||
759 | |||
760 | /// <summary> | ||
761 | /// Exponential backoff of the retransmission timeout, per section 5.5 | ||
762 | /// of RFC 2988 | ||
763 | /// </summary> | ||
764 | public void BackoffRTO() | ||
765 | { | 758 | { |
766 | // Reset SRTT and RTTVAR, we assume they are bogus since things | 759 | p *= 5; |
767 | // didn't work out and we're backing off the timeout | 760 | if( p> m_maxRTO) |
768 | SRTT = 0.0f; | 761 | p = m_maxRTO; |
769 | RTTVAR = 0.0f; | 762 | else if(p < m_defaultRTO) |
763 | p = m_defaultRTO; | ||
770 | 764 | ||
771 | // Double the retransmission timeout | 765 | m_RTO = p; |
772 | RTO = Math.Min(RTO * 2, m_maxRTO); | ||
773 | } | 766 | } |
774 | 767 | ||
775 | const double MIN_CALLBACK_MS = 20.0; | 768 | const double MIN_CALLBACK_MS = 20.0; |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 2300800..e313934 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -229,11 +229,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
229 | StatVerbosity.Debug)); | 229 | StatVerbosity.Debug)); |
230 | } | 230 | } |
231 | 231 | ||
232 | public virtual bool HandlesRegion(Location x) | ||
233 | { | ||
234 | return m_udpServer.HandlesRegion(x); | ||
235 | } | ||
236 | |||
237 | public virtual void Start() | 232 | public virtual void Start() |
238 | { | 233 | { |
239 | m_udpServer.Start(); | 234 | m_udpServer.Start(); |
@@ -256,7 +251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
256 | 251 | ||
257 | /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> | 252 | /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> |
258 | public const int MTU = 1400; | 253 | public const int MTU = 1400; |
259 | public const int MAXPAYLOAD = 1250; | 254 | public const int MAXPAYLOAD = 1200; |
260 | 255 | ||
261 | /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary> | 256 | /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary> |
262 | public int ClientLogoutsDueToNoReceives { get; protected set; } | 257 | public int ClientLogoutsDueToNoReceives { get; protected set; } |
@@ -279,11 +274,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
279 | /// OnQueueEmpty event is triggered for textures</summary> | 274 | /// OnQueueEmpty event is triggered for textures</summary> |
280 | public readonly int TextureSendLimit; | 275 | public readonly int TextureSendLimit; |
281 | 276 | ||
282 | /// <summary>Handlers for incoming packets</summary> | ||
283 | //PacketEventDictionary packetEvents = new PacketEventDictionary(); | ||
284 | /// <summary>Incoming packets that are awaiting handling</summary> | ||
285 | //protected OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); | ||
286 | |||
287 | protected BlockingCollection<IncomingPacket> packetInbox = new BlockingCollection<IncomingPacket>(); | 277 | protected BlockingCollection<IncomingPacket> packetInbox = new BlockingCollection<IncomingPacket>(); |
288 | 278 | ||
289 | /// <summary>Bandwidth throttle for this UDP server</summary> | 279 | /// <summary>Bandwidth throttle for this UDP server</summary> |
@@ -303,9 +293,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
303 | /// <summary>Reference to the scene this UDP server is attached to</summary> | 293 | /// <summary>Reference to the scene this UDP server is attached to</summary> |
304 | public Scene Scene { get; protected set; } | 294 | public Scene Scene { get; protected set; } |
305 | 295 | ||
306 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> | ||
307 | protected Location m_location; | ||
308 | |||
309 | /// <summary>The size of the receive buffer for the UDP socket. This value | 296 | /// <summary>The size of the receive buffer for the UDP socket. This value |
310 | /// is passed up to the operating system and used in the system networking | 297 | /// is passed up to the operating system and used in the system networking |
311 | /// stack. Use zero to leave this value as the default</summary> | 298 | /// stack. Use zero to leave this value as the default</summary> |
@@ -374,12 +361,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
374 | /// </summary> | 361 | /// </summary> |
375 | public int IncomingOrphanedPacketCount { get; protected set; } | 362 | public int IncomingOrphanedPacketCount { get; protected set; } |
376 | 363 | ||
377 | /// <summary> | 364 | public bool SupportViewerObjectsCache = true; |
378 | /// Queue some low priority but potentially high volume async requests so that they don't overwhelm available | ||
379 | /// threadpool threads. | ||
380 | /// </summary> | ||
381 | // public JobEngine IpahEngine { get; protected set; } | ||
382 | |||
383 | /// <summary> | 365 | /// <summary> |
384 | /// Run queue empty processing within a single persistent thread. | 366 | /// Run queue empty processing within a single persistent thread. |
385 | /// </summary> | 367 | /// </summary> |
@@ -444,6 +426,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
444 | m_disableFacelights = config.GetBoolean("DisableFacelights", false); | 426 | m_disableFacelights = config.GetBoolean("DisableFacelights", false); |
445 | m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60); | 427 | m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60); |
446 | m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300); | 428 | m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300); |
429 | SupportViewerObjectsCache = config.GetBoolean("SupportViewerObjectsCache", SupportViewerObjectsCache); | ||
447 | } | 430 | } |
448 | else | 431 | else |
449 | { | 432 | { |
@@ -477,8 +460,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
477 | Throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f); | 460 | Throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f); |
478 | ThrottleRates = new ThrottleRates(configSource); | 461 | ThrottleRates = new ThrottleRates(configSource); |
479 | 462 | ||
480 | Random rnd = new Random(Util.EnvironmentTickCount()); | ||
481 | |||
482 | // if (usePools) | 463 | // if (usePools) |
483 | // EnablePools(); | 464 | // EnablePools(); |
484 | } | 465 | } |
@@ -556,13 +537,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
556 | } | 537 | } |
557 | 538 | ||
558 | Scene = (Scene)scene; | 539 | Scene = (Scene)scene; |
559 | m_location = new Location(Scene.RegionInfo.RegionHandle); | 540 | |
560 | /* | ||
561 | IpahEngine | ||
562 | = new JobEngine( | ||
563 | string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), | ||
564 | "INCOMING PACKET ASYNC HANDLING ENGINE"); | ||
565 | */ | ||
566 | OqrEngine = new JobEngine( | 541 | OqrEngine = new JobEngine( |
567 | string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), | 542 | string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), |
568 | "OUTGOING QUEUE REFILL ENGINE"); | 543 | "OUTGOING QUEUE REFILL ENGINE"); |
@@ -689,11 +664,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
689 | commands.Register(); | 664 | commands.Register(); |
690 | } | 665 | } |
691 | 666 | ||
692 | public bool HandlesRegion(Location x) | ||
693 | { | ||
694 | return x == m_location; | ||
695 | } | ||
696 | |||
697 | public int GetTotalQueuedOutgoingPackets() | 667 | public int GetTotalQueuedOutgoingPackets() |
698 | { | 668 | { |
699 | int total = 0; | 669 | int total = 0; |
@@ -844,13 +814,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
844 | bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; | 814 | bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; |
845 | bool doCopy = true; | 815 | bool doCopy = true; |
846 | 816 | ||
847 | // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. | ||
848 | // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting | ||
849 | // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here | ||
850 | // to accomodate for both common scenarios and provide ample room for ACK appending in both | ||
851 | //int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; | ||
852 | |||
853 | //UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); | ||
854 | UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint); | 817 | UDPPacketBuffer buffer = GetNewUDPBuffer(udpClient.RemoteEndPoint); |
855 | 818 | ||
856 | // Zerocode if needed | 819 | // Zerocode if needed |
@@ -993,7 +956,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
993 | { | 956 | { |
994 | bool highPriority = false; | 957 | bool highPriority = false; |
995 | 958 | ||
996 | if(zerocode) | 959 | if (zerocode) |
997 | buffer = ZeroEncode(buffer); | 960 | buffer = ZeroEncode(buffer); |
998 | 961 | ||
999 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) | 962 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) |
@@ -1012,49 +975,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1012 | SendPacketFinal(outgoingPacket); | 975 | SendPacketFinal(outgoingPacket); |
1013 | } | 976 | } |
1014 | 977 | ||
978 | public void SendUDPPacket(LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category) | ||
979 | { | ||
980 | bool highPriority = false; | ||
981 | |||
982 | if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) | ||
983 | { | ||
984 | category = (ThrottleOutPacketType)((int)category & 127); | ||
985 | highPriority = true; | ||
986 | } | ||
987 | |||
988 | OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); | ||
989 | |||
990 | // If we were not provided a method for handling unacked, use the UDPServer default method | ||
991 | if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0) | ||
992 | outgoingPacket.UnackedMethod = delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); }; | ||
993 | |||
994 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false, highPriority)) | ||
995 | SendPacketFinal(outgoingPacket); | ||
996 | } | ||
997 | |||
998 | static private readonly byte[] PacketAckHeader = new byte[] { | ||
999 | 0, | ||
1000 | 0, 0, 0, 0, // sequence number | ||
1001 | 0, // extra | ||
1002 | 0xff, 0xff, 0xff, 0xfb // ID 65531 (low frequency bigendian) | ||
1003 | }; | ||
1004 | |||
1015 | public void SendAcks(LLUDPClient udpClient) | 1005 | public void SendAcks(LLUDPClient udpClient) |
1016 | { | 1006 | { |
1017 | uint ack; | 1007 | if(udpClient.PendingAcks.Count == 0) |
1008 | return; | ||
1018 | 1009 | ||
1019 | if (udpClient.PendingAcks.Dequeue(out ack)) | 1010 | UDPPacketBuffer buf = GetNewUDPBuffer(udpClient.RemoteEndPoint); |
1011 | Buffer.BlockCopy(PacketAckHeader, 0, buf.Data, 0, 10); | ||
1012 | byte[] data = buf.Data; | ||
1013 | // count at position 10 | ||
1014 | int pos = 11; | ||
1015 | |||
1016 | uint ack; | ||
1017 | int count = 0; | ||
1018 | while (udpClient.PendingAcks.Dequeue(out ack)) | ||
1020 | { | 1019 | { |
1021 | List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); | 1020 | Utils.UIntToBytes(ack, data, pos); pos += 4; |
1022 | PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); | 1021 | ++count; |
1023 | block.ID = ack; | ||
1024 | blocks.Add(block); | ||
1025 | 1022 | ||
1026 | while (udpClient.PendingAcks.Dequeue(out ack)) | 1023 | if (count == 255) |
1027 | { | 1024 | { |
1028 | block = new PacketAckPacket.PacketsBlock(); | 1025 | data[10] = 255; |
1029 | block.ID = ack; | 1026 | buf.DataLength = pos; |
1030 | blocks.Add(block); | 1027 | SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown); |
1028 | |||
1029 | buf = GetNewUDPBuffer(udpClient.RemoteEndPoint); | ||
1030 | Buffer.BlockCopy(PacketAckHeader, 0, buf.Data, 0, 10); | ||
1031 | data = buf.Data; | ||
1032 | pos = 11; | ||
1033 | count = 0; | ||
1031 | } | 1034 | } |
1032 | 1035 | } | |
1033 | PacketAckPacket packet = new PacketAckPacket(); | 1036 | if (count > 0) |
1034 | packet.Header.Reliable = false; | 1037 | { |
1035 | packet.Packets = blocks.ToArray(); | 1038 | data[10] = (byte)count; |
1036 | 1039 | buf.DataLength = pos; | |
1037 | SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null); | 1040 | SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown); |
1038 | } | 1041 | } |
1039 | } | 1042 | } |
1040 | 1043 | ||
1044 | static private readonly byte[] StartPingCheckHeader = new byte[] { | ||
1045 | 0, | ||
1046 | 0, 0, 0, 0, // sequence number | ||
1047 | 0, // extra | ||
1048 | 1 // ID 1 (high frequency) | ||
1049 | }; | ||
1050 | |||
1041 | public void SendPing(LLUDPClient udpClient) | 1051 | public void SendPing(LLUDPClient udpClient) |
1042 | { | 1052 | { |
1043 | StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); | 1053 | UDPPacketBuffer buf = GetNewUDPBuffer(udpClient.RemoteEndPoint); |
1044 | 1054 | Buffer.BlockCopy(StartPingCheckHeader, 0, buf.Data, 0, 7); | |
1045 | pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++; | 1055 | byte[] data = buf.Data; |
1046 | // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit | 1056 | |
1047 | pc.PingID.OldestUnacked = 0; | 1057 | data[7] = udpClient.CurrentPingSequence++; |
1048 | 1058 | // older seq number of our un ack packets, so viewers could clean deduplication lists TODO | |
1049 | SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); | 1059 | //Utils.UIntToBytes(0, data, 8); |
1050 | udpClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount(); | 1060 | data[8] = 0; |
1061 | data[9] = 0; | ||
1062 | data[10] = 0; | ||
1063 | data[11] = 0; | ||
1064 | |||
1065 | buf.DataLength = 12; | ||
1066 | SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown); | ||
1067 | |||
1068 | udpClient.m_lastStartpingTimeMS = Util.GetTimeStampMS(); | ||
1051 | } | 1069 | } |
1052 | 1070 | ||
1071 | static private readonly byte[] CompletePingCheckHeader = new byte[] { | ||
1072 | 0, | ||
1073 | 0, 0, 0, 0, // sequence number | ||
1074 | 0, // extra | ||
1075 | 2 // ID 1 (high frequency) | ||
1076 | }; | ||
1077 | |||
1053 | public void CompletePing(LLUDPClient udpClient, byte pingID) | 1078 | public void CompletePing(LLUDPClient udpClient, byte pingID) |
1054 | { | 1079 | { |
1055 | CompletePingCheckPacket completePing = new CompletePingCheckPacket(); | 1080 | UDPPacketBuffer buf = GetNewUDPBuffer(udpClient.RemoteEndPoint); |
1056 | completePing.PingID.PingID = pingID; | 1081 | Buffer.BlockCopy(CompletePingCheckHeader, 0, buf.Data, 0, 7); |
1057 | SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); | 1082 | byte[] data = buf.Data; |
1083 | |||
1084 | data[7] = pingID; | ||
1085 | |||
1086 | buf.DataLength = 8; | ||
1087 | SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown); | ||
1058 | } | 1088 | } |
1059 | 1089 | ||
1060 | public void HandleUnacked(LLClientView client) | 1090 | public void HandleUnacked(LLClientView client) |
@@ -1090,13 +1120,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1090 | } | 1120 | } |
1091 | 1121 | ||
1092 | // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO | 1122 | // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO |
1093 | List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO); | 1123 | List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.m_RTO); |
1094 | 1124 | ||
1095 | if (expiredPackets != null) | 1125 | if (expiredPackets != null) |
1096 | { | 1126 | { |
1097 | //m_log.Debug("[LLUDPSERVER]: Handling " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); | ||
1098 | // Exponential backoff of the retransmission timeout | ||
1099 | udpClient.BackoffRTO(); | ||
1100 | for (int i = 0; i < expiredPackets.Count; ++i) | 1127 | for (int i = 0; i < expiredPackets.Count; ++i) |
1101 | expiredPackets[i].UnackedMethod(expiredPackets[i]); | 1128 | expiredPackets[i].UnackedMethod(expiredPackets[i]); |
1102 | } | 1129 | } |
@@ -1144,8 +1171,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1144 | 1171 | ||
1145 | int dataLength = buffer.DataLength; | 1172 | int dataLength = buffer.DataLength; |
1146 | 1173 | ||
1147 | // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here | 1174 | // only append acks on plain reliable messages |
1148 | if (!isZerocoded && !isResend && outgoingPacket.UnackedMethod == null) | 1175 | if (flags == Helpers.MSG_RELIABLE && outgoingPacket.UnackedMethod == null) |
1149 | { | 1176 | { |
1150 | // Keep appending ACKs until there is no room left in the buffer or there are | 1177 | // Keep appending ACKs until there is no room left in the buffer or there are |
1151 | // no more ACKs to append | 1178 | // no more ACKs to append |
@@ -1184,7 +1211,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1184 | // Stats tracking | 1211 | // Stats tracking |
1185 | Interlocked.Increment(ref udpClient.PacketsSent); | 1212 | Interlocked.Increment(ref udpClient.PacketsSent); |
1186 | PacketsSentCount++; | 1213 | PacketsSentCount++; |
1187 | |||
1188 | SyncSend(buffer); | 1214 | SyncSend(buffer); |
1189 | 1215 | ||
1190 | // Keep track of when this packet was sent out (right now) | 1216 | // Keep track of when this packet was sent out (right now) |
@@ -1315,11 +1341,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1315 | if (packet.Type == PacketType.UseCircuitCode) | 1341 | if (packet.Type == PacketType.UseCircuitCode) |
1316 | { | 1342 | { |
1317 | // And if there is a UseCircuitCode pending, also drop it | 1343 | // And if there is a UseCircuitCode pending, also drop it |
1344 | |||
1318 | lock (m_pendingCache) | 1345 | lock (m_pendingCache) |
1319 | { | 1346 | { |
1320 | if (m_pendingCache.Contains(endPoint)) | 1347 | if (m_pendingCache.Contains(endPoint)) |
1321 | { | 1348 | { |
1322 | FreeUDPBuffer(buffer); | 1349 | FreeUDPBuffer(buffer); |
1350 | SendAckImmediate(endPoint, packet.Header.Sequence); // i hear you shutup | ||
1323 | return; | 1351 | return; |
1324 | } | 1352 | } |
1325 | 1353 | ||
@@ -1328,6 +1356,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1328 | 1356 | ||
1329 | Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet }); | 1357 | Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet }); |
1330 | FreeUDPBuffer(buffer); | 1358 | FreeUDPBuffer(buffer); |
1359 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1331 | return; | 1360 | return; |
1332 | } | 1361 | } |
1333 | } | 1362 | } |
@@ -1482,11 +1511,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1482 | } | 1511 | } |
1483 | else if (packet.Type == PacketType.CompletePingCheck) | 1512 | else if (packet.Type == PacketType.CompletePingCheck) |
1484 | { | 1513 | { |
1485 | int t = Util.EnvironmentTickCountSubtract(udpClient.m_lastStartpingTimeMS); | 1514 | double t = Util.GetTimeStampMS() - udpClient.m_lastStartpingTimeMS; |
1486 | int c = udpClient.m_pingMS; | 1515 | double c = 0.8 * udpClient.m_pingMS; |
1487 | c = 800 * c + 200 * t; | 1516 | c += 0.2 * t; |
1488 | c /= 1000; | 1517 | int p = (int)c; |
1489 | udpClient.m_pingMS = c; | 1518 | udpClient.m_pingMS = p; |
1519 | udpClient.UpdateRoundTrip(p); | ||
1490 | return; | 1520 | return; |
1491 | } | 1521 | } |
1492 | 1522 | ||
@@ -1651,7 +1681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1651 | } | 1681 | } |
1652 | 1682 | ||
1653 | // Now we know we can handle more data | 1683 | // Now we know we can handle more data |
1654 | Thread.Sleep(200); | 1684 | //Thread.Sleep(200); |
1655 | 1685 | ||
1656 | // Obtain the pending queue and remove it from the cache | 1686 | // Obtain the pending queue and remove it from the cache |
1657 | Queue<UDPPacketBuffer> queue = null; | 1687 | Queue<UDPPacketBuffer> queue = null; |
@@ -1666,8 +1696,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1666 | m_pendingCache.Remove(endPoint); | 1696 | m_pendingCache.Remove(endPoint); |
1667 | } | 1697 | } |
1668 | 1698 | ||
1669 | client.CheckViewerCaps(); | ||
1670 | |||
1671 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); | 1699 | m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); |
1672 | // Reinject queued packets | 1700 | // Reinject queued packets |
1673 | while (queue.Count > 0) | 1701 | while (queue.Count > 0) |
@@ -1678,18 +1706,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1678 | 1706 | ||
1679 | queue = null; | 1707 | queue = null; |
1680 | 1708 | ||
1681 | // Send ack straight away to let the viewer know that the connection is active. | ||
1682 | // The client will be null if it already exists (e.g. if on a region crossing the client sends a use | ||
1683 | // circuit code to the existing child agent. This is not particularly obvious. | ||
1684 | SendAckImmediate(endPoint, uccp.Header.Sequence); | ||
1685 | |||
1686 | // We only want to send initial data to new clients, not ones which are being converted from child to root. | ||
1687 | if (client != null) | 1709 | if (client != null) |
1688 | { | 1710 | { |
1689 | bool tp = (aCircuit.teleportFlags > 0); | 1711 | if(aCircuit.teleportFlags <= 0) |
1690 | // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from | 1712 | client.SendRegionHandshake(); |
1691 | if (!tp) | ||
1692 | client.SceneAgent.SendInitialDataToMe(); | ||
1693 | } | 1713 | } |
1694 | } | 1714 | } |
1695 | else | 1715 | else |
@@ -1705,8 +1725,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1705 | } | 1725 | } |
1706 | 1726 | ||
1707 | // m_log.DebugFormat( | 1727 | // m_log.DebugFormat( |
1708 | // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", | 1728 | // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", |
1709 | // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); | 1729 | // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); |
1710 | 1730 | ||
1711 | } | 1731 | } |
1712 | catch (Exception e) | 1732 | catch (Exception e) |
@@ -1720,117 +1740,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1720 | e.StackTrace); | 1740 | e.StackTrace); |
1721 | } | 1741 | } |
1722 | } | 1742 | } |
1723 | /* | ||
1724 | protected void HandleCompleteMovementIntoRegion(object o) | ||
1725 | { | ||
1726 | IPEndPoint endPoint = null; | ||
1727 | IClientAPI client = null; | ||
1728 | |||
1729 | try | ||
1730 | { | ||
1731 | object[] array = (object[])o; | ||
1732 | endPoint = (IPEndPoint)array[0]; | ||
1733 | CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1]; | ||
1734 | |||
1735 | m_log.DebugFormat( | ||
1736 | "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, Scene.Name); | ||
1737 | |||
1738 | // Determine which agent this packet came from | ||
1739 | // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination | ||
1740 | // simulator with no existing child presence, the viewer (at least LL 3.3.4) will send UseCircuitCode | ||
1741 | // and then CompleteAgentMovement immediately without waiting for an ack. As we are now handling these | ||
1742 | // packets asynchronously, we need to account for this thread proceeding more quickly than the | ||
1743 | // UseCircuitCode thread. | ||
1744 | int count = 40; | ||
1745 | while (count-- > 0) | ||
1746 | { | ||
1747 | if (Scene.TryGetClient(endPoint, out client)) | ||
1748 | { | ||
1749 | if (!client.IsActive) | ||
1750 | { | ||
1751 | // This check exists to catch a condition where the client has been closed by another thread | ||
1752 | // but has not yet been removed from the client manager (and possibly a new connection has | ||
1753 | // not yet been established). | ||
1754 | m_log.DebugFormat( | ||
1755 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.", | ||
1756 | endPoint, client.Name, Scene.Name); | ||
1757 | } | ||
1758 | else if (client.SceneAgent == null) | ||
1759 | { | ||
1760 | // This check exists to catch a condition where the new client has been added to the client | ||
1761 | // manager but the SceneAgent has not yet been set in Scene.AddNewAgent(). If we are too | ||
1762 | // eager, then the new ScenePresence may not have registered a listener for this messsage | ||
1763 | // before we try to process it. | ||
1764 | // XXX: A better long term fix may be to add the SceneAgent before the client is added to | ||
1765 | // the client manager | ||
1766 | m_log.DebugFormat( | ||
1767 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.", | ||
1768 | endPoint, client.Name, Scene.Name); | ||
1769 | } | ||
1770 | else | ||
1771 | { | ||
1772 | break; | ||
1773 | } | ||
1774 | } | ||
1775 | else | ||
1776 | { | ||
1777 | m_log.DebugFormat( | ||
1778 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.", | ||
1779 | endPoint, Scene.Name); | ||
1780 | } | ||
1781 | |||
1782 | Thread.Sleep(200); | ||
1783 | } | ||
1784 | |||
1785 | if (client == null) | ||
1786 | { | ||
1787 | m_log.DebugFormat( | ||
1788 | "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.", | ||
1789 | endPoint, Scene.Name); | ||
1790 | |||
1791 | return; | ||
1792 | } | ||
1793 | else if (!client.IsActive || client.SceneAgent == null) | ||
1794 | { | ||
1795 | // This check exists to catch a condition where the client has been closed by another thread | ||
1796 | // but has not yet been removed from the client manager. | ||
1797 | // The packet could be simply ignored but it is useful to know if this condition occurred for other debugging | ||
1798 | // purposes. | ||
1799 | m_log.DebugFormat( | ||
1800 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.", | ||
1801 | endPoint, client.Name, Scene.Name); | ||
1802 | |||
1803 | return; | ||
1804 | } | ||
1805 | |||
1806 | IncomingPacket incomingPacket1; | ||
1807 | |||
1808 | // Inbox insertion | ||
1809 | if (UsePools) | ||
1810 | { | ||
1811 | incomingPacket1 = m_incomingPacketPool.GetObject(); | ||
1812 | incomingPacket1.Client = (LLClientView)client; | ||
1813 | incomingPacket1.Packet = packet; | ||
1814 | } | ||
1815 | else | ||
1816 | { | ||
1817 | incomingPacket1 = new IncomingPacket((LLClientView)client, packet); | ||
1818 | } | ||
1819 | |||
1820 | packetInbox.Enqueue(incomingPacket1); | ||
1821 | } | ||
1822 | catch (Exception e) | ||
1823 | { | ||
1824 | m_log.ErrorFormat( | ||
1825 | "[LLUDPSERVER]: CompleteAgentMovement handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", | ||
1826 | endPoint != null ? endPoint.ToString() : "n/a", | ||
1827 | client != null ? client.Name : "unknown", | ||
1828 | client != null ? client.AgentId.ToString() : "unknown", | ||
1829 | e.Message, | ||
1830 | e.StackTrace); | ||
1831 | } | ||
1832 | } | ||
1833 | */ | ||
1834 | 1743 | ||
1835 | /// <summary> | 1744 | /// <summary> |
1836 | /// Send an ack immediately to the given endpoint. | 1745 | /// Send an ack immediately to the given endpoint. |
@@ -1898,7 +1807,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1898 | { | 1807 | { |
1899 | if (Scene.TryGetClient(agentID, out client)) | 1808 | if (Scene.TryGetClient(agentID, out client)) |
1900 | { | 1809 | { |
1901 | if (client.SceneAgent != null) | 1810 | if (client.SceneAgent != null && |
1811 | client.CircuitCode == circuitCode && | ||
1812 | client.SessionId == sessionID && | ||
1813 | client.RemoteEndPoint == remoteEndPoint && | ||
1814 | client.SceneAgent.ControllingClient.SecureSessionId == sessionInfo.LoginInfo.SecureSession) | ||
1902 | return client; | 1815 | return client; |
1903 | Scene.CloseAgent(agentID, true); | 1816 | Scene.CloseAgent(agentID, true); |
1904 | } | 1817 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs index 8ed2cf1..0b008a9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Text; | ||
29 | using OpenSim.Framework; | 30 | using OpenSim.Framework; |
30 | using Nini.Config; | 31 | using Nini.Config; |
31 | using OpenMetaverse; | 32 | using OpenMetaverse; |
@@ -275,5 +276,86 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
275 | v.ToBytes(m_tmp, 0); | 276 | v.ToBytes(m_tmp, 0); |
276 | AddBytes(m_tmp, 16); | 277 | AddBytes(m_tmp, 16); |
277 | } | 278 | } |
279 | |||
280 | // maxlen <= 255 and includes null termination byte | ||
281 | public void AddShortString(string str, int maxlen) | ||
282 | { | ||
283 | if (String.IsNullOrEmpty(str)) | ||
284 | { | ||
285 | AddZeros(1); | ||
286 | return; | ||
287 | } | ||
288 | |||
289 | --maxlen; // account for null term | ||
290 | bool NullTerm = str.EndsWith("\0"); | ||
291 | |||
292 | byte[] data = Util.UTF8.GetBytes(str); | ||
293 | int len = data.Length; | ||
294 | if(NullTerm) | ||
295 | --len; | ||
296 | |||
297 | if(len <= maxlen) | ||
298 | { | ||
299 | AddByte((byte)(len + 1)); | ||
300 | AddBytes(data, len); | ||
301 | AddZeros(1); | ||
302 | return; | ||
303 | } | ||
304 | |||
305 | if ((data[maxlen] & 0x80) != 0) | ||
306 | { | ||
307 | while (maxlen > 0 && (data[maxlen] & 0xc0) != 0xc0) | ||
308 | maxlen--; | ||
309 | } | ||
310 | AddByte((byte)(maxlen + 1)); | ||
311 | AddBytes(data, maxlen); | ||
312 | AddZeros(1); | ||
313 | } | ||
314 | // maxlen <= 255 and includes null termination byte, maxchars == max len of utf8 source | ||
315 | public void AddShortString(string str, int maxchars, int maxlen) | ||
316 | { | ||
317 | if (String.IsNullOrEmpty(str)) | ||
318 | { | ||
319 | AddZeros(1); | ||
320 | return; | ||
321 | } | ||
322 | |||
323 | --maxlen; // account for null term | ||
324 | bool NullTerm = false; | ||
325 | byte[] data; | ||
326 | |||
327 | if (str.Length > maxchars) | ||
328 | { | ||
329 | data = Util.UTF8.GetBytes(str.Substring(0,maxchars)); | ||
330 | } | ||
331 | else | ||
332 | { | ||
333 | NullTerm = str.EndsWith("\0"); | ||
334 | data = Util.UTF8.GetBytes(str); | ||
335 | } | ||
336 | |||
337 | int len = data.Length; | ||
338 | if (NullTerm) | ||
339 | --len; | ||
340 | |||
341 | if (len <= maxlen) | ||
342 | { | ||
343 | AddByte((byte)(len + 1)); | ||
344 | AddBytes(data, len); | ||
345 | AddZeros(1); | ||
346 | return; | ||
347 | } | ||
348 | |||
349 | if ((data[maxlen] & 0x80) != 0) | ||
350 | { | ||
351 | while (maxlen > 0 && (data[maxlen] & 0xc0) != 0xc0) | ||
352 | maxlen--; | ||
353 | } | ||
354 | |||
355 | AddByte((byte)(maxlen + 1)); | ||
356 | AddBytes(data, maxlen); | ||
357 | AddZeros(1); | ||
358 | } | ||
359 | |||
278 | } | 360 | } |
279 | } | 361 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs index 3277638..707acdd 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs | |||
@@ -67,7 +67,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
67 | public Int64 MinimumAdaptiveThrottleRate; | 67 | public Int64 MinimumAdaptiveThrottleRate; |
68 | 68 | ||
69 | public int ClientMaxRate; | 69 | public int ClientMaxRate; |
70 | public float BrustTime; | 70 | public float BurstTime; |
71 | 71 | ||
72 | /// <summary> | 72 | /// <summary> |
73 | /// Default constructor | 73 | /// Default constructor |
@@ -94,8 +94,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
94 | if (ClientMaxRate > 1000000) | 94 | if (ClientMaxRate > 1000000) |
95 | ClientMaxRate = 1000000; // no more than 8Mbps | 95 | ClientMaxRate = 1000000; // no more than 8Mbps |
96 | 96 | ||
97 | BrustTime = (float)throttleConfig.GetInt("client_throttle_burtsTimeMS", 10); | 97 | BurstTime = (float)throttleConfig.GetInt("client_throttle_burtsTimeMS", 10); |
98 | BrustTime *= 1e-3f; | 98 | BurstTime *= 1e-3f; |
99 | 99 | ||
100 | // Adaptive is broken | 100 | // Adaptive is broken |
101 | // AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); | 101 | // AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs index 1daf091..1bf05a3 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs | |||
@@ -45,22 +45,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
45 | 45 | ||
46 | private static Int32 m_counter = 0; | 46 | private static Int32 m_counter = 0; |
47 | 47 | ||
48 | // private Int32 m_identifier; | ||
49 | |||
50 | protected const float m_timeScale = 1e-3f; | 48 | protected const float m_timeScale = 1e-3f; |
51 | 49 | ||
52 | /// <summary> | 50 | /// <summary> |
53 | /// This is the number of m_minimumDripRate bytes | 51 | /// minimum recovery rate, ie bandwith |
54 | /// allowed in a burst | ||
55 | /// roughtly, with this settings, the maximum time system will take | ||
56 | /// to recheck a bucket in ms | ||
57 | /// | ||
58 | /// </summary> | 52 | /// </summary> |
59 | protected const float m_quantumsPerBurst = 5; | 53 | protected const float MINDRIPRATE = 500; |
60 | 54 | ||
61 | /// <summary> | 55 | // minimum and maximim burst size, ie max number of bytes token can have |
62 | /// </summary> | 56 | protected const float MINBURST = 1500; // can't be less than one MTU or it will block |
63 | protected const float m_minimumDripRate = 1500; | 57 | protected const float MAXBURST = 7500; |
64 | 58 | ||
65 | /// <summary>Time of the last drip</summary> | 59 | /// <summary>Time of the last drip</summary> |
66 | protected double m_lastDrip; | 60 | protected double m_lastDrip; |
@@ -109,10 +103,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
109 | get { return m_burst; } | 103 | get { return m_burst; } |
110 | set { | 104 | set { |
111 | float rate = (value < 0 ? 0 : value); | 105 | float rate = (value < 0 ? 0 : value); |
112 | if (rate < 1.5f * m_minimumDripRate) | 106 | if (rate < MINBURST) |
113 | rate = 1.5f * m_minimumDripRate; | 107 | rate = MINBURST; |
114 | else if (rate > m_minimumDripRate * m_quantumsPerBurst) | 108 | else if (rate > MAXBURST) |
115 | rate = m_minimumDripRate * m_quantumsPerBurst; | 109 | rate = MAXBURST; |
116 | 110 | ||
117 | m_burst = rate; | 111 | m_burst = rate; |
118 | } | 112 | } |
@@ -122,8 +116,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
122 | { | 116 | { |
123 | get { | 117 | get { |
124 | float rate = RequestedBurst * BurstModifier(); | 118 | float rate = RequestedBurst * BurstModifier(); |
125 | if (rate < m_minimumDripRate) | 119 | if (rate < MINBURST) |
126 | rate = m_minimumDripRate; | 120 | rate = MINBURST; |
127 | return (float)rate; | 121 | return (float)rate; |
128 | } | 122 | } |
129 | } | 123 | } |
@@ -159,8 +153,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
159 | return rate; | 153 | return rate; |
160 | 154 | ||
161 | rate *= m_parent.DripRateModifier(); | 155 | rate *= m_parent.DripRateModifier(); |
162 | if (rate < m_minimumDripRate) | 156 | if (rate < MINDRIPRATE) |
163 | rate = m_minimumDripRate; | 157 | rate = MINDRIPRATE; |
164 | 158 | ||
165 | return (float)rate; | 159 | return (float)rate; |
166 | } | 160 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs index 1f978e1..32a6c40 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs | |||
@@ -215,14 +215,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
215 | // As with other network applications, assume that an acknowledged packet is an | 215 | // As with other network applications, assume that an acknowledged packet is an |
216 | // indication that the network can handle a little more load, speed up the transmission | 216 | // indication that the network can handle a little more load, speed up the transmission |
217 | ackedPacket.Client.FlowThrottle.AcknowledgePackets(1); | 217 | ackedPacket.Client.FlowThrottle.AcknowledgePackets(1); |
218 | |||
219 | if (!pendingAcknowledgement.FromResend) | ||
220 | { | ||
221 | // Calculate the round-trip time for this packet and its ACK | ||
222 | int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount; | ||
223 | if (rtt > 0) | ||
224 | ackedPacket.Client.UpdateRoundTrip(rtt); | ||
225 | } | ||
226 | } | 218 | } |
227 | else | 219 | else |
228 | { | 220 | { |
diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs index 1b6401a..56123a5 100644 --- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs +++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs | |||
@@ -50,8 +50,8 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
50 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 50 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
51 | 51 | ||
52 | private object timeTickLock = new object(); | 52 | private object timeTickLock = new object(); |
53 | private double lastTimeTick = 0.0; | 53 | private int lastTimeTick = 0; |
54 | private double lastFilesExpire = 0.0; | 54 | private int lastFilesExpire = 0; |
55 | private bool inTimeTick = false; | 55 | private bool inTimeTick = false; |
56 | 56 | ||
57 | public struct XferRequest | 57 | public struct XferRequest |
@@ -66,15 +66,15 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
66 | { | 66 | { |
67 | public byte[] Data; | 67 | public byte[] Data; |
68 | public int refsCount; | 68 | public int refsCount; |
69 | public double timeStampMS; | 69 | public int timeStampMS; |
70 | } | 70 | } |
71 | 71 | ||
72 | #region INonSharedRegionModule Members | 72 | #region INonSharedRegionModule Members |
73 | 73 | ||
74 | public void Initialise(IConfigSource config) | 74 | public void Initialise(IConfigSource config) |
75 | { | 75 | { |
76 | lastTimeTick = Util.GetTimeStampMS() + 30000.0; | 76 | lastTimeTick = (int)Util.GetTimeStampMS() + 30000; |
77 | lastFilesExpire = lastTimeTick + 180000.0; | 77 | lastFilesExpire = lastTimeTick + 180000; |
78 | } | 78 | } |
79 | 79 | ||
80 | public void AddRegion(Scene scene) | 80 | public void AddRegion(Scene scene) |
@@ -121,10 +121,9 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
121 | { | 121 | { |
122 | if(!inTimeTick) | 122 | if(!inTimeTick) |
123 | { | 123 | { |
124 | double now = Util.GetTimeStampMS(); | 124 | int now = (int)Util.GetTimeStampMS(); |
125 | if(now - lastTimeTick > 1750.0) | 125 | if(now - lastTimeTick > 750) |
126 | { | 126 | { |
127 | |||
128 | if(Transfers.Count == 0 && NewFiles.Count == 0) | 127 | if(Transfers.Count == 0 && NewFiles.Count == 0) |
129 | lastTimeTick = now; | 128 | lastTimeTick = now; |
130 | else | 129 | else |
@@ -163,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
163 | { | 162 | { |
164 | lock (NewFiles) | 163 | lock (NewFiles) |
165 | { | 164 | { |
166 | double now = Util.GetTimeStampMS(); | 165 | int now = (int)Util.GetTimeStampMS(); |
167 | if (NewFiles.ContainsKey(fileName)) | 166 | if (NewFiles.ContainsKey(fileName)) |
168 | { | 167 | { |
169 | NewFiles[fileName].refsCount++; | 168 | NewFiles[fileName].refsCount++; |
@@ -183,18 +182,18 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
183 | } | 182 | } |
184 | 183 | ||
185 | #endregion | 184 | #endregion |
186 | public void expireFiles(double now) | 185 | public void expireFiles(int now) |
187 | { | 186 | { |
188 | lock (NewFiles) | 187 | lock (NewFiles) |
189 | { | 188 | { |
190 | // hopefully we will not have many files so nasty code will do it | 189 | // hopefully we will not have many files so nasty code will do it |
191 | if(now - lastFilesExpire > 120000.0) | 190 | if(now - lastFilesExpire > 120000) |
192 | { | 191 | { |
193 | lastFilesExpire = now; | 192 | lastFilesExpire = now; |
194 | List<string> expires = new List<string>(); | 193 | List<string> expires = new List<string>(); |
195 | foreach(string fname in NewFiles.Keys) | 194 | foreach(string fname in NewFiles.Keys) |
196 | { | 195 | { |
197 | if(NewFiles[fname].refsCount == 0 && now - NewFiles[fname].timeStampMS > 120000.0) | 196 | if(NewFiles[fname].refsCount == 0 && now - NewFiles[fname].timeStampMS > 120000) |
198 | expires.Add(fname); | 197 | expires.Add(fname); |
199 | } | 198 | } |
200 | foreach(string fname in expires) | 199 | foreach(string fname in expires) |
@@ -230,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
230 | } | 229 | } |
231 | } | 230 | } |
232 | 231 | ||
233 | public void transfersTimeTick(double now) | 232 | public void transfersTimeTick(int now) |
234 | { | 233 | { |
235 | XferDownLoad[] xfrs; | 234 | XferDownLoad[] xfrs; |
236 | lock(Transfers) | 235 | lock(Transfers) |
@@ -241,6 +240,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
241 | xfrs = new XferDownLoad[Transfers.Count]; | 240 | xfrs = new XferDownLoad[Transfers.Count]; |
242 | Transfers.Values.CopyTo(xfrs,0); | 241 | Transfers.Values.CopyTo(xfrs,0); |
243 | } | 242 | } |
243 | |||
244 | foreach(XferDownLoad xfr in xfrs) | 244 | foreach(XferDownLoad xfr in xfrs) |
245 | { | 245 | { |
246 | if(xfr.checkTime(now)) | 246 | if(xfr.checkTime(now)) |
@@ -272,14 +272,15 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
272 | if (!Transfers.ContainsKey(xferID)) | 272 | if (!Transfers.ContainsKey(xferID)) |
273 | { | 273 | { |
274 | byte[] fileData = NewFiles[fileName].Data; | 274 | byte[] fileData = NewFiles[fileName].Data; |
275 | int burstSize = remoteClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset) >> 11; | 275 | int burstSize = remoteClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Task) >> 10; |
276 | if(Transfers.Count > 1) | 276 | burstSize *= remoteClient.PingTimeMS; |
277 | burstSize /= Transfers.Count; | 277 | burstSize >>= 10; // ping is ms, 1 round trip |
278 | if(burstSize > 32) | ||
279 | burstSize = 32; | ||
278 | XferDownLoad transaction = | 280 | XferDownLoad transaction = |
279 | new XferDownLoad(fileName, fileData, xferID, remoteClient, burstSize); | 281 | new XferDownLoad(fileName, fileData, xferID, remoteClient, burstSize); |
280 | 282 | ||
281 | Transfers.Add(xferID, transaction); | 283 | Transfers.Add(xferID, transaction); |
282 | |||
283 | transaction.StartSend(); | 284 | transaction.StartSend(); |
284 | 285 | ||
285 | // The transaction for this file is on its way | 286 | // The transaction for this file is on its way |
@@ -320,27 +321,27 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
320 | 321 | ||
321 | public class XferDownLoad | 322 | public class XferDownLoad |
322 | { | 323 | { |
323 | public IClientAPI Client; | 324 | public IClientAPI remoteClient; |
324 | public byte[] Data = new byte[0]; | 325 | public byte[] Data = new byte[0]; |
325 | public string FileName = String.Empty; | 326 | public string FileName = String.Empty; |
326 | public ulong XferID = 0; | 327 | public ulong XferID = 0; |
327 | public bool isDeleted = false; | 328 | public bool isDeleted = false; |
328 | 329 | ||
329 | private object myLock = new object(); | 330 | private object myLock = new object(); |
330 | private double lastsendTimeMS; | 331 | private int lastACKTimeMS; |
331 | private int LastPacket; | 332 | private int LastPacket; |
332 | private int lastBytes; | 333 | private int lastBytes; |
333 | private int lastSentPacket; | 334 | private int lastSentPacket; |
334 | private int lastAckPacket; | 335 | private int lastAckPacket; |
335 | private int burstSize; | 336 | private int burstSize; // additional packets, so can be zero |
336 | private int retries = 0; | 337 | private int retries; |
337 | 338 | ||
338 | public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client, int burstsz) | 339 | public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client, int burstsz) |
339 | { | 340 | { |
340 | FileName = fileName; | 341 | FileName = fileName; |
341 | Data = data; | 342 | Data = data; |
342 | XferID = xferID; | 343 | XferID = xferID; |
343 | Client = client; | 344 | remoteClient = client; |
344 | burstSize = burstsz; | 345 | burstSize = burstsz; |
345 | } | 346 | } |
346 | 347 | ||
@@ -352,7 +353,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
352 | { | 353 | { |
353 | if(!isDeleted) | 354 | if(!isDeleted) |
354 | { | 355 | { |
355 | Data = new byte[0]; | 356 | Data = null; |
356 | isDeleted = true; | 357 | isDeleted = true; |
357 | } | 358 | } |
358 | } | 359 | } |
@@ -381,30 +382,29 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
381 | lastBytes = 1024; | 382 | lastBytes = 1024; |
382 | LastPacket--; | 383 | LastPacket--; |
383 | } | 384 | } |
384 | |||
385 | } | 385 | } |
386 | 386 | ||
387 | lastAckPacket = -1; | 387 | lastAckPacket = -1; |
388 | lastSentPacket = -1; | 388 | lastSentPacket = -1; |
389 | retries = 0; | ||
389 | 390 | ||
390 | double now = Util.GetTimeStampMS(); | 391 | SendBurst(); |
391 | |||
392 | SendBurst(now); | ||
393 | return; | 392 | return; |
394 | } | 393 | } |
395 | } | 394 | } |
396 | 395 | ||
397 | private void SendBurst(double now) | 396 | private void SendBurst() |
398 | { | 397 | { |
399 | int start = lastAckPacket + 1; | 398 | int start = lastAckPacket + 1; |
400 | int end = start + burstSize; | 399 | int end = start + burstSize; |
401 | if (end > LastPacket) | 400 | if (end > LastPacket) |
402 | end = LastPacket; | 401 | end = LastPacket; |
403 | while(start <= end) | 402 | while (start <= end) |
404 | SendPacket(start++ , now); | 403 | SendPacket(start++); |
404 | lastACKTimeMS = (int)Util.GetTimeStampMS() + 1000; // reset timeout with some slack for queues delays | ||
405 | } | 405 | } |
406 | 406 | ||
407 | private void SendPacket(int pkt, double now) | 407 | private void SendPacket(int pkt) |
408 | { | 408 | { |
409 | if(pkt > LastPacket) | 409 | if(pkt > LastPacket) |
410 | return; | 410 | return; |
@@ -422,23 +422,9 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
422 | pktid = (uint)pkt; | 422 | pktid = (uint)pkt; |
423 | } | 423 | } |
424 | 424 | ||
425 | byte[] transferData; | 425 | remoteClient.SendXferPacket(XferID, pktid, Data, pkt << 10, pktsize, true); |
426 | if(pkt == 0) | ||
427 | { | ||
428 | transferData = new byte[pktsize + 4]; | ||
429 | Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); | ||
430 | Array.Copy(Data, 0, transferData, 4, pktsize); | ||
431 | } | ||
432 | else | ||
433 | { | ||
434 | transferData = new byte[pktsize]; | ||
435 | Array.Copy(Data, pkt << 10, transferData, 0, pktsize); | ||
436 | } | ||
437 | |||
438 | Client.SendXferPacket(XferID, pktid, transferData, false); | ||
439 | 426 | ||
440 | lastSentPacket = pkt; | 427 | lastSentPacket = pkt; |
441 | lastsendTimeMS = now; | ||
442 | } | 428 | } |
443 | 429 | ||
444 | /// <summary> | 430 | /// <summary> |
@@ -453,39 +439,49 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer | |||
453 | if(isDeleted) | 439 | if(isDeleted) |
454 | return true; | 440 | return true; |
455 | 441 | ||
456 | packet &= 0x7fffffff; | 442 | packet &= 0x7fffffff; |
457 | if(lastAckPacket < packet) | 443 | if (lastAckPacket < packet) |
458 | lastAckPacket = (int)packet; | 444 | lastAckPacket = (int)packet; |
459 | 445 | else if (lastAckPacket == LastPacket) | |
460 | if(lastAckPacket == LastPacket) | ||
461 | { | 446 | { |
462 | done(); | 447 | done(); |
463 | return true; | 448 | return true; |
464 | } | 449 | } |
465 | double now = Util.GetTimeStampMS(); | 450 | |
466 | SendPacket(lastSentPacket + 1, now); | 451 | lastACKTimeMS = (int)Util.GetTimeStampMS(); |
452 | retries = 0; | ||
453 | SendPacket(lastSentPacket + 1); | ||
467 | return false; | 454 | return false; |
468 | } | 455 | } |
469 | } | 456 | } |
470 | 457 | ||
471 | public bool checkTime(double now) | 458 | public bool checkTime(int now) |
472 | { | 459 | { |
473 | if(Monitor.TryEnter(myLock)) | 460 | if (Monitor.TryEnter(myLock)) |
474 | { | 461 | { |
475 | if(!isDeleted) | 462 | if (!isDeleted) |
476 | { | 463 | { |
477 | double timeMS = now - lastsendTimeMS; | 464 | int timeMS = now - lastACKTimeMS; |
478 | if(timeMS > 60000.0) | 465 | int tout = 5 * remoteClient.PingTimeMS; |
479 | done(); | 466 | if (tout < 1000) |
480 | else if(timeMS > 3500.0 && retries++ < 3) | 467 | tout = 1000; |
468 | else if(tout > 10000) | ||
469 | tout = 10000; | ||
470 | |||
471 | if (timeMS > tout) | ||
481 | { | 472 | { |
482 | burstSize >>= 1; | 473 | if (++retries > 4) |
483 | SendBurst(now); | 474 | done(); |
475 | else | ||
476 | { | ||
477 | burstSize = lastSentPacket - lastAckPacket; | ||
478 | SendBurst(); | ||
479 | } | ||
484 | } | 480 | } |
485 | } | 481 | } |
486 | 482 | bool isdel = isDeleted; | |
487 | Monitor.Exit(myLock); | 483 | Monitor.Exit(myLock); |
488 | return isDeleted; | 484 | return isdel; |
489 | } | 485 | } |
490 | return false; | 486 | return false; |
491 | } | 487 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs index 5457dc3..e63629e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs | |||
@@ -142,8 +142,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests | |||
142 | 142 | ||
143 | // We must update the scenes in order to make the root new root agents trigger position updates in their | 143 | // We must update the scenes in order to make the root new root agents trigger position updates in their |
144 | // children. | 144 | // children. |
145 | sceneWest.Update(1); | 145 | sceneWest.Update(4); |
146 | sceneEast.Update(1); | 146 | sceneEast.Update(4); |
147 | sp1.DrawDistance += 64; | ||
148 | sp2.DrawDistance += 64; | ||
149 | sceneWest.Update(2); | ||
150 | sceneEast.Update(2); | ||
147 | 151 | ||
148 | // Check child positions are correct. | 152 | // Check child positions are correct. |
149 | Assert.AreEqual( | 153 | Assert.AreEqual( |
@@ -233,8 +237,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat.Tests | |||
233 | 237 | ||
234 | // We must update the scenes in order to make the root new root agents trigger position updates in their | 238 | // We must update the scenes in order to make the root new root agents trigger position updates in their |
235 | // children. | 239 | // children. |
236 | sceneNorth.Update(1); | 240 | sceneNorth.Update(4); |
237 | sceneSouth.Update(1); | 241 | sceneSouth.Update(4); |
242 | sp1.DrawDistance += 64; | ||
243 | sp2.DrawDistance += 64; | ||
244 | sceneNorth.Update(2); | ||
245 | sceneSouth.Update(2); | ||
238 | 246 | ||
239 | // Check child positions are correct. | 247 | // Check child positions are correct. |
240 | Assert.AreEqual( | 248 | Assert.AreEqual( |
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 772485c..39bf46c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | |||
@@ -256,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
256 | 256 | ||
257 | private void OnMakeRootAgent(ScenePresence sp) | 257 | private void OnMakeRootAgent(ScenePresence sp) |
258 | { | 258 | { |
259 | if(sp.gotCrossUpdate) | 259 | if(sp.m_gotCrossUpdate) |
260 | return; | 260 | return; |
261 | 261 | ||
262 | RecacheFriends(sp.ControllingClient); | 262 | RecacheFriends(sp.ControllingClient); |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 9471c90..187df31 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -54,15 +54,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 54 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
55 | private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]"; | 55 | private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]"; |
56 | 56 | ||
57 | public const int DefaultMaxTransferDistance = 4095; | ||
58 | public const bool WaitForAgentArrivedAtDestinationDefault = true; | 57 | public const bool WaitForAgentArrivedAtDestinationDefault = true; |
59 | 58 | ||
60 | /// <summary> | 59 | /// <summary> |
61 | /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. | ||
62 | /// </summary> | ||
63 | public int MaxTransferDistance { get; set; } | ||
64 | |||
65 | /// <summary> | ||
66 | /// If true then on a teleport, the source region waits for a callback from the destination region. If | 60 | /// If true then on a teleport, the source region waits for a callback from the destination region. If |
67 | /// a callback fails to arrive within a set time then the user is pulled back into the source region. | 61 | /// a callback fails to arrive within a set time then the user is pulled back into the source region. |
68 | /// </summary> | 62 | /// </summary> |
@@ -227,11 +221,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
227 | WaitForAgentArrivedAtDestination | 221 | WaitForAgentArrivedAtDestination |
228 | = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); | 222 | = transferConfig.GetBoolean("wait_for_callback", WaitForAgentArrivedAtDestinationDefault); |
229 | 223 | ||
230 | MaxTransferDistance = transferConfig.GetInt("max_distance", DefaultMaxTransferDistance); | ||
231 | } | ||
232 | else | ||
233 | { | ||
234 | MaxTransferDistance = DefaultMaxTransferDistance; | ||
235 | } | 224 | } |
236 | 225 | ||
237 | m_entityTransferStateMachine = new EntityTransferStateMachine(this); | 226 | m_entityTransferStateMachine = new EntityTransferStateMachine(this); |
@@ -640,29 +629,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
640 | } | 629 | } |
641 | 630 | ||
642 | /// <summary> | 631 | /// <summary> |
643 | /// Determines whether this instance is within the max transfer distance. | ||
644 | /// </summary> | ||
645 | /// <param name="sourceRegion"></param> | ||
646 | /// <param name="destRegion"></param> | ||
647 | /// <returns> | ||
648 | /// <c>true</c> if this instance is within max transfer distance; otherwise, <c>false</c>. | ||
649 | /// </returns> | ||
650 | private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion) | ||
651 | { | ||
652 | if(MaxTransferDistance == 0) | ||
653 | return true; | ||
654 | |||
655 | // m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); | ||
656 | // | ||
657 | // m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", | ||
658 | // destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI); | ||
659 | |||
660 | // Insanely, RegionLoc on RegionInfo is the 256m map co-ord whilst GridRegion.RegionLoc is the raw meters position. | ||
661 | return Math.Abs(sourceRegion.RegionLocX - destRegion.RegionCoordX) <= MaxTransferDistance | ||
662 | && Math.Abs(sourceRegion.RegionLocY - destRegion.RegionCoordY) <= MaxTransferDistance; | ||
663 | } | ||
664 | |||
665 | /// <summary> | ||
666 | /// Wraps DoTeleportInternal() and manages the transfer state. | 632 | /// Wraps DoTeleportInternal() and manages the transfer state. |
667 | /// </summary> | 633 | /// </summary> |
668 | public void DoTeleport( | 634 | public void DoTeleport( |
@@ -722,18 +688,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
722 | 688 | ||
723 | RegionInfo sourceRegion = sp.Scene.RegionInfo; | 689 | RegionInfo sourceRegion = sp.Scene.RegionInfo; |
724 | 690 | ||
725 | if (!IsWithinMaxTeleportDistance(sourceRegion, finalDestination)) | ||
726 | { | ||
727 | sp.ControllingClient.SendTeleportFailed( | ||
728 | string.Format( | ||
729 | "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way", | ||
730 | finalDestination.RegionName, finalDestination.RegionCoordX, finalDestination.RegionCoordY, | ||
731 | sourceRegion.RegionName, sourceRegion.RegionLocX, sourceRegion.RegionLocY, | ||
732 | MaxTransferDistance)); | ||
733 | |||
734 | return; | ||
735 | } | ||
736 | |||
737 | ulong destinationHandle = finalDestination.RegionHandle; | 691 | ulong destinationHandle = finalDestination.RegionHandle; |
738 | 692 | ||
739 | // Let's do DNS resolution only once in this process, please! | 693 | // Let's do DNS resolution only once in this process, please! |
@@ -1103,6 +1057,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1103 | } | 1057 | } |
1104 | } | 1058 | } |
1105 | } | 1059 | } |
1060 | else | ||
1061 | { | ||
1062 | if(!sp.IsInLocalTransit || sp.RegionViewDistance == 0) | ||
1063 | { | ||
1064 | // this will be closed by callback | ||
1065 | if (agentCircuit.ChildrenCapSeeds != null) | ||
1066 | agentCircuit.ChildrenCapSeeds.Remove(sp.RegionHandle); | ||
1067 | } | ||
1068 | } | ||
1106 | 1069 | ||
1107 | string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);; | 1070 | string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);; |
1108 | 1071 | ||
@@ -1175,7 +1138,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1175 | 1138 | ||
1176 | agent.SenderWantsToWaitForRoot = true; | 1139 | agent.SenderWantsToWaitForRoot = true; |
1177 | 1140 | ||
1178 | //SetCallbackURL(agent, sp.Scene.RegionInfo); | 1141 | if(!sp.IsInLocalTransit || sp.RegionViewDistance == 0) |
1142 | SetNewCallbackURL(agent, sp.Scene.RegionInfo); | ||
1179 | 1143 | ||
1180 | // Reset the do not close flag. This must be done before the destination opens child connections (here | 1144 | // Reset the do not close flag. This must be done before the destination opens child connections (here |
1181 | // triggered by UpdateAgent) to avoid race conditions. However, we also want to reset it as late as possible | 1145 | // triggered by UpdateAgent) to avoid race conditions. However, we also want to reset it as late as possible |
@@ -1183,11 +1147,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1183 | // in no close. | 1147 | // in no close. |
1184 | sp.DoNotCloseAfterTeleport = false; | 1148 | sp.DoNotCloseAfterTeleport = false; |
1185 | 1149 | ||
1150 | // we still need to flag this as child here | ||
1151 | // a close from receiving region seems possible to happen before we reach sp.MakeChildAgent below | ||
1152 | // causing the agent to be loggout out from grid incorrectly | ||
1153 | sp.IsChildAgent = true; | ||
1186 | // Send the Update. If this returns true, we know the client has contacted the destination | 1154 | // Send the Update. If this returns true, we know the client has contacted the destination |
1187 | // via CompleteMovementIntoRegion, so we can let go. | 1155 | // via CompleteMovementIntoRegion, so we can let go. |
1188 | // If it returns false, something went wrong, and we need to abort. | 1156 | // If it returns false, something went wrong, and we need to abort. |
1189 | if (!UpdateAgent(reg, finalDestination, agent, sp, ctx)) | 1157 | if (!UpdateAgent(reg, finalDestination, agent, sp, ctx)) |
1190 | { | 1158 | { |
1159 | sp.IsChildAgent = false; | ||
1191 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | 1160 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) |
1192 | { | 1161 | { |
1193 | m_interRegionTeleportAborts.Value++; | 1162 | m_interRegionTeleportAborts.Value++; |
@@ -1208,7 +1177,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1208 | return; | 1177 | return; |
1209 | } | 1178 | } |
1210 | 1179 | ||
1211 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 1180 | //shut this up for now |
1181 | m_entityTransferStateMachine.ResetFromTransit(sp.UUID); | ||
1182 | |||
1183 | //m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | ||
1212 | 1184 | ||
1213 | sp.HasMovedAway(!(OutSideViewRange || logout)); | 1185 | sp.HasMovedAway(!(OutSideViewRange || logout)); |
1214 | 1186 | ||
@@ -1224,25 +1196,33 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1224 | sp.closeAllChildAgents(); | 1196 | sp.closeAllChildAgents(); |
1225 | else | 1197 | else |
1226 | sp.CloseChildAgents(childRegionsToClose); | 1198 | sp.CloseChildAgents(childRegionsToClose); |
1199 | } | ||
1227 | 1200 | ||
1228 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone | 1201 | |
1229 | // goes by HG hook | 1202 | // if far jump we do need to close anyways |
1230 | if (NeedsClosing(reg, OutSideViewRange)) | 1203 | if (NeedsClosing(reg, OutSideViewRange)) |
1204 | { | ||
1205 | int count = 60; | ||
1206 | do | ||
1231 | { | 1207 | { |
1232 | if (!sp.Scene.IncomingPreCloseClient(sp)) | 1208 | Thread.Sleep(250); |
1233 | { | 1209 | if(sp.IsDeleted) |
1234 | sp.IsInTransit = false; | ||
1235 | return; | 1210 | return; |
1236 | } | 1211 | if(!sp.IsInTransit) |
1212 | break; | ||
1213 | } while (--count > 0); | ||
1237 | 1214 | ||
1238 | // viewers and target region take extra time to process the tp | 1215 | |
1239 | Thread.Sleep(15000); | 1216 | if (!sp.IsDeleted) |
1217 | { | ||
1240 | m_log.DebugFormat( | 1218 | m_log.DebugFormat( |
1241 | "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name); | 1219 | "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport {2}", sp.Name, Scene.Name, sp.IsInTransit?"timeout":""); |
1242 | sp.Scene.CloseAgent(sp.UUID, false); | 1220 | sp.Scene.CloseAgent(sp.UUID, false); |
1243 | } | 1221 | } |
1244 | sp.IsInTransit = false; | 1222 | return; |
1245 | } | 1223 | } |
1224 | // otherwise keep child | ||
1225 | sp.IsInTransit = false; | ||
1246 | } | 1226 | } |
1247 | 1227 | ||
1248 | /// <summary> | 1228 | /// <summary> |
@@ -1313,9 +1293,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1313 | { | 1293 | { |
1314 | agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; | 1294 | agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; |
1315 | 1295 | ||
1296 | //m_log.DebugFormat( | ||
1297 | // "[ENTITY TRANSFER MODULE]: Set release callback URL to {0} in {1}", | ||
1298 | // agent.CallbackURI, region.RegionName); | ||
1299 | } | ||
1300 | |||
1301 | protected virtual void SetNewCallbackURL(AgentData agent, RegionInfo region) | ||
1302 | { | ||
1303 | agent.NewCallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; | ||
1304 | |||
1316 | m_log.DebugFormat( | 1305 | m_log.DebugFormat( |
1317 | "[ENTITY TRANSFER MODULE]: Set release callback URL to {0} in {1}", | 1306 | "[ENTITY TRANSFER MODULE]: Set release callback URL to {0} in {1}", |
1318 | agent.CallbackURI, region.RegionName); | 1307 | agent.NewCallbackURI, region.RegionName); |
1319 | } | 1308 | } |
1320 | 1309 | ||
1321 | /// <summary> | 1310 | /// <summary> |
@@ -1590,6 +1579,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1590 | 1579 | ||
1591 | public ScenePresence CrossAsync(ScenePresence agent, bool isFlying) | 1580 | public ScenePresence CrossAsync(ScenePresence agent, bool isFlying) |
1592 | { | 1581 | { |
1582 | if(agent.RegionViewDistance == 0) | ||
1583 | return agent; | ||
1584 | |||
1593 | Vector3 newpos; | 1585 | Vector3 newpos; |
1594 | EntityTransferContext ctx = new EntityTransferContext(); | 1586 | EntityTransferContext ctx = new EntityTransferContext(); |
1595 | string failureReason; | 1587 | string failureReason; |
@@ -1810,11 +1802,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1810 | cAgent.Position = pos; | 1802 | cAgent.Position = pos; |
1811 | cAgent.ChildrenCapSeeds = agent.KnownRegions; | 1803 | cAgent.ChildrenCapSeeds = agent.KnownRegions; |
1812 | 1804 | ||
1813 | childRegionsToClose = agent.GetChildAgentsToClose(neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); | 1805 | if(ctx.OutboundVersion < 0.7f) |
1814 | if(cAgent.ChildrenCapSeeds != null) | ||
1815 | { | 1806 | { |
1816 | foreach(ulong regh in childRegionsToClose) | 1807 | childRegionsToClose = agent.GetChildAgentsToClose(neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); |
1817 | cAgent.ChildrenCapSeeds.Remove(regh); | 1808 | if(cAgent.ChildrenCapSeeds != null) |
1809 | { | ||
1810 | foreach(ulong regh in childRegionsToClose) | ||
1811 | cAgent.ChildrenCapSeeds.Remove(regh); | ||
1812 | } | ||
1818 | } | 1813 | } |
1819 | 1814 | ||
1820 | if (isFlying) | 1815 | if (isFlying) |
@@ -1879,7 +1874,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1879 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); | 1874 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); |
1880 | 1875 | ||
1881 | Vector3 vel2 = Vector3.Zero; | 1876 | Vector3 vel2 = Vector3.Zero; |
1882 | if((agent.crossingFlags & 2) != 0) | 1877 | if((agent.m_crossingFlags & 2) != 0) |
1883 | vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); | 1878 | vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); |
1884 | 1879 | ||
1885 | if (m_eqModule != null) | 1880 | if (m_eqModule != null) |
@@ -1905,10 +1900,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1905 | if(childRegionsToClose != null) | 1900 | if(childRegionsToClose != null) |
1906 | agent.CloseChildAgents(childRegionsToClose); | 1901 | agent.CloseChildAgents(childRegionsToClose); |
1907 | 1902 | ||
1908 | if((agent.crossingFlags & 8) == 0) | 1903 | if((agent.m_crossingFlags & 8) == 0) |
1909 | agent.ClearControls(); // don't let attachments delete (called in HasMovedAway) disturb taken controls on viewers | 1904 | agent.ClearControls(); // don't let attachments delete (called in HasMovedAway) disturb taken controls on viewers |
1910 | 1905 | ||
1911 | agent.HasMovedAway((agent.crossingFlags & 8) == 0); | 1906 | agent.HasMovedAway((agent.m_crossingFlags & 8) == 0); |
1912 | 1907 | ||
1913 | agent.MakeChildAgent(neighbourRegion.RegionHandle); | 1908 | agent.MakeChildAgent(neighbourRegion.RegionHandle); |
1914 | 1909 | ||
@@ -1957,12 +1952,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1957 | 1952 | ||
1958 | if (seeds.ContainsKey(regionhandler)) | 1953 | if (seeds.ContainsKey(regionhandler)) |
1959 | seeds.Remove(regionhandler); | 1954 | seeds.Remove(regionhandler); |
1960 | /* | ||
1961 | List<ulong> oldregions = new List<ulong>(seeds.Keys); | ||
1962 | 1955 | ||
1963 | if (oldregions.Contains(currentRegionHandler)) | ||
1964 | oldregions.Remove(currentRegionHandler); | ||
1965 | */ | ||
1966 | if (!seeds.ContainsKey(currentRegionHandler)) | 1956 | if (!seeds.ContainsKey(currentRegionHandler)) |
1967 | seeds.Add(currentRegionHandler, sp.ControllingClient.RequestClientInfo().CapsPath); | 1957 | seeds.Add(currentRegionHandler, sp.ControllingClient.RequestClientInfo().CapsPath); |
1968 | 1958 | ||
@@ -1971,6 +1961,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1971 | agent.BaseFolder = UUID.Zero; | 1961 | agent.BaseFolder = UUID.Zero; |
1972 | agent.InventoryFolder = UUID.Zero; | 1962 | agent.InventoryFolder = UUID.Zero; |
1973 | agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, region); | 1963 | agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, region); |
1964 | agent.startfar = sp.DrawDistance; | ||
1974 | agent.child = true; | 1965 | agent.child = true; |
1975 | agent.Appearance = new AvatarAppearance(); | 1966 | agent.Appearance = new AvatarAppearance(); |
1976 | agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight; | 1967 | agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight; |
@@ -1999,24 +1990,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
1999 | agent.Mac = currentAgentCircuit.Mac; | 1990 | agent.Mac = currentAgentCircuit.Mac; |
2000 | agent.Id0 = currentAgentCircuit.Id0; | 1991 | agent.Id0 = currentAgentCircuit.Id0; |
2001 | } | 1992 | } |
2002 | /* | ||
2003 | AgentPosition agentpos = null; | ||
2004 | 1993 | ||
2005 | if (oldregions.Count > 0) | ||
2006 | { | ||
2007 | agentpos = new AgentPosition(); | ||
2008 | agentpos.AgentID = new UUID(sp.UUID.Guid); | ||
2009 | agentpos.SessionID = sp.ControllingClient.SessionId; | ||
2010 | agentpos.Size = sp.Appearance.AvatarSize; | ||
2011 | agentpos.Center = sp.CameraPosition; | ||
2012 | agentpos.Far = sp.DrawDistance; | ||
2013 | agentpos.Position = sp.AbsolutePosition; | ||
2014 | agentpos.Velocity = sp.Velocity; | ||
2015 | agentpos.RegionHandle = currentRegionHandler; | ||
2016 | agentpos.Throttles = sp.ControllingClient.GetThrottlesPacked(1); | ||
2017 | agentpos.ChildrenCapSeeds = seeds; | ||
2018 | } | ||
2019 | */ | ||
2020 | IPEndPoint external = region.ExternalEndPoint; | 1994 | IPEndPoint external = region.ExternalEndPoint; |
2021 | if (external != null) | 1995 | if (external != null) |
2022 | { | 1996 | { |
@@ -2025,20 +1999,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2025 | InformClientOfNeighbourCompleted, | 1999 | InformClientOfNeighbourCompleted, |
2026 | d); | 2000 | d); |
2027 | } | 2001 | } |
2028 | /* | ||
2029 | if(oldregions.Count >0) | ||
2030 | { | ||
2031 | uint neighbourx; | ||
2032 | uint neighboury; | ||
2033 | UUID scope = sp.Scene.RegionInfo.ScopeID; | ||
2034 | foreach (ulong handler in oldregions) | ||
2035 | { | ||
2036 | Utils.LongToUInts(handler, out neighbourx, out neighboury); | ||
2037 | GridRegion neighbour = sp.Scene.GridService.GetRegionByPosition(scope, (int)neighbourx, (int)neighboury); | ||
2038 | sp.Scene.SimulationService.UpdateAgent(neighbour, agentpos); | ||
2039 | } | ||
2040 | } | ||
2041 | */ | ||
2042 | } | 2002 | } |
2043 | 2003 | ||
2044 | #endregion | 2004 | #endregion |
@@ -2048,6 +2008,44 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2048 | private delegate void InformClientOfNeighbourDelegate( | 2008 | private delegate void InformClientOfNeighbourDelegate( |
2049 | ScenePresence avatar, AgentCircuitData a, GridRegion reg, IPEndPoint endPoint, bool newAgent); | 2009 | ScenePresence avatar, AgentCircuitData a, GridRegion reg, IPEndPoint endPoint, bool newAgent); |
2050 | 2010 | ||
2011 | List<GridRegion> RegionsInView(Vector3 pos, RegionInfo curregion, List<GridRegion> fullneighbours, float viewrange) | ||
2012 | { | ||
2013 | List<GridRegion> ret = new List<GridRegion>(); | ||
2014 | if(fullneighbours.Count == 0 || viewrange == 0) | ||
2015 | return ret; | ||
2016 | |||
2017 | int curX = (int)Util.RegionToWorldLoc(curregion.RegionLocX) + (int)pos.X; | ||
2018 | int minX = curX - (int)viewrange; | ||
2019 | int maxX = curX + (int)viewrange; | ||
2020 | int curY = (int)Util.RegionToWorldLoc(curregion.RegionLocY) + (int)pos.Y; | ||
2021 | int minY = curY - (int)viewrange; | ||
2022 | int maxY = curY + (int)viewrange; | ||
2023 | int rtmp; | ||
2024 | |||
2025 | foreach (GridRegion r in fullneighbours) | ||
2026 | { | ||
2027 | OpenSim.Framework.RegionFlags? regionFlags = r.RegionFlags; | ||
2028 | if (regionFlags != null) | ||
2029 | { | ||
2030 | if ((regionFlags & OpenSim.Framework.RegionFlags.RegionOnline) == 0) | ||
2031 | continue; | ||
2032 | } | ||
2033 | |||
2034 | rtmp = r.RegionLocX; | ||
2035 | if (maxX < rtmp) | ||
2036 | continue; | ||
2037 | if (minX > rtmp + r.RegionSizeX) | ||
2038 | continue; | ||
2039 | rtmp = r.RegionLocY; | ||
2040 | if (maxY < rtmp) | ||
2041 | continue; | ||
2042 | if (minY > rtmp + r.RegionSizeY) | ||
2043 | continue; | ||
2044 | ret.Add(r); | ||
2045 | } | ||
2046 | return ret; | ||
2047 | } | ||
2048 | |||
2051 | /// <summary> | 2049 | /// <summary> |
2052 | /// This informs all neighbouring regions about agent "avatar". | 2050 | /// This informs all neighbouring regions about agent "avatar". |
2053 | /// and as important informs the avatar about then | 2051 | /// and as important informs the avatar about then |
@@ -2055,22 +2053,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2055 | /// <param name="sp"></param> | 2053 | /// <param name="sp"></param> |
2056 | public void EnableChildAgents(ScenePresence sp) | 2054 | public void EnableChildAgents(ScenePresence sp) |
2057 | { | 2055 | { |
2058 | // assumes that out of view range regions are disconnected by the previus region | 2056 | // assumes that out of view range regions are disconnected by the previous region |
2059 | 2057 | ||
2060 | List<GridRegion> neighbours = new List<GridRegion>(); | ||
2061 | Scene spScene = sp.Scene; | 2058 | Scene spScene = sp.Scene; |
2062 | RegionInfo m_regionInfo = spScene.RegionInfo; | 2059 | RegionInfo regionInfo = spScene.RegionInfo; |
2063 | 2060 | ||
2064 | if (m_regionInfo != null) | 2061 | if (regionInfo == null) |
2062 | return; | ||
2063 | |||
2064 | ulong currentRegionHandler = regionInfo.RegionHandle; | ||
2065 | |||
2066 | List<GridRegion> neighbours; | ||
2067 | if (sp.RegionViewDistance > 0) | ||
2065 | { | 2068 | { |
2066 | neighbours = GetNeighbors(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); | 2069 | List<GridRegion> fullneighbours = GetNeighbors(sp); |
2070 | neighbours = RegionsInView(sp.AbsolutePosition, regionInfo, fullneighbours, sp.RegionViewDistance); | ||
2067 | } | 2071 | } |
2068 | else | 2072 | else |
2069 | { | 2073 | neighbours = new List<GridRegion>(); |
2070 | m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?"); | ||
2071 | } | ||
2072 | |||
2073 | ulong currentRegionHandler = m_regionInfo.RegionHandle; | ||
2074 | 2074 | ||
2075 | LinkedList<ulong> previousRegionNeighbourHandles; | 2075 | LinkedList<ulong> previousRegionNeighbourHandles; |
2076 | Dictionary<ulong, string> seeds; | 2076 | Dictionary<ulong, string> seeds; |
@@ -2106,13 +2106,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2106 | List<AgentCircuitData> cagents = new List<AgentCircuitData>(); | 2106 | List<AgentCircuitData> cagents = new List<AgentCircuitData>(); |
2107 | List<ulong> newneighbours = new List<ulong>(); | 2107 | List<ulong> newneighbours = new List<ulong>(); |
2108 | 2108 | ||
2109 | bool notHG = (sp.TeleportFlags & Constants.TeleportFlags.ViaHGLogin) == 0; | ||
2110 | |||
2111 | foreach (GridRegion neighbour in neighbours) | 2109 | foreach (GridRegion neighbour in neighbours) |
2112 | { | 2110 | { |
2113 | ulong handler = neighbour.RegionHandle; | 2111 | ulong handler = neighbour.RegionHandle; |
2114 | 2112 | ||
2115 | if (notHG && previousRegionNeighbourHandles.Contains(handler)) | 2113 | if (previousRegionNeighbourHandles.Contains(handler)) |
2116 | { | 2114 | { |
2117 | // agent already knows this region | 2115 | // agent already knows this region |
2118 | previousRegionNeighbourHandles.Remove(handler); | 2116 | previousRegionNeighbourHandles.Remove(handler); |
@@ -2130,7 +2128,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2130 | agent.child = true; | 2128 | agent.child = true; |
2131 | agent.Appearance = new AvatarAppearance(); | 2129 | agent.Appearance = new AvatarAppearance(); |
2132 | agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight; | 2130 | agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight; |
2133 | 2131 | agent.startfar = sp.DrawDistance; | |
2134 | if (currentAgentCircuit != null) | 2132 | if (currentAgentCircuit != null) |
2135 | { | 2133 | { |
2136 | agent.ServiceURLs = currentAgentCircuit.ServiceURLs; | 2134 | agent.ServiceURLs = currentAgentCircuit.ServiceURLs; |
@@ -2159,13 +2157,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2159 | foreach (ulong handler in previousRegionNeighbourHandles) | 2157 | foreach (ulong handler in previousRegionNeighbourHandles) |
2160 | seeds.Remove(handler); | 2158 | seeds.Remove(handler); |
2161 | 2159 | ||
2162 | if(notHG) // does not work on HG | 2160 | toclose = new List<ulong>(previousRegionNeighbourHandles); |
2163 | { | ||
2164 | toclose = new List<ulong>(previousRegionNeighbourHandles); | ||
2165 | // sp.CloseChildAgents(toclose); | ||
2166 | } | ||
2167 | else | ||
2168 | toclose = new List<ulong>(); | ||
2169 | } | 2161 | } |
2170 | else | 2162 | else |
2171 | toclose = new List<ulong>(); | 2163 | toclose = new List<ulong>(); |
@@ -2197,7 +2189,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2197 | 2189 | ||
2198 | Util.FireAndForget(delegate | 2190 | Util.FireAndForget(delegate |
2199 | { | 2191 | { |
2200 | Thread.Sleep(500); // the original delay that was at InformClientOfNeighbourAsync start | ||
2201 | int count = 0; | 2192 | int count = 0; |
2202 | IPEndPoint ipe; | 2193 | IPEndPoint ipe; |
2203 | 2194 | ||
@@ -2220,10 +2211,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2220 | } | 2211 | } |
2221 | count++; | 2212 | count++; |
2222 | } | 2213 | } |
2223 | else if (notHG && !previousRegionNeighbourHandles.Contains(handler)) | 2214 | else if (!previousRegionNeighbourHandles.Contains(handler)) |
2224 | { | 2215 | { |
2225 | spScene.SimulationService.UpdateAgent(neighbour, agentpos); | 2216 | spScene.SimulationService.UpdateAgent(neighbour, agentpos); |
2226 | } | 2217 | } |
2218 | if (sp.IsDeleted) | ||
2219 | return; | ||
2227 | } | 2220 | } |
2228 | catch (Exception e) | 2221 | catch (Exception e) |
2229 | { | 2222 | { |
@@ -2240,6 +2233,214 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2240 | } | 2233 | } |
2241 | } | 2234 | } |
2242 | 2235 | ||
2236 | public void CheckChildAgents(ScenePresence sp) | ||
2237 | { | ||
2238 | // assumes that out of view range regions are disconnected by the previous region | ||
2239 | |||
2240 | Scene spScene = sp.Scene; | ||
2241 | RegionInfo regionInfo = spScene.RegionInfo; | ||
2242 | |||
2243 | if (regionInfo == null) | ||
2244 | return; | ||
2245 | |||
2246 | ulong currentRegionHandler = regionInfo.RegionHandle; | ||
2247 | |||
2248 | List<GridRegion> neighbours; | ||
2249 | if (sp.RegionViewDistance > 0) | ||
2250 | { | ||
2251 | List<GridRegion> fullneighbours = GetNeighbors(sp); | ||
2252 | neighbours = RegionsInView(sp.AbsolutePosition, regionInfo, fullneighbours, sp.RegionViewDistance); | ||
2253 | } | ||
2254 | else | ||
2255 | neighbours = new List<GridRegion>(); | ||
2256 | |||
2257 | LinkedList<ulong> previousRegionNeighbourHandles = new LinkedList<ulong>(sp.KnownRegions.Keys); | ||
2258 | |||
2259 | IClientAPI spClient = sp.ControllingClient; | ||
2260 | |||
2261 | AgentCircuitData currentAgentCircuit = | ||
2262 | spScene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); | ||
2263 | |||
2264 | List<AgentCircuitData> cagents = new List<AgentCircuitData>(); | ||
2265 | List<GridRegion> newneighbours = new List<GridRegion>(); | ||
2266 | |||
2267 | foreach (GridRegion neighbour in neighbours) | ||
2268 | { | ||
2269 | ulong handler = neighbour.RegionHandle; | ||
2270 | |||
2271 | if (previousRegionNeighbourHandles.Contains(handler)) | ||
2272 | { | ||
2273 | // agent already knows this region | ||
2274 | previousRegionNeighbourHandles.Remove(handler); | ||
2275 | continue; | ||
2276 | } | ||
2277 | |||
2278 | if (handler == currentRegionHandler) | ||
2279 | continue; | ||
2280 | |||
2281 | // a new region to add | ||
2282 | AgentCircuitData agent = spClient.RequestClientInfo(); | ||
2283 | agent.BaseFolder = UUID.Zero; | ||
2284 | agent.InventoryFolder = UUID.Zero; | ||
2285 | agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour); | ||
2286 | agent.child = true; | ||
2287 | agent.Appearance = new AvatarAppearance(); | ||
2288 | agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight; | ||
2289 | agent.startfar = sp.DrawDistance; | ||
2290 | if (currentAgentCircuit != null) | ||
2291 | { | ||
2292 | agent.ServiceURLs = currentAgentCircuit.ServiceURLs; | ||
2293 | agent.IPAddress = currentAgentCircuit.IPAddress; | ||
2294 | agent.Viewer = currentAgentCircuit.Viewer; | ||
2295 | agent.Channel = currentAgentCircuit.Channel; | ||
2296 | agent.Mac = currentAgentCircuit.Mac; | ||
2297 | agent.Id0 = currentAgentCircuit.Id0; | ||
2298 | } | ||
2299 | |||
2300 | newneighbours.Add(neighbour); | ||
2301 | agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); | ||
2302 | sp.AddNeighbourRegion(neighbour, agent.CapsPath); | ||
2303 | |||
2304 | agent.ChildrenCapSeeds = null; | ||
2305 | cagents.Add(agent); | ||
2306 | } | ||
2307 | |||
2308 | List<ulong> toclose; | ||
2309 | // previousRegionNeighbourHandles now contains regions to forget | ||
2310 | if (previousRegionNeighbourHandles.Count > 0) | ||
2311 | { | ||
2312 | if (previousRegionNeighbourHandles.Contains(currentRegionHandler)) | ||
2313 | previousRegionNeighbourHandles.Remove(currentRegionHandler); | ||
2314 | |||
2315 | foreach (ulong handler in previousRegionNeighbourHandles) | ||
2316 | sp.KnownRegions.Remove(handler); | ||
2317 | |||
2318 | toclose = new List<ulong>(previousRegionNeighbourHandles); | ||
2319 | } | ||
2320 | else | ||
2321 | toclose = new List<ulong>(); | ||
2322 | |||
2323 | ICapabilitiesModule capsModule = spScene.CapsModule; | ||
2324 | if (capsModule != null) | ||
2325 | capsModule.SetChildrenSeed(sp.UUID, sp.KnownRegions); | ||
2326 | |||
2327 | if (toclose.Count > 0) | ||
2328 | sp.CloseChildAgents(toclose); | ||
2329 | |||
2330 | if (newneighbours.Count > 0) | ||
2331 | { | ||
2332 | int count = 0; | ||
2333 | IPEndPoint ipe; | ||
2334 | |||
2335 | foreach (GridRegion neighbour in newneighbours) | ||
2336 | { | ||
2337 | try | ||
2338 | { | ||
2339 | ipe = neighbour.ExternalEndPoint; | ||
2340 | if (ipe != null) | ||
2341 | InformClientOfNeighbourAsync(sp, cagents[count], neighbour, ipe, true); | ||
2342 | else | ||
2343 | { | ||
2344 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: lost DNS resolution for neighbour {0}", neighbour.ExternalHostName); | ||
2345 | } | ||
2346 | count++; | ||
2347 | if (sp.IsDeleted) | ||
2348 | return; | ||
2349 | } | ||
2350 | catch (Exception e) | ||
2351 | { | ||
2352 | m_log.ErrorFormat( | ||
2353 | "[ENTITY TRANSFER MODULE]: Error creating child agent at {0} ({1} ({2}, {3}). {4}", | ||
2354 | neighbour.ExternalHostName, | ||
2355 | neighbour.RegionHandle, | ||
2356 | neighbour.RegionLocX, | ||
2357 | neighbour.RegionLocY, | ||
2358 | e); | ||
2359 | } | ||
2360 | } | ||
2361 | } | ||
2362 | } | ||
2363 | |||
2364 | public void CloseOldChildAgents(ScenePresence sp) | ||
2365 | { | ||
2366 | Scene spScene = sp.Scene; | ||
2367 | RegionInfo regionInfo = spScene.RegionInfo; | ||
2368 | |||
2369 | if (regionInfo == null) | ||
2370 | return; | ||
2371 | |||
2372 | ulong currentRegionHandler = regionInfo.RegionHandle; | ||
2373 | |||
2374 | List<GridRegion> neighbours; | ||
2375 | if (sp.RegionViewDistance > 0) | ||
2376 | { | ||
2377 | List<GridRegion> fullneighbours = GetNeighbors(sp); | ||
2378 | neighbours = RegionsInView(sp.AbsolutePosition, regionInfo, fullneighbours, sp.RegionViewDistance); | ||
2379 | } | ||
2380 | else | ||
2381 | neighbours = new List<GridRegion>(); | ||
2382 | |||
2383 | LinkedList<ulong> previousRegionNeighbourHandles; | ||
2384 | Dictionary<ulong, string> seeds; | ||
2385 | ICapabilitiesModule capsModule = spScene.CapsModule; | ||
2386 | |||
2387 | if (capsModule != null) | ||
2388 | { | ||
2389 | seeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(sp.UUID)); | ||
2390 | previousRegionNeighbourHandles = new LinkedList<ulong>(seeds.Keys); | ||
2391 | } | ||
2392 | else | ||
2393 | { | ||
2394 | seeds = new Dictionary<ulong, string>(); | ||
2395 | previousRegionNeighbourHandles = new LinkedList<ulong>(); | ||
2396 | } | ||
2397 | |||
2398 | IClientAPI spClient = sp.ControllingClient; | ||
2399 | |||
2400 | // This will fail if the user aborts login | ||
2401 | try | ||
2402 | { | ||
2403 | if (!seeds.ContainsKey(currentRegionHandler)) | ||
2404 | seeds.Add(currentRegionHandler, spClient.RequestClientInfo().CapsPath); | ||
2405 | } | ||
2406 | catch | ||
2407 | { | ||
2408 | return; | ||
2409 | } | ||
2410 | |||
2411 | foreach (GridRegion neighbour in neighbours) | ||
2412 | { | ||
2413 | ulong handler = neighbour.RegionHandle; | ||
2414 | |||
2415 | if (previousRegionNeighbourHandles.Contains(handler)) | ||
2416 | previousRegionNeighbourHandles.Remove(handler); | ||
2417 | } | ||
2418 | |||
2419 | List<ulong> toclose; | ||
2420 | // previousRegionNeighbourHandles now contains regions to forget | ||
2421 | if (previousRegionNeighbourHandles.Count == 0) | ||
2422 | return; | ||
2423 | |||
2424 | if (previousRegionNeighbourHandles.Contains(currentRegionHandler)) | ||
2425 | previousRegionNeighbourHandles.Remove(currentRegionHandler); | ||
2426 | |||
2427 | foreach (ulong handler in previousRegionNeighbourHandles) | ||
2428 | seeds.Remove(handler); | ||
2429 | |||
2430 | toclose = new List<ulong>(previousRegionNeighbourHandles); | ||
2431 | |||
2432 | if (capsModule != null) | ||
2433 | capsModule.SetChildrenSeed(sp.UUID, seeds); | ||
2434 | |||
2435 | sp.KnownRegions = seeds; | ||
2436 | sp.SetNeighbourRegionSizeInfo(neighbours); | ||
2437 | |||
2438 | Util.FireAndForget(delegate | ||
2439 | { | ||
2440 | sp.CloseChildAgents(toclose); | ||
2441 | }); | ||
2442 | } | ||
2443 | |||
2243 | // Computes the difference between two region bases. | 2444 | // Computes the difference between two region bases. |
2244 | // Returns a vector of world coordinates (meters) from base of first region to the second. | 2445 | // Returns a vector of world coordinates (meters) from base of first region to the second. |
2245 | // The first region is the home region of the passed scene presence. | 2446 | // The first region is the home region of the passed scene presence. |
@@ -2440,6 +2641,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2440 | 2641 | ||
2441 | } | 2642 | } |
2442 | 2643 | ||
2644 | // all this code should be moved to scene replacing the now bad one there | ||
2645 | // cache Neighbors | ||
2646 | List<GridRegion> Neighbors = null; | ||
2647 | DateTime LastNeighborsTime = DateTime.MinValue; | ||
2648 | |||
2443 | /// <summary> | 2649 | /// <summary> |
2444 | /// Return the list of online regions that are considered to be neighbours to the given scene. | 2650 | /// Return the list of online regions that are considered to be neighbours to the given scene. |
2445 | /// </summary> | 2651 | /// </summary> |
@@ -2447,39 +2653,41 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2447 | /// <param name="pRegionLocX"></param> | 2653 | /// <param name="pRegionLocX"></param> |
2448 | /// <param name="pRegionLocY"></param> | 2654 | /// <param name="pRegionLocY"></param> |
2449 | /// <returns></returns> | 2655 | /// <returns></returns> |
2450 | protected List<GridRegion> GetNeighbors(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY) | 2656 | protected List<GridRegion> GetNeighbors(ScenePresence avatar) |
2451 | { | 2657 | { |
2452 | Scene pScene = avatar.Scene; | 2658 | Scene pScene = avatar.Scene; |
2453 | RegionInfo m_regionInfo = pScene.RegionInfo; | ||
2454 | List<GridRegion> neighbours; | ||
2455 | 2659 | ||
2456 | uint dd = (uint)avatar.RegionViewDistance; | 2660 | uint dd = (uint)pScene.MaxRegionViewDistance; |
2661 | if(dd <= 1) | ||
2662 | return new List<GridRegion>(); | ||
2457 | 2663 | ||
2458 | // until avatar movement updates client connections, we need to send at least this current region immediate neighbors | 2664 | if (Neighbors != null && (DateTime.UtcNow - LastNeighborsTime).TotalSeconds < 30) |
2459 | uint ddX = Math.Max(dd, Constants.RegionSize); | 2665 | { |
2460 | uint ddY = Math.Max(dd, Constants.RegionSize); | 2666 | return Neighbors; |
2667 | } | ||
2461 | 2668 | ||
2462 | ddX--; | 2669 | RegionInfo regionInfo = pScene.RegionInfo; |
2463 | ddY--; | 2670 | List<GridRegion> neighbours; |
2464 | 2671 | ||
2465 | // reference to region edges. Should be avatar position | 2672 | dd--; |
2466 | uint startX = Util.RegionToWorldLoc(pRegionLocX); | ||
2467 | uint endX = startX + m_regionInfo.RegionSizeX; | ||
2468 | uint startY = Util.RegionToWorldLoc(pRegionLocY); | ||
2469 | uint endY = startY + m_regionInfo.RegionSizeY; | ||
2470 | 2673 | ||
2471 | startX -= ddX; | 2674 | uint startX = Util.RegionToWorldLoc(regionInfo.RegionLocX); |
2472 | startY -= ddY; | 2675 | uint endX = startX + regionInfo.RegionSizeX; |
2473 | endX += ddX; | 2676 | uint startY = Util.RegionToWorldLoc(regionInfo.RegionLocY); |
2474 | endY += ddY; | 2677 | uint endY = startY + regionInfo.RegionSizeY; |
2475 | 2678 | ||
2476 | neighbours | 2679 | startX -= dd; |
2477 | = avatar.Scene.GridService.GetRegionRange( | 2680 | startY -= dd; |
2478 | m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY); | 2681 | endX += dd; |
2682 | endY += dd; | ||
2479 | 2683 | ||
2480 | // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1). | 2684 | neighbours = avatar.Scene.GridService.GetRegionRange( |
2481 | neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID ); | 2685 | regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY); |
2482 | 2686 | ||
2687 | // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1). | ||
2688 | neighbours.RemoveAll( r => r.RegionID == regionInfo.RegionID ); | ||
2689 | Neighbors = neighbours; | ||
2690 | LastNeighborsTime = DateTime.UtcNow; | ||
2483 | return neighbours; | 2691 | return neighbours; |
2484 | } | 2692 | } |
2485 | #endregion | 2693 | #endregion |
@@ -2488,7 +2696,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
2488 | 2696 | ||
2489 | public void AgentArrivedAtDestination(UUID id) | 2697 | public void AgentArrivedAtDestination(UUID id) |
2490 | { | 2698 | { |
2491 | m_entityTransferStateMachine.SetAgentArrivedAtDestination(id); | 2699 | ScenePresence sp = Scene.GetScenePresence(id); |
2700 | if(sp == null || sp.IsDeleted || !sp.IsInTransit) | ||
2701 | return; | ||
2702 | |||
2703 | //Scene.CloseAgent(sp.UUID, false); | ||
2704 | sp.IsInTransit = false; | ||
2705 | //m_entityTransferStateMachine.SetAgentArrivedAtDestination(id); | ||
2492 | } | 2706 | } |
2493 | 2707 | ||
2494 | #endregion | 2708 | #endregion |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs index 1529fc2..615ae78 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs | |||
@@ -68,7 +68,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
68 | if (sp.IsNPC) | 68 | if (sp.IsNPC) |
69 | return; | 69 | return; |
70 | 70 | ||
71 | if(sp.gotCrossUpdate) | 71 | if(sp.m_gotCrossUpdate) |
72 | { | 72 | { |
73 | Util.FireAndForget(delegate | 73 | Util.FireAndForget(delegate |
74 | { | 74 | { |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs index a7e62eb..6f4eace 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs | |||
@@ -50,7 +50,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
50 | public void AddRegion(Scene scene) | 50 | public void AddRegion(Scene scene) |
51 | { | 51 | { |
52 | scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; | 52 | scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; |
53 | scene.EventManager.OnNewClient += OnNewClient; | ||
54 | 53 | ||
55 | m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID); | 54 | m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID); |
56 | 55 | ||
@@ -61,7 +60,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
61 | public void RemoveRegion(Scene scene) | 60 | public void RemoveRegion(Scene scene) |
62 | { | 61 | { |
63 | scene.EventManager.OnMakeRootAgent -= OnMakeRootAgent; | 62 | scene.EventManager.OnMakeRootAgent -= OnMakeRootAgent; |
64 | scene.EventManager.OnNewClient -= OnNewClient; | ||
65 | 63 | ||
66 | m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID); | 64 | m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID); |
67 | } | 65 | } |
@@ -71,7 +69,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
71 | if (sp.IsNPC) | 69 | if (sp.IsNPC) |
72 | return; | 70 | return; |
73 | 71 | ||
74 | if(sp.gotCrossUpdate) | 72 | sp.ControllingClient.OnConnectionClosed += OnConnectionClose; |
73 | |||
74 | if (sp.m_gotCrossUpdate) | ||
75 | { | 75 | { |
76 | Util.FireAndForget(delegate | 76 | Util.FireAndForget(delegate |
77 | { | 77 | { |
@@ -89,11 +89,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
89 | m_PresenceService.ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID); | 89 | m_PresenceService.ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID); |
90 | } | 90 | } |
91 | 91 | ||
92 | public void OnNewClient(IClientAPI client) | ||
93 | { | ||
94 | client.OnConnectionClosed += OnConnectionClose; | ||
95 | } | ||
96 | |||
97 | public void OnConnectionClose(IClientAPI client) | 92 | public void OnConnectionClose(IClientAPI client) |
98 | { | 93 | { |
99 | if (client != null && client.SceneAgent != null && !client.SceneAgent.IsChildAgent) | 94 | if (client != null && client.SceneAgent != null && !client.SceneAgent.IsChildAgent) |
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index ac28cee..986a44f 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | |||
@@ -574,7 +574,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
574 | Scene.RegionInfo.RegionSettings.Save(); | 574 | Scene.RegionInfo.RegionSettings.Save(); |
575 | TriggerRegionInfoChange(); | 575 | TriggerRegionInfoChange(); |
576 | sendRegionHandshakeToAll(); | 576 | sendRegionHandshakeToAll(); |
577 | sendRegionInfoPacketToAll(); | 577 | // sendRegionInfoPacketToAll(); |
578 | } | 578 | } |
579 | 579 | ||
580 | private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient) | 580 | private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient) |
@@ -1404,7 +1404,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
1404 | RegionInfoForEstateMenuArgs args = new RegionInfoForEstateMenuArgs(); | 1404 | RegionInfoForEstateMenuArgs args = new RegionInfoForEstateMenuArgs(); |
1405 | args.billableFactor = Scene.RegionInfo.EstateSettings.BillableFactor; | 1405 | args.billableFactor = Scene.RegionInfo.EstateSettings.BillableFactor; |
1406 | args.estateID = Scene.RegionInfo.EstateSettings.EstateID; | 1406 | args.estateID = Scene.RegionInfo.EstateSettings.EstateID; |
1407 | args.maxAgents = (byte)Scene.RegionInfo.RegionSettings.AgentLimit; | 1407 | args.maxAgents = Scene.RegionInfo.RegionSettings.AgentLimit; |
1408 | args.objectBonusFactor = (float)Scene.RegionInfo.RegionSettings.ObjectBonus; | 1408 | args.objectBonusFactor = (float)Scene.RegionInfo.RegionSettings.ObjectBonus; |
1409 | args.parentEstateID = Scene.RegionInfo.EstateSettings.ParentEstateID; | 1409 | args.parentEstateID = Scene.RegionInfo.EstateSettings.ParentEstateID; |
1410 | args.pricePerMeter = Scene.RegionInfo.EstateSettings.PricePerMeter; | 1410 | args.pricePerMeter = Scene.RegionInfo.EstateSettings.PricePerMeter; |
@@ -1419,6 +1419,8 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
1419 | args.waterHeight = (float)Scene.RegionInfo.RegionSettings.WaterHeight; | 1419 | args.waterHeight = (float)Scene.RegionInfo.RegionSettings.WaterHeight; |
1420 | args.simName = Scene.RegionInfo.RegionName; | 1420 | args.simName = Scene.RegionInfo.RegionName; |
1421 | args.regionType = Scene.RegionInfo.RegionType; | 1421 | args.regionType = Scene.RegionInfo.RegionType; |
1422 | args.AgentCapacity = Scene.RegionInfo.AgentCapacity; | ||
1423 | args.ObjectsCapacity = Scene.RegionInfo.ObjectCapacity; | ||
1422 | 1424 | ||
1423 | remote_client.SendRegionInfoToEstateMenu(args); | 1425 | remote_client.SendRegionInfoToEstateMenu(args); |
1424 | } | 1426 | } |
@@ -1518,42 +1520,7 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
1518 | 1520 | ||
1519 | public void sendRegionHandshake(IClientAPI remoteClient) | 1521 | public void sendRegionHandshake(IClientAPI remoteClient) |
1520 | { | 1522 | { |
1521 | RegionHandshakeArgs args = new RegionHandshakeArgs(); | 1523 | remoteClient.SendRegionHandshake(); |
1522 | |||
1523 | args.isEstateManager = Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(remoteClient.AgentId); | ||
1524 | if (Scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && Scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId) | ||
1525 | args.isEstateManager = true; | ||
1526 | |||
1527 | args.billableFactor = Scene.RegionInfo.EstateSettings.BillableFactor; | ||
1528 | args.terrainStartHeight0 = (float)Scene.RegionInfo.RegionSettings.Elevation1SW; | ||
1529 | args.terrainHeightRange0 = (float)Scene.RegionInfo.RegionSettings.Elevation2SW; | ||
1530 | args.terrainStartHeight1 = (float)Scene.RegionInfo.RegionSettings.Elevation1NW; | ||
1531 | args.terrainHeightRange1 = (float)Scene.RegionInfo.RegionSettings.Elevation2NW; | ||
1532 | args.terrainStartHeight2 = (float)Scene.RegionInfo.RegionSettings.Elevation1SE; | ||
1533 | args.terrainHeightRange2 = (float)Scene.RegionInfo.RegionSettings.Elevation2SE; | ||
1534 | args.terrainStartHeight3 = (float)Scene.RegionInfo.RegionSettings.Elevation1NE; | ||
1535 | args.terrainHeightRange3 = (float)Scene.RegionInfo.RegionSettings.Elevation2NE; | ||
1536 | args.simAccess = Scene.RegionInfo.AccessLevel; | ||
1537 | args.waterHeight = (float)Scene.RegionInfo.RegionSettings.WaterHeight; | ||
1538 | args.regionFlags = GetRegionFlags(); | ||
1539 | args.regionName = Scene.RegionInfo.RegionName; | ||
1540 | args.SimOwner = Scene.RegionInfo.EstateSettings.EstateOwner; | ||
1541 | |||
1542 | args.terrainBase0 = UUID.Zero; | ||
1543 | args.terrainBase1 = UUID.Zero; | ||
1544 | args.terrainBase2 = UUID.Zero; | ||
1545 | args.terrainBase3 = UUID.Zero; | ||
1546 | args.terrainDetail0 = Scene.RegionInfo.RegionSettings.TerrainTexture1; | ||
1547 | args.terrainDetail1 = Scene.RegionInfo.RegionSettings.TerrainTexture2; | ||
1548 | args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; | ||
1549 | args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; | ||
1550 | |||
1551 | // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); | ||
1552 | // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); | ||
1553 | // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); | ||
1554 | // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); | ||
1555 | |||
1556 | remoteClient.SendRegionHandshake(Scene.RegionInfo,args); | ||
1557 | } | 1524 | } |
1558 | 1525 | ||
1559 | public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2) | 1526 | public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2) |
@@ -1673,7 +1640,6 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
1673 | client.OnRegionInfoRequest += HandleRegionInfoRequest; | 1640 | client.OnRegionInfoRequest += HandleRegionInfoRequest; |
1674 | client.OnEstateCovenantRequest += HandleEstateCovenantRequest; | 1641 | client.OnEstateCovenantRequest += HandleEstateCovenantRequest; |
1675 | client.OnLandStatRequest += HandleLandStatRequest; | 1642 | client.OnLandStatRequest += HandleLandStatRequest; |
1676 | sendRegionHandshake(client); | ||
1677 | } | 1643 | } |
1678 | 1644 | ||
1679 | 1645 | ||
@@ -1681,39 +1647,43 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
1681 | { | 1647 | { |
1682 | RegionFlags flags = RegionFlags.None; | 1648 | RegionFlags flags = RegionFlags.None; |
1683 | 1649 | ||
1650 | if (Scene.RegionInfo.EstateSettings.AllowLandmark) | ||
1651 | flags |= RegionFlags.AllowLandmark; | ||
1652 | if (Scene.RegionInfo.EstateSettings.AllowSetHome) | ||
1653 | flags |= RegionFlags.AllowSetHome; | ||
1654 | if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) | ||
1655 | flags |= RegionFlags.ResetHomeOnTeleport; | ||
1684 | if (Scene.RegionInfo.EstateSettings.FixedSun) | 1656 | if (Scene.RegionInfo.EstateSettings.FixedSun) |
1685 | flags |= RegionFlags.SunFixed; | 1657 | flags |= RegionFlags.SunFixed; |
1686 | if (Scene.RegionInfo.EstateSettings.PublicAccess) | 1658 | if (Scene.RegionInfo.EstateSettings.TaxFree) // this is now wrong means ALLOW_ACCESS_OVERRIDE |
1687 | flags |= (RegionFlags.PublicAllowed | | 1659 | flags |= RegionFlags.TaxFree; |
1688 | RegionFlags.ExternallyVisible); | 1660 | |
1689 | if (Scene.RegionInfo.EstateSettings.AllowVoice) | 1661 | if (Scene.RegionInfo.EstateSettings.PublicAccess) //?? |
1690 | flags |= RegionFlags.AllowVoice; | 1662 | flags |= (RegionFlags.PublicAllowed | RegionFlags.ExternallyVisible); |
1663 | |||
1664 | if (Scene.RegionInfo.EstateSettings.BlockDwell) | ||
1665 | flags |= RegionFlags.BlockDwell; | ||
1691 | if (Scene.RegionInfo.EstateSettings.AllowDirectTeleport) | 1666 | if (Scene.RegionInfo.EstateSettings.AllowDirectTeleport) |
1692 | flags |= RegionFlags.AllowDirectTeleport; | 1667 | flags |= RegionFlags.AllowDirectTeleport; |
1668 | if (Scene.RegionInfo.EstateSettings.EstateSkipScripts) | ||
1669 | flags |= RegionFlags.EstateSkipScripts; | ||
1670 | |||
1693 | if (Scene.RegionInfo.EstateSettings.DenyAnonymous) | 1671 | if (Scene.RegionInfo.EstateSettings.DenyAnonymous) |
1694 | flags |= RegionFlags.DenyAnonymous; | 1672 | flags |= RegionFlags.DenyAnonymous; |
1695 | if (Scene.RegionInfo.EstateSettings.DenyIdentified) | 1673 | if (Scene.RegionInfo.EstateSettings.DenyIdentified) // unused? |
1696 | flags |= RegionFlags.DenyIdentified; | 1674 | flags |= RegionFlags.DenyIdentified; |
1697 | if (Scene.RegionInfo.EstateSettings.DenyTransacted) | 1675 | if (Scene.RegionInfo.EstateSettings.DenyTransacted) // unused? |
1698 | flags |= RegionFlags.DenyTransacted; | 1676 | flags |= RegionFlags.DenyTransacted; |
1699 | if (Scene.RegionInfo.EstateSettings.AbuseEmailToEstateOwner) | ||
1700 | flags |= RegionFlags.AbuseEmailToEstateOwner; | ||
1701 | if (Scene.RegionInfo.EstateSettings.BlockDwell) | ||
1702 | flags |= RegionFlags.BlockDwell; | ||
1703 | if (Scene.RegionInfo.EstateSettings.EstateSkipScripts) | ||
1704 | flags |= RegionFlags.EstateSkipScripts; | ||
1705 | if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) | ||
1706 | flags |= RegionFlags.ResetHomeOnTeleport; | ||
1707 | if (Scene.RegionInfo.EstateSettings.TaxFree) | ||
1708 | flags |= RegionFlags.TaxFree; | ||
1709 | if (Scene.RegionInfo.EstateSettings.AllowLandmark) | ||
1710 | flags |= RegionFlags.AllowLandmark; | ||
1711 | if (Scene.RegionInfo.EstateSettings.AllowParcelChanges) | 1677 | if (Scene.RegionInfo.EstateSettings.AllowParcelChanges) |
1712 | flags |= RegionFlags.AllowParcelChanges; | 1678 | flags |= RegionFlags.AllowParcelChanges; |
1713 | if (Scene.RegionInfo.EstateSettings.AllowSetHome) | 1679 | if (Scene.RegionInfo.EstateSettings.AbuseEmailToEstateOwner) // now is block fly |
1714 | flags |= RegionFlags.AllowSetHome; | 1680 | flags |= RegionFlags.AbuseEmailToEstateOwner; |
1681 | if (Scene.RegionInfo.EstateSettings.AllowVoice) | ||
1682 | flags |= RegionFlags.AllowVoice; | ||
1683 | |||
1684 | |||
1715 | if (Scene.RegionInfo.EstateSettings.DenyMinors) | 1685 | if (Scene.RegionInfo.EstateSettings.DenyMinors) |
1716 | flags |= (RegionFlags)(1 << 30); | 1686 | flags |= RegionFlags.DenyAgeUnverified; |
1717 | 1687 | ||
1718 | return (uint)flags; | 1688 | return (uint)flags; |
1719 | } | 1689 | } |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs index 993b782..9e687eb 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs | |||
@@ -247,11 +247,11 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
247 | m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); | 247 | m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); |
248 | } | 248 | } |
249 | } | 249 | } |
250 | public void sendClientInitialLandInfo(IClientAPI remoteClient) | 250 | public void sendClientInitialLandInfo(IClientAPI remoteClient, bool overlay) |
251 | { | 251 | { |
252 | if (m_landManagementModule != null) | 252 | if (m_landManagementModule != null) |
253 | { | 253 | { |
254 | m_landManagementModule.sendClientInitialLandInfo(remoteClient); | 254 | m_landManagementModule.sendClientInitialLandInfo(remoteClient, overlay); |
255 | } | 255 | } |
256 | } | 256 | } |
257 | #endregion | 257 | #endregion |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 8c327d8..b67cad7 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | |||
@@ -491,7 +491,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
491 | return; | 491 | return; |
492 | } | 492 | } |
493 | 493 | ||
494 | public void sendClientInitialLandInfo(IClientAPI remoteClient) | 494 | public void sendClientInitialLandInfo(IClientAPI remoteClient, bool overlay) |
495 | { | 495 | { |
496 | ScenePresence avatar; | 496 | ScenePresence avatar; |
497 | 497 | ||
@@ -507,7 +507,8 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
507 | avatar.currentParcelUUID = over.LandData.GlobalID; | 507 | avatar.currentParcelUUID = over.LandData.GlobalID; |
508 | over.SendLandUpdateToClient(avatar.ControllingClient); | 508 | over.SendLandUpdateToClient(avatar.ControllingClient); |
509 | } | 509 | } |
510 | SendParcelOverlay(remoteClient); | 510 | if(overlay) |
511 | SendParcelOverlay(remoteClient); | ||
511 | } | 512 | } |
512 | 513 | ||
513 | public void SendLandUpdate(ScenePresence avatar, ILandObject over) | 514 | public void SendLandUpdate(ScenePresence avatar, ILandObject over) |
@@ -998,6 +999,39 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
998 | } | 999 | } |
999 | } | 1000 | } |
1000 | 1001 | ||
1002 | public ILandObject GetLandObjectinLandUnits(int x, int y) | ||
1003 | { | ||
1004 | if (m_landList.Count == 0 || m_landIDList == null) | ||
1005 | return null; | ||
1006 | |||
1007 | lock (m_landIDList) | ||
1008 | { | ||
1009 | try | ||
1010 | { | ||
1011 | return m_landList[m_landIDList[x, y]]; | ||
1012 | } | ||
1013 | catch (IndexOutOfRangeException) | ||
1014 | { | ||
1015 | return null; | ||
1016 | } | ||
1017 | } | ||
1018 | } | ||
1019 | |||
1020 | public int GetLandObjectIDinLandUnits(int x, int y) | ||
1021 | { | ||
1022 | lock (m_landIDList) | ||
1023 | { | ||
1024 | try | ||
1025 | { | ||
1026 | return m_landIDList[x, y]; | ||
1027 | } | ||
1028 | catch (IndexOutOfRangeException) | ||
1029 | { | ||
1030 | return -1; | ||
1031 | } | ||
1032 | } | ||
1033 | } | ||
1034 | |||
1001 | // Create a 'parcel is here' bitmap for the parcel identified by the passed landID | 1035 | // Create a 'parcel is here' bitmap for the parcel identified by the passed landID |
1002 | private bool[,] CreateBitmapForID(int landID) | 1036 | private bool[,] CreateBitmapForID(int landID) |
1003 | { | 1037 | { |
@@ -1282,18 +1316,9 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1282 | #region Parcel Updating | 1316 | #region Parcel Updating |
1283 | 1317 | ||
1284 | /// <summary> | 1318 | /// <summary> |
1285 | /// Send the parcel overlay blocks to the client. We send the overlay packets | 1319 | /// Send the parcel overlay blocks to the client. |
1286 | /// around a location and limited by the 'parcelLayerViewDistance'. This number | ||
1287 | /// is usually 128 and the code is arranged so it sends all the parcel overlay | ||
1288 | /// information for a whole region if the region is legacy sized (256x256). If | ||
1289 | /// the region is larger, only the parcel layer information is sent around | ||
1290 | /// the point specified. This reduces the problem of parcel layer information | ||
1291 | /// blocks increasing exponentially as region size increases. | ||
1292 | /// </summary> | 1320 | /// </summary> |
1293 | /// <param name="remote_client">The object representing the client</param> | 1321 | /// <param name="remote_client">The object representing the client</param> |
1294 | /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param> | ||
1295 | /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param> | ||
1296 | /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param> | ||
1297 | public void SendParcelOverlay(IClientAPI remote_client) | 1322 | public void SendParcelOverlay(IClientAPI remote_client) |
1298 | { | 1323 | { |
1299 | if (remote_client.SceneAgent.PresenceType == PresenceType.Npc) | 1324 | if (remote_client.SceneAgent.PresenceType == PresenceType.Npc) |
@@ -1301,99 +1326,133 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1301 | 1326 | ||
1302 | const int LAND_BLOCKS_PER_PACKET = 1024; | 1327 | const int LAND_BLOCKS_PER_PACKET = 1024; |
1303 | 1328 | ||
1329 | int curID; | ||
1330 | int southID; | ||
1331 | |||
1304 | byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; | 1332 | byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; |
1305 | int byteArrayCount = 0; | 1333 | int byteArrayCount = 0; |
1306 | int sequenceID = 0; | 1334 | int sequenceID = 0; |
1307 | 1335 | ||
1336 | int sx = (int)m_scene.RegionInfo.RegionSizeX / LandUnit; | ||
1337 | byte curByte; | ||
1338 | byte tmpByte; | ||
1339 | |||
1308 | // Layer data is in LandUnit (4m) chunks | 1340 | // Layer data is in LandUnit (4m) chunks |
1309 | for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += LandUnit) | 1341 | for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / LandUnit; ++y) |
1310 | { | 1342 | { |
1311 | for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += LandUnit) | 1343 | for (int x = 0; x < sx;) |
1312 | { | 1344 | { |
1313 | byte tempByte = 0; //This represents the byte for the current 4x4 | 1345 | curID = GetLandObjectIDinLandUnits(x,y); |
1346 | if(curID < 0) | ||
1347 | continue; | ||
1314 | 1348 | ||
1315 | ILandObject currentParcelBlock = GetLandObject(x, y); | 1349 | ILandObject currentParcel = GetLandObject(curID); |
1350 | if (currentParcel == null) | ||
1351 | continue; | ||
1316 | 1352 | ||
1317 | if (currentParcelBlock != null) | 1353 | // types |
1354 | if (currentParcel.LandData.OwnerID == remote_client.AgentId) | ||
1318 | { | 1355 | { |
1319 | // types | 1356 | //Owner Flag |
1320 | if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) | 1357 | curByte = LandChannel.LAND_TYPE_OWNED_BY_REQUESTER; |
1321 | { | 1358 | } |
1322 | //Owner Flag | 1359 | else if (currentParcel.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcel.LandData.GroupID)) |
1323 | tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_REQUESTER; | 1360 | { |
1324 | } | 1361 | curByte = LandChannel.LAND_TYPE_OWNED_BY_GROUP; |
1325 | else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID)) | 1362 | } |
1326 | { | 1363 | else if (currentParcel.LandData.SalePrice > 0 && |
1327 | tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_GROUP; | 1364 | (currentParcel.LandData.AuthBuyerID == UUID.Zero || |
1328 | } | 1365 | currentParcel.LandData.AuthBuyerID == remote_client.AgentId)) |
1329 | else if (currentParcelBlock.LandData.SalePrice > 0 && | 1366 | { |
1330 | (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || | 1367 | //Sale type |
1331 | currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) | 1368 | curByte = LandChannel.LAND_TYPE_IS_FOR_SALE; |
1332 | { | 1369 | } |
1333 | //Sale type | 1370 | else if (currentParcel.LandData.OwnerID == UUID.Zero) |
1334 | tempByte = (byte)LandChannel.LAND_TYPE_IS_FOR_SALE; | 1371 | { |
1335 | } | 1372 | //Public type |
1336 | else if (currentParcelBlock.LandData.OwnerID == UUID.Zero) | 1373 | curByte = LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero |
1337 | { | 1374 | } |
1338 | //Public type | 1375 | // LAND_TYPE_IS_BEING_AUCTIONED still unsuported |
1339 | tempByte = (byte)LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero | 1376 | else |
1340 | } | 1377 | { |
1341 | // LAND_TYPE_IS_BEING_AUCTIONED still unsuported | 1378 | //Other |
1342 | else | 1379 | curByte = LandChannel.LAND_TYPE_OWNED_BY_OTHER; |
1343 | { | 1380 | } |
1344 | //Other Flag | ||
1345 | tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_OTHER; | ||
1346 | } | ||
1347 | 1381 | ||
1348 | // now flags | 1382 | // now flags |
1349 | // border control | 1383 | // local sound |
1384 | if ((currentParcel.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0) | ||
1385 | curByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND; | ||
1350 | 1386 | ||
1351 | ILandObject westParcel = null; | 1387 | // hide avatars |
1352 | ILandObject southParcel = null; | 1388 | if (!currentParcel.LandData.SeeAVs) |
1353 | if (x > 0) | 1389 | curByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS; |
1354 | { | ||
1355 | westParcel = GetLandObject((x - 1), y); | ||
1356 | } | ||
1357 | if (y > 0) | ||
1358 | { | ||
1359 | southParcel = GetLandObject(x, (y - 1)); | ||
1360 | } | ||
1361 | 1390 | ||
1362 | if (x == 0) | 1391 | // border flags for current |
1363 | { | 1392 | if (y == 0) |
1364 | tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; | 1393 | { |
1365 | } | 1394 | curByte |= LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; |
1366 | else if (westParcel != null && westParcel != currentParcelBlock) | 1395 | tmpByte = curByte; |
1367 | { | 1396 | } |
1368 | tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; | 1397 | else |
1369 | } | 1398 | { |
1399 | tmpByte = curByte; | ||
1400 | southID = GetLandObjectIDinLandUnits(x, (y - 1)); | ||
1401 | if (southID >= 0 && southID != curID) | ||
1402 | tmpByte |= LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; | ||
1403 | } | ||
1404 | |||
1405 | tmpByte |= LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST; | ||
1406 | byteArray[byteArrayCount] = tmpByte; | ||
1407 | byteArrayCount++; | ||
1370 | 1408 | ||
1371 | if (y == 0) | 1409 | if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) |
1410 | { | ||
1411 | remote_client.SendLandParcelOverlay(byteArray, sequenceID); | ||
1412 | byteArrayCount = 0; | ||
1413 | sequenceID++; | ||
1414 | byteArray = new byte[LAND_BLOCKS_PER_PACKET]; | ||
1415 | } | ||
1416 | // keep adding while on same parcel, checking south border | ||
1417 | if (y == 0) | ||
1418 | { | ||
1419 | // all have south border and that is already on curByte | ||
1420 | while (++x < sx && GetLandObjectIDinLandUnits(x, y) == curID) | ||
1372 | { | 1421 | { |
1373 | tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; | 1422 | byteArray[byteArrayCount] = curByte; |
1423 | byteArrayCount++; | ||
1424 | if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) | ||
1425 | { | ||
1426 | remote_client.SendLandParcelOverlay(byteArray, sequenceID); | ||
1427 | byteArrayCount = 0; | ||
1428 | sequenceID++; | ||
1429 | byteArray = new byte[LAND_BLOCKS_PER_PACKET]; | ||
1430 | } | ||
1374 | } | 1431 | } |
1375 | else if (southParcel != null && southParcel != currentParcelBlock) | 1432 | } |
1433 | else | ||
1434 | { | ||
1435 | while (++x < sx && GetLandObjectIDinLandUnits(x, y) == curID) | ||
1376 | { | 1436 | { |
1377 | tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; | 1437 | // need to check south one by one |
1378 | } | 1438 | southID = GetLandObjectIDinLandUnits(x, (y - 1)); |
1379 | 1439 | if (southID >= 0 && southID != curID) | |
1380 | // local sound | 1440 | { |
1381 | if ((currentParcelBlock.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0) | 1441 | tmpByte = curByte; |
1382 | tempByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND; | 1442 | tmpByte |= LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH; |
1383 | 1443 | byteArray[byteArrayCount] = tmpByte; | |
1384 | // hide avatars | 1444 | } |
1385 | if (!currentParcelBlock.LandData.SeeAVs) | 1445 | else |
1386 | tempByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS; | 1446 | byteArray[byteArrayCount] = curByte; |
1387 | |||
1388 | 1447 | ||
1389 | byteArray[byteArrayCount] = tempByte; | 1448 | byteArrayCount++; |
1390 | byteArrayCount++; | 1449 | if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) |
1391 | if (byteArrayCount >= LAND_BLOCKS_PER_PACKET) | 1450 | { |
1392 | { | 1451 | remote_client.SendLandParcelOverlay(byteArray, sequenceID); |
1393 | remote_client.SendLandParcelOverlay(byteArray, sequenceID); | 1452 | byteArrayCount = 0; |
1394 | byteArrayCount = 0; | 1453 | sequenceID++; |
1395 | sequenceID++; | 1454 | byteArray = new byte[LAND_BLOCKS_PER_PACKET]; |
1396 | byteArray = new byte[LAND_BLOCKS_PER_PACKET]; | 1455 | } |
1397 | } | 1456 | } |
1398 | } | 1457 | } |
1399 | } | 1458 | } |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 26500ab..094b0f5 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs | |||
@@ -1841,7 +1841,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
1841 | UUID lgid = LandData.GlobalID; | 1841 | UUID lgid = LandData.GlobalID; |
1842 | m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) | 1842 | m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) |
1843 | { | 1843 | { |
1844 | if(sp.IsNPC || sp.IsLoggingIn || sp.IsDeleted || sp.currentParcelUUID != lgid) | 1844 | if(sp.IsNPC || sp.IsDeleted || sp.currentParcelUUID != lgid) |
1845 | return; | 1845 | return; |
1846 | cur += (now - sp.ParcelDwellTickMS); | 1846 | cur += (now - sp.ParcelDwellTickMS); |
1847 | sp.ParcelDwellTickMS = now; | 1847 | sp.ParcelDwellTickMS = now; |
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs index f5aa40a..66a7df1 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs | |||
@@ -219,9 +219,13 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap | |||
219 | lock (media) | 219 | lock (media) |
220 | me = media[face]; | 220 | me = media[face]; |
221 | 221 | ||
222 | // TODO: Really need a proper copy constructor down in libopenmetaverse | ||
223 | if (me != null) | 222 | if (me != null) |
224 | me = MediaEntry.FromOSD(me.GetOSD()); | 223 | { |
224 | Primitive.TextureEntry te = part.Shape.Textures; | ||
225 | Primitive.TextureEntryFace teFace = te.GetFace((uint)face); | ||
226 | if (teFace != null && teFace.MediaFlags) | ||
227 | me = MediaEntry.FromOSD(me.GetOSD()); | ||
228 | } | ||
225 | } | 229 | } |
226 | 230 | ||
227 | // m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me); | 231 | // m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me); |
@@ -336,15 +340,40 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap | |||
336 | return string.Empty; | 340 | return string.Empty; |
337 | } | 341 | } |
338 | 342 | ||
339 | if (null == part.Shape.Media) | 343 | if (part.Shape.Media == null) |
340 | return string.Empty; | 344 | return string.Empty; |
341 | 345 | ||
342 | ObjectMediaResponse resp = new ObjectMediaResponse(); | 346 | MediaEntry[] currentML = part.Shape.Media.ToArray(); |
347 | |||
348 | int nentries = currentML.Length; | ||
349 | int nsides = part.GetNumberOfSides(); | ||
350 | if(nentries > nsides) | ||
351 | nentries = nsides; | ||
343 | 352 | ||
353 | Primitive.TextureEntry te = part.Shape.Textures; | ||
354 | bool isnull = true; | ||
355 | |||
356 | for(int face = 0; face < nentries; ++face) | ||
357 | { | ||
358 | Primitive.TextureEntryFace teFace = te.GetFace((uint)face); | ||
359 | if(!teFace.MediaFlags) | ||
360 | currentML[face] = null; | ||
361 | else | ||
362 | isnull = false; | ||
363 | } | ||
364 | |||
365 | if(isnull) | ||
366 | { | ||
367 | //remove the damm thing | ||
368 | part.Shape.Media = null; | ||
369 | part.MediaUrl = null; | ||
370 | return string.Empty; | ||
371 | } | ||
372 | |||
373 | ObjectMediaResponse resp = new ObjectMediaResponse(); | ||
344 | resp.PrimID = primId; | 374 | resp.PrimID = primId; |
345 | 375 | ||
346 | lock (part.Shape.Media) | 376 | resp.FaceMedia = currentML; |
347 | resp.FaceMedia = part.Shape.Media.ToArray(); | ||
348 | 377 | ||
349 | resp.Version = part.MediaUrl; | 378 | resp.Version = part.MediaUrl; |
350 | 379 | ||
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 99cf121..f927573 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs | |||
@@ -790,7 +790,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap | |||
790 | try | 790 | try |
791 | { | 791 | { |
792 | using (Bitmap img = (Bitmap)m_imgDecoder.DecodeToImage(asset)) | 792 | using (Bitmap img = (Bitmap)m_imgDecoder.DecodeToImage(asset)) |
793 | ret = new warp_Texture(img); | 793 | ret = new warp_Texture(img, 8); // reduce textures size to 256x256 |
794 | } | 794 | } |
795 | catch (Exception e) | 795 | catch (Exception e) |
796 | { | 796 | { |
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index da54c54..15294c3 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | |||
@@ -406,16 +406,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
406 | 406 | ||
407 | WorkManager.StartThread( | 407 | WorkManager.StartThread( |
408 | process, | 408 | process, |
409 | string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName), | 409 | string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName)); |
410 | ThreadPriority.BelowNormal, | ||
411 | true, | ||
412 | false); | ||
413 | WorkManager.StartThread( | 410 | WorkManager.StartThread( |
414 | MapBlockSendThread, | 411 | MapBlockSendThread, |
415 | string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName), | 412 | string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName)); |
416 | ThreadPriority.BelowNormal, | ||
417 | true, | ||
418 | false); | ||
419 | } | 413 | } |
420 | 414 | ||
421 | /// <summary> | 415 | /// <summary> |
@@ -482,7 +476,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
482 | // viewers only ask for green dots to each region now | 476 | // viewers only ask for green dots to each region now |
483 | // except at login with regionhandle 0 | 477 | // except at login with regionhandle 0 |
484 | // possible on some other rare ocasions | 478 | // possible on some other rare ocasions |
485 | // use previus hack of sending all items with the green dots | 479 | // use previous hack of sending all items with the green dots |
486 | 480 | ||
487 | bool adultRegion; | 481 | bool adultRegion; |
488 | if (regionhandle == 0) | 482 | if (regionhandle == 0) |
@@ -1189,6 +1183,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
1189 | return; | 1183 | return; |
1190 | 1184 | ||
1191 | GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags); | 1185 | GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags); |
1186 | Watchdog.UpdateThread(); | ||
1192 | } | 1187 | } |
1193 | 1188 | ||
1194 | thisRunData.Clear(); | 1189 | thisRunData.Clear(); |
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 1b690ba..9377564 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs | |||
@@ -90,6 +90,8 @@ namespace OpenSim.Region.Framework.Interfaces | |||
90 | void AgentArrivedAtDestination(UUID agent); | 90 | void AgentArrivedAtDestination(UUID agent); |
91 | 91 | ||
92 | void EnableChildAgents(ScenePresence agent); | 92 | void EnableChildAgents(ScenePresence agent); |
93 | void CheckChildAgents(ScenePresence agent); | ||
94 | void CloseOldChildAgents(ScenePresence agent); | ||
93 | 95 | ||
94 | void EnableChildAgent(ScenePresence agent, GridRegion region); | 96 | void EnableChildAgent(ScenePresence agent, GridRegion region); |
95 | 97 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 0c080d2..2995091 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | |||
@@ -153,10 +153,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
153 | /// <param name="remoteClient"></param> | 153 | /// <param name="remoteClient"></param> |
154 | public void RequestPrim(uint primLocalID, IClientAPI remoteClient) | 154 | public void RequestPrim(uint primLocalID, IClientAPI remoteClient) |
155 | { | 155 | { |
156 | SceneObjectGroup sog = GetGroupByPrim(primLocalID); | 156 | SceneObjectPart part = GetSceneObjectPart(primLocalID); |
157 | if (part != null) | ||
158 | { | ||
159 | SceneObjectGroup sog = part.ParentGroup; | ||
160 | if(!sog.IsDeleted) | ||
161 | { | ||
162 | PrimUpdateFlags update = PrimUpdateFlags.FullUpdate; | ||
163 | if (sog.RootPart.Shape.MeshFlagEntry) | ||
164 | update = PrimUpdateFlags.FullUpdatewithAnim; | ||
165 | part.SendUpdate(remoteClient, update); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | //SceneObjectGroup sog = GetGroupByPrim(primLocalID); | ||
157 | 170 | ||
158 | if (sog != null) | 171 | //if (sog != null) |
159 | sog.SendFullAnimUpdateToClient(remoteClient); | 172 | //sog.SendFullAnimUpdateToClient(remoteClient); |
160 | } | 173 | } |
161 | 174 | ||
162 | /// <summary> | 175 | /// <summary> |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7668a87..073d11f 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -170,8 +170,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
170 | } | 170 | } |
171 | private bool m_scripts_enabled; | 171 | private bool m_scripts_enabled; |
172 | 172 | ||
173 | public SynchronizeSceneHandler SynchronizeScene; | ||
174 | |||
175 | public bool ClampNegativeZ | 173 | public bool ClampNegativeZ |
176 | { | 174 | { |
177 | get { return m_clampNegativeZ; } | 175 | get { return m_clampNegativeZ; } |
@@ -277,6 +275,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
277 | get { return m_maxRegionViewDistance; } | 275 | get { return m_maxRegionViewDistance; } |
278 | } | 276 | } |
279 | 277 | ||
278 | protected float m_minRegionViewDistance = 96f; | ||
279 | public float MinRegionViewDistance | ||
280 | { | ||
281 | get { return m_minRegionViewDistance; } | ||
282 | } | ||
283 | |||
280 | private List<string> m_AllowedViewers = new List<string>(); | 284 | private List<string> m_AllowedViewers = new List<string>(); |
281 | private List<string> m_BannedViewers = new List<string>(); | 285 | private List<string> m_BannedViewers = new List<string>(); |
282 | 286 | ||
@@ -922,6 +926,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
922 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); | 926 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); |
923 | m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance); | 927 | m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance); |
924 | m_maxRegionViewDistance = startupConfig.GetFloat("MaxRegionsViewDistance", m_maxRegionViewDistance); | 928 | m_maxRegionViewDistance = startupConfig.GetFloat("MaxRegionsViewDistance", m_maxRegionViewDistance); |
929 | m_minRegionViewDistance = startupConfig.GetFloat("MinRegionsViewDistance", m_minRegionViewDistance); | ||
925 | 930 | ||
926 | // old versions compatibility | 931 | // old versions compatibility |
927 | LegacySitOffsets = startupConfig.GetBoolean("LegacySitOffsets", LegacySitOffsets); | 932 | LegacySitOffsets = startupConfig.GetBoolean("LegacySitOffsets", LegacySitOffsets); |
@@ -932,6 +937,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
932 | if (m_maxRegionViewDistance > m_maxDrawDistance) | 937 | if (m_maxRegionViewDistance > m_maxDrawDistance) |
933 | m_maxRegionViewDistance = m_maxDrawDistance; | 938 | m_maxRegionViewDistance = m_maxDrawDistance; |
934 | 939 | ||
940 | if(m_minRegionViewDistance < 96f) | ||
941 | m_minRegionViewDistance = 96f; | ||
942 | if(m_minRegionViewDistance > m_maxRegionViewDistance) | ||
943 | m_minRegionViewDistance = m_maxRegionViewDistance; | ||
944 | |||
935 | UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); | 945 | UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); |
936 | if (!UseBackup) | 946 | if (!UseBackup) |
937 | m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); | 947 | m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); |
@@ -1006,11 +1016,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1006 | m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete); | 1016 | m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete); |
1007 | m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); | 1017 | m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); |
1008 | m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); | 1018 | m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); |
1009 | m_dontPersistBefore = | 1019 | m_dontPersistBefore = startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); |
1010 | startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); | ||
1011 | m_dontPersistBefore *= 10000000; | 1020 | m_dontPersistBefore *= 10000000; |
1012 | m_persistAfter = | 1021 | m_persistAfter = startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); |
1013 | startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); | ||
1014 | m_persistAfter *= 10000000; | 1022 | m_persistAfter *= 10000000; |
1015 | 1023 | ||
1016 | m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); | 1024 | m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); |
@@ -1290,7 +1298,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1290 | { | 1298 | { |
1291 | if (RegionInfo.RegionHandle != otherRegion.RegionHandle) | 1299 | if (RegionInfo.RegionHandle != otherRegion.RegionHandle) |
1292 | { | 1300 | { |
1293 | |||
1294 | if (isNeighborRegion(otherRegion)) | 1301 | if (isNeighborRegion(otherRegion)) |
1295 | { | 1302 | { |
1296 | // Let the grid service module know, so this can be cached | 1303 | // Let the grid service module know, so this can be cached |
@@ -1300,9 +1307,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1300 | { | 1307 | { |
1301 | ForEachRootScenePresence(delegate(ScenePresence agent) | 1308 | ForEachRootScenePresence(delegate(ScenePresence agent) |
1302 | { | 1309 | { |
1303 | //agent.ControllingClient.new | ||
1304 | //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); | ||
1305 | |||
1306 | List<ulong> old = new List<ulong>(); | 1310 | List<ulong> old = new List<ulong>(); |
1307 | old.Add(otherRegion.RegionHandle); | 1311 | old.Add(otherRegion.RegionHandle); |
1308 | agent.DropOldNeighbours(old); | 1312 | agent.DropOldNeighbours(old); |
@@ -1328,7 +1332,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1328 | 1332 | ||
1329 | public bool isNeighborRegion(GridRegion otherRegion) | 1333 | public bool isNeighborRegion(GridRegion otherRegion) |
1330 | { | 1334 | { |
1331 | int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; ; | 1335 | int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; |
1332 | 1336 | ||
1333 | if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX) | 1337 | if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX) |
1334 | return false; | 1338 | return false; |
@@ -1695,9 +1699,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1695 | { | 1699 | { |
1696 | if (PhysicsEnabled) | 1700 | if (PhysicsEnabled) |
1697 | physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime); | 1701 | physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime); |
1698 | |||
1699 | if (SynchronizeScene != null) | ||
1700 | SynchronizeScene(this); | ||
1701 | } | 1702 | } |
1702 | 1703 | ||
1703 | tmpMS2 = Util.GetTimeStampMS(); | 1704 | tmpMS2 = Util.GetTimeStampMS(); |
@@ -1775,30 +1776,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1775 | 1776 | ||
1776 | // Region ready should always be set | 1777 | // Region ready should always be set |
1777 | Ready = true; | 1778 | Ready = true; |
1778 | |||
1779 | |||
1780 | IConfig restartConfig = m_config.Configs["RestartModule"]; | ||
1781 | if (restartConfig != null) | ||
1782 | { | ||
1783 | string markerPath = restartConfig.GetString("MarkerPath", String.Empty); | ||
1784 | |||
1785 | if (markerPath != String.Empty) | ||
1786 | { | ||
1787 | string path = Path.Combine(markerPath, RegionInfo.RegionID.ToString() + ".ready"); | ||
1788 | try | ||
1789 | { | ||
1790 | string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); | ||
1791 | FileStream fs = File.Create(path); | ||
1792 | System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); | ||
1793 | Byte[] buf = enc.GetBytes(pidstring); | ||
1794 | fs.Write(buf, 0, buf.Length); | ||
1795 | fs.Close(); | ||
1796 | } | ||
1797 | catch (Exception) | ||
1798 | { | ||
1799 | } | ||
1800 | } | ||
1801 | } | ||
1802 | } | 1779 | } |
1803 | else | 1780 | else |
1804 | { | 1781 | { |
@@ -4818,6 +4795,20 @@ Label_GroupsDone: | |||
4818 | return true; | 4795 | return true; |
4819 | } | 4796 | } |
4820 | 4797 | ||
4798 | |||
4799 | /// <summary> | ||
4800 | /// Tries to teleport agent within region. | ||
4801 | /// </summary> | ||
4802 | /// <param name="remoteClient"></param> | ||
4803 | /// <param name="position"></param> | ||
4804 | /// <param name="lookAt"></param> | ||
4805 | /// <param name="teleportFlags"></param> | ||
4806 | public void RequestLocalTeleport(ScenePresence sp, Vector3 position, Vector3 vel, | ||
4807 | Vector3 lookat, int flags) | ||
4808 | { | ||
4809 | sp.LocalTeleport(position, vel, lookat, flags); | ||
4810 | } | ||
4811 | |||
4821 | /// <summary> | 4812 | /// <summary> |
4822 | /// Tries to teleport agent to another region. | 4813 | /// Tries to teleport agent to another region. |
4823 | /// </summary> | 4814 | /// </summary> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 7d5bbbf..c0bafc5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -119,6 +119,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
119 | 119 | ||
120 | // private PrimCountTaintedDelegate handlerPrimCountTainted = null; | 120 | // private PrimCountTaintedDelegate handlerPrimCountTainted = null; |
121 | 121 | ||
122 | public bool IsViewerCachable | ||
123 | { | ||
124 | get | ||
125 | { | ||
126 | // needs more exclusion ? | ||
127 | return(Backup && !IsTemporary && !inTransit && !IsSelected && !UsesPhysics && !IsAttachmentCheckFull() && | ||
128 | !RootPart.Shape.MeshFlagEntry && // animations are not sent correctly for now | ||
129 | RootPart.KeyframeMotion == null && | ||
130 | (DateTime.UtcNow.Ticks - timeLastChanged > 36000000000) && //36000000000 is one hour | ||
131 | RootPart.Velocity.LengthSquared() < 1e8f && // should not be needed | ||
132 | RootPart.Acceleration.LengthSquared() < 1e4f // should not be needed | ||
133 | ); | ||
134 | } | ||
135 | } | ||
136 | |||
122 | /// <summary> | 137 | /// <summary> |
123 | /// Signal whether the non-inventory attributes of any prims in the group have changed | 138 | /// Signal whether the non-inventory attributes of any prims in the group have changed |
124 | /// since the group's last persistent backup | 139 | /// since the group's last persistent backup |
@@ -128,7 +143,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
128 | private long timeLastChanged = 0; | 143 | private long timeLastChanged = 0; |
129 | private long m_maxPersistTime = 0; | 144 | private long m_maxPersistTime = 0; |
130 | private long m_minPersistTime = 0; | 145 | private long m_minPersistTime = 0; |
131 | // private Random m_rand; | 146 | |
147 | public int PseudoCRC; | ||
132 | 148 | ||
133 | /// <summary> | 149 | /// <summary> |
134 | /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage | 150 | /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage |
@@ -145,40 +161,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
145 | { | 161 | { |
146 | if (value) | 162 | if (value) |
147 | { | 163 | { |
148 | |||
149 | if (Backup) | 164 | if (Backup) |
150 | { | ||
151 | m_scene.SceneGraph.FireChangeBackup(this); | 165 | m_scene.SceneGraph.FireChangeBackup(this); |
152 | } | 166 | |
167 | PseudoCRC = (int)(DateTime.UtcNow.Ticks); ; | ||
153 | timeLastChanged = DateTime.UtcNow.Ticks; | 168 | timeLastChanged = DateTime.UtcNow.Ticks; |
154 | if (!m_hasGroupChanged) | 169 | if (!m_hasGroupChanged) |
155 | timeFirstChanged = DateTime.UtcNow.Ticks; | 170 | timeFirstChanged = timeLastChanged; |
156 | if (m_rootPart != null && m_scene != null) | 171 | if (m_rootPart != null && m_scene != null) |
157 | { | 172 | { |
158 | /* | ||
159 | if (m_rand == null) | ||
160 | { | ||
161 | byte[] val = new byte[16]; | ||
162 | m_rootPart.UUID.ToBytes(val, 0); | ||
163 | m_rand = new Random(BitConverter.ToInt32(val, 0)); | ||
164 | } | ||
165 | */ | ||
166 | if (m_scene.GetRootAgentCount() == 0) | 173 | if (m_scene.GetRootAgentCount() == 0) |
167 | { | 174 | { |
168 | //If the region is empty, this change has been made by an automated process | 175 | //If the region is empty, this change has been made by an automated process |
169 | //and thus we delay the persist time by a random amount between 1.5 and 2.5. | 176 | //and thus we delay the persist time by a random amount between 1.5 and 2.5. |
170 | 177 | ||
171 | // float factor = 1.5f + (float)(m_rand.NextDouble()); | ||
172 | float factor = 2.0f; | 178 | float factor = 2.0f; |
173 | m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor); | 179 | m_maxPersistTime = (long)(m_scene.m_persistAfter * factor); |
174 | m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor); | 180 | m_minPersistTime = (long)(m_scene.m_dontPersistBefore * factor); |
175 | } | 181 | } |
176 | else | 182 | else |
177 | { | 183 | { |
178 | //If the region is not empty, we want to obey the minimum and maximum persist times | ||
179 | //but add a random factor so we stagger the object persistance a little | ||
180 | // m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 | ||
181 | // m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 | ||
182 | m_maxPersistTime = m_scene.m_persistAfter; | 184 | m_maxPersistTime = m_scene.m_persistAfter; |
183 | m_minPersistTime = m_scene.m_dontPersistBefore; | 185 | m_minPersistTime = m_scene.m_dontPersistBefore; |
184 | } | 186 | } |
@@ -768,9 +770,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
768 | } | 770 | } |
769 | 771 | ||
770 | if(av.IsNPC) | 772 | if(av.IsNPC) |
771 | av.crossingFlags = 0; | 773 | av.m_crossingFlags = 0; |
772 | else | 774 | else |
773 | av.crossingFlags = cflags; | 775 | av.m_crossingFlags = cflags; |
774 | 776 | ||
775 | av.PrevSitOffset = av.OffsetPosition; | 777 | av.PrevSitOffset = av.OffsetPosition; |
776 | av.ParentID = 0; | 778 | av.ParentID = 0; |
@@ -819,7 +821,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
819 | if(entityTransfer.CrossAgentCreateFarChild(av,destination, newpos, ctx)) | 821 | if(entityTransfer.CrossAgentCreateFarChild(av,destination, newpos, ctx)) |
820 | crossedfar = true; | 822 | crossedfar = true; |
821 | else | 823 | else |
822 | av.crossingFlags = 0; | 824 | av.m_crossingFlags = 0; |
823 | } | 825 | } |
824 | 826 | ||
825 | if(crossedfar) | 827 | if(crossedfar) |
@@ -832,7 +834,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
832 | av.IsInTransit = true; | 834 | av.IsInTransit = true; |
833 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); | 835 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); |
834 | 836 | ||
835 | if(av.crossingFlags > 0) | 837 | if(av.m_crossingFlags > 0) |
836 | entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, false, ctx); | 838 | entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, false, ctx); |
837 | 839 | ||
838 | if (av.IsChildAgent) | 840 | if (av.IsChildAgent) |
@@ -847,7 +849,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
847 | av.ParentPart = null; | 849 | av.ParentPart = null; |
848 | // In any case | 850 | // In any case |
849 | av.IsInTransit = false; | 851 | av.IsInTransit = false; |
850 | av.crossingFlags = 0; | 852 | av.m_crossingFlags = 0; |
851 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname); | 853 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname); |
852 | } | 854 | } |
853 | else | 855 | else |
@@ -863,7 +865,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
863 | oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f); | 865 | oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f); |
864 | oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f); | 866 | oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f); |
865 | av.AbsolutePosition = oldp; | 867 | av.AbsolutePosition = oldp; |
866 | av.crossingFlags = 0; | 868 | av.m_crossingFlags = 0; |
867 | av.sitAnimation = "SIT"; | 869 | av.sitAnimation = "SIT"; |
868 | av.IsInTransit = false; | 870 | av.IsInTransit = false; |
869 | if(av.Animator!= null) | 871 | if(av.Animator!= null) |
@@ -924,7 +926,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
924 | ScenePresence av = avinfo.av; | 926 | ScenePresence av = avinfo.av; |
925 | av.ParentUUID = UUID.Zero; | 927 | av.ParentUUID = UUID.Zero; |
926 | av.ParentID = avinfo.ParentID; | 928 | av.ParentID = avinfo.ParentID; |
927 | av.crossingFlags = 0; | 929 | av.m_crossingFlags = 0; |
928 | } | 930 | } |
929 | } | 931 | } |
930 | avsToCross.Clear(); | 932 | avsToCross.Clear(); |
@@ -1330,6 +1332,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1330 | public SceneObjectGroup() | 1332 | public SceneObjectGroup() |
1331 | { | 1333 | { |
1332 | m_lastCollisionSoundMS = Util.GetTimeStampMS() + 1000.0; | 1334 | m_lastCollisionSoundMS = Util.GetTimeStampMS() + 1000.0; |
1335 | PseudoCRC = (int)(DateTime.UtcNow.Ticks); | ||
1333 | } | 1336 | } |
1334 | 1337 | ||
1335 | /// <summary> | 1338 | /// <summary> |
@@ -2441,6 +2444,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
2441 | } | 2444 | } |
2442 | } | 2445 | } |
2443 | 2446 | ||
2447 | public void SendUpdateProbes(IClientAPI remoteClient) | ||
2448 | { | ||
2449 | PrimUpdateFlags update = PrimUpdateFlags.UpdateProbe; | ||
2450 | |||
2451 | RootPart.SendUpdate(remoteClient, update); | ||
2452 | |||
2453 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
2454 | for (int i = 0; i < parts.Length; i++) | ||
2455 | { | ||
2456 | SceneObjectPart part = parts[i]; | ||
2457 | if (part != RootPart) | ||
2458 | part.SendUpdate(remoteClient, update); | ||
2459 | } | ||
2460 | } | ||
2461 | |||
2444 | #region Copying | 2462 | #region Copying |
2445 | 2463 | ||
2446 | /// <summary> | 2464 | /// <summary> |
@@ -2516,6 +2534,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2516 | } | 2534 | } |
2517 | 2535 | ||
2518 | dupe.InvalidatePartsLinkMaps(); | 2536 | dupe.InvalidatePartsLinkMaps(); |
2537 | dupe.PseudoCRC = (int)(DateTime.UtcNow.Ticks); | ||
2519 | m_dupeInProgress = false; | 2538 | m_dupeInProgress = false; |
2520 | return dupe; | 2539 | return dupe; |
2521 | } | 2540 | } |
@@ -2769,6 +2788,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2769 | } | 2788 | } |
2770 | } | 2789 | } |
2771 | 2790 | ||
2791 | PseudoCRC = (int)(DateTime.UtcNow.Ticks); | ||
2772 | rpart.ScheduleFullUpdate(); | 2792 | rpart.ScheduleFullUpdate(); |
2773 | } | 2793 | } |
2774 | 2794 | ||
@@ -2808,6 +2828,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2808 | part.ResetIDs(part.LinkNum); // Don't change link nums | 2828 | part.ResetIDs(part.LinkNum); // Don't change link nums |
2809 | m_parts.Add(part.UUID, part); | 2829 | m_parts.Add(part.UUID, part); |
2810 | } | 2830 | } |
2831 | PseudoCRC = (int)(DateTime.UtcNow.Ticks); | ||
2811 | } | 2832 | } |
2812 | } | 2833 | } |
2813 | 2834 | ||
@@ -3117,7 +3138,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3117 | } | 3138 | } |
3118 | } | 3139 | } |
3119 | 3140 | ||
3120 | |||
3121 | // 'linkPart' == the root of the group being linked into this group | 3141 | // 'linkPart' == the root of the group being linked into this group |
3122 | SceneObjectPart linkPart = objectGroup.m_rootPart; | 3142 | SceneObjectPart linkPart = objectGroup.m_rootPart; |
3123 | 3143 | ||
@@ -3160,7 +3180,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3160 | axPos *= Quaternion.Conjugate(parentRot); | 3180 | axPos *= Quaternion.Conjugate(parentRot); |
3161 | linkPart.OffsetPosition = axPos; | 3181 | linkPart.OffsetPosition = axPos; |
3162 | 3182 | ||
3163 | |||
3164 | // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. | 3183 | // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. |
3165 | // Now that we know this SOG has at least two SOPs in it, the new root | 3184 | // Now that we know this SOG has at least two SOPs in it, the new root |
3166 | // SOP becomes the first in the linkset. | 3185 | // SOP becomes the first in the linkset. |
@@ -3193,8 +3212,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3193 | 3212 | ||
3194 | linkPart.CreateSelected = true; | 3213 | linkPart.CreateSelected = true; |
3195 | 3214 | ||
3196 | // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now | 3215 | linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive || RootPart.VolumeDetectActive, true); |
3197 | linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true); | ||
3198 | 3216 | ||
3199 | // If the added SOP is physical, also tell the physics engine about the link relationship. | 3217 | // If the added SOP is physical, also tell the physics engine about the link relationship. |
3200 | if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) | 3218 | if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 312ce26..5e2204e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -312,7 +312,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
312 | private Quaternion m_sitTargetOrientation = Quaternion.Identity; | 312 | private Quaternion m_sitTargetOrientation = Quaternion.Identity; |
313 | private Vector3 m_sitTargetPosition; | 313 | private Vector3 m_sitTargetPosition; |
314 | private string m_sitAnimation = "SIT"; | 314 | private string m_sitAnimation = "SIT"; |
315 | private bool m_occupied; // KF if any av is sitting on this prim | ||
316 | private string m_text = String.Empty; | 315 | private string m_text = String.Empty; |
317 | private string m_touchName = String.Empty; | 316 | private string m_touchName = String.Empty; |
318 | private UndoRedoState m_UndoRedo = null; | 317 | private UndoRedoState m_UndoRedo = null; |
@@ -1001,7 +1000,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1001 | get | 1000 | get |
1002 | { | 1001 | { |
1003 | PhysicsActor actor = PhysActor; | 1002 | PhysicsActor actor = PhysActor; |
1004 | if (actor != null) | 1003 | if (actor != null && actor.IsPhysical) |
1005 | { | 1004 | { |
1006 | m_acceleration = actor.Acceleration; | 1005 | m_acceleration = actor.Acceleration; |
1007 | } | 1006 | } |
@@ -1038,8 +1037,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1038 | { | 1037 | { |
1039 | get | 1038 | get |
1040 | { | 1039 | { |
1041 | if (m_text.Length > 256) // yes > 254 | 1040 | if (m_text.Length > 254) |
1042 | return m_text.Substring(0, 256); | 1041 | return m_text.Substring(0, 254); |
1043 | return m_text; | 1042 | return m_text; |
1044 | } | 1043 | } |
1045 | set { m_text = value; } | 1044 | set { m_text = value; } |
@@ -1179,9 +1178,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1179 | 1178 | ||
1180 | set | 1179 | set |
1181 | { | 1180 | { |
1181 | string old = m_mediaUrl; | ||
1182 | m_mediaUrl = value; | 1182 | m_mediaUrl = value; |
1183 | 1183 | ||
1184 | if (ParentGroup != null) | 1184 | if (ParentGroup != null && old != m_mediaUrl) |
1185 | ParentGroup.HasGroupChanged = true; | 1185 | ParentGroup.HasGroupChanged = true; |
1186 | } | 1186 | } |
1187 | } | 1187 | } |
@@ -1385,13 +1385,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1385 | } | 1385 | } |
1386 | } | 1386 | } |
1387 | 1387 | ||
1388 | [XmlIgnore] | ||
1389 | public bool IsOccupied // KF If an av is sittingon this prim | ||
1390 | { | ||
1391 | get { return m_occupied; } | ||
1392 | set { m_occupied = value; } | ||
1393 | } | ||
1394 | |||
1395 | /// <summary> | 1388 | /// <summary> |
1396 | /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero | 1389 | /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero |
1397 | /// </summary> | 1390 | /// </summary> |
@@ -2338,10 +2331,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2338 | { | 2331 | { |
2339 | ParentGroup.Scene.RemovePhysicalPrim(1); | 2332 | ParentGroup.Scene.RemovePhysicalPrim(1); |
2340 | 2333 | ||
2341 | Velocity = new Vector3(0, 0, 0); | 2334 | Stop(); |
2342 | Acceleration = new Vector3(0, 0, 0); | ||
2343 | AngularVelocity = new Vector3(0, 0, 0); | ||
2344 | APIDActive = false; | ||
2345 | 2335 | ||
2346 | if (pa.Phantom && !VolumeDetectActive) | 2336 | if (pa.Phantom && !VolumeDetectActive) |
2347 | { | 2337 | { |
@@ -2475,13 +2465,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2475 | 2465 | ||
2476 | public uint GetEffectiveObjectFlags() | 2466 | public uint GetEffectiveObjectFlags() |
2477 | { | 2467 | { |
2478 | // Commenting this section of code out since it doesn't actually do anything, as enums are handled by | 2468 | uint eff = (uint)Flags | (uint)LocalFlags; |
2479 | // value rather than reference | 2469 | if(m_inventory == null || m_inventory.Count == 0) |
2480 | // PrimFlags f = _flags; | 2470 | eff |= (uint)PrimFlags.InventoryEmpty; |
2481 | // if (m_parentGroup == null || m_parentGroup.RootPart == this) | 2471 | return eff; |
2482 | // f &= ~(PrimFlags.Touch | PrimFlags.Money); | ||
2483 | |||
2484 | return (uint)Flags | (uint)LocalFlags; | ||
2485 | } | 2472 | } |
2486 | 2473 | ||
2487 | // some of this lines need be moved to other place later | 2474 | // some of this lines need be moved to other place later |
@@ -3896,15 +3883,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
3896 | { | 3883 | { |
3897 | if (Shape.SculptEntry && !ignoreSculpt) | 3884 | if (Shape.SculptEntry && !ignoreSculpt) |
3898 | return PrimType.SCULPT; | 3885 | return PrimType.SCULPT; |
3899 | 3886 | ProfileShape ps = (ProfileShape)(Shape.ProfileCurve & 0x07); | |
3900 | if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | 3887 | if (ps == ProfileShape.Square) |
3901 | { | 3888 | { |
3902 | if (Shape.PathCurve == (byte)Extrusion.Straight) | 3889 | if (Shape.PathCurve == (byte)Extrusion.Straight) |
3903 | return PrimType.BOX; | 3890 | return PrimType.BOX; |
3904 | else if (Shape.PathCurve == (byte)Extrusion.Curve1) | 3891 | else if (Shape.PathCurve == (byte)Extrusion.Curve1) |
3905 | return PrimType.TUBE; | 3892 | return PrimType.TUBE; |
3906 | } | 3893 | } |
3907 | else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | 3894 | else if (ps == ProfileShape.Circle) |
3908 | { | 3895 | { |
3909 | if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible) | 3896 | if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible) |
3910 | return PrimType.CYLINDER; | 3897 | return PrimType.CYLINDER; |
@@ -3912,12 +3899,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3912 | else if (Shape.PathCurve == (byte)Extrusion.Curve1) | 3899 | else if (Shape.PathCurve == (byte)Extrusion.Curve1) |
3913 | return PrimType.TORUS; | 3900 | return PrimType.TORUS; |
3914 | } | 3901 | } |
3915 | else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | 3902 | else if (ps == ProfileShape.HalfCircle) |
3916 | { | 3903 | { |
3917 | if (Shape.PathCurve == (byte)Extrusion.Curve1 || Shape.PathCurve == (byte)Extrusion.Curve2) | 3904 | if (Shape.PathCurve == (byte)Extrusion.Curve1 || Shape.PathCurve == (byte)Extrusion.Curve2) |
3918 | return PrimType.SPHERE; | 3905 | return PrimType.SPHERE; |
3919 | } | 3906 | } |
3920 | else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | 3907 | else if (ps == ProfileShape.EquilateralTriangle) |
3921 | { | 3908 | { |
3922 | if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible) | 3909 | if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible) |
3923 | return PrimType.PRISM; | 3910 | return PrimType.PRISM; |
@@ -4004,9 +3991,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
4004 | /// <param name="text"></param> | 3991 | /// <param name="text"></param> |
4005 | public void SetText(string text) | 3992 | public void SetText(string text) |
4006 | { | 3993 | { |
4007 | Text = text; | 3994 | string oldtext = m_text; |
3995 | m_text = text; | ||
4008 | 3996 | ||
4009 | if (ParentGroup != null) | 3997 | if (ParentGroup != null && oldtext != text) |
4010 | { | 3998 | { |
4011 | ParentGroup.HasGroupChanged = true; | 3999 | ParentGroup.HasGroupChanged = true; |
4012 | ScheduleFullUpdate(); | 4000 | ScheduleFullUpdate(); |
@@ -4021,11 +4009,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
4021 | /// <param name="alpha"></param> | 4009 | /// <param name="alpha"></param> |
4022 | public void SetText(string text, Vector3 color, double alpha) | 4010 | public void SetText(string text, Vector3 color, double alpha) |
4023 | { | 4011 | { |
4012 | Color oldcolor = Color; | ||
4013 | string oldtext = m_text; | ||
4024 | Color = Color.FromArgb((int) (alpha*0xff), | 4014 | Color = Color.FromArgb((int) (alpha*0xff), |
4025 | (int) (color.X*0xff), | 4015 | (int) (color.X*0xff), |
4026 | (int) (color.Y*0xff), | 4016 | (int) (color.Y*0xff), |
4027 | (int) (color.Z*0xff)); | 4017 | (int) (color.Z*0xff)); |
4028 | SetText(text); | 4018 | m_text = text; |
4019 | if(ParentGroup != null && (oldcolor != Color || oldtext != m_text)) | ||
4020 | { | ||
4021 | ParentGroup.HasGroupChanged = true; | ||
4022 | ScheduleFullUpdate(); | ||
4023 | } | ||
4029 | } | 4024 | } |
4030 | 4025 | ||
4031 | public void StoreUndoState(ObjectChangeType change) | 4026 | public void StoreUndoState(ObjectChangeType change) |
@@ -4722,14 +4717,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
4722 | if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none | 4717 | if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none |
4723 | || (Shape.PathCurve == (byte)Extrusion.Flexible)) | 4718 | || (Shape.PathCurve == (byte)Extrusion.Flexible)) |
4724 | { | 4719 | { |
4720 | Stop(); | ||
4725 | if (pa != null) | 4721 | if (pa != null) |
4726 | { | 4722 | { |
4727 | if(wasUsingPhysics) | 4723 | if(wasUsingPhysics) |
4728 | ParentGroup.Scene.RemovePhysicalPrim(1); | 4724 | ParentGroup.Scene.RemovePhysicalPrim(1); |
4729 | RemoveFromPhysics(); | 4725 | RemoveFromPhysics(); |
4730 | } | 4726 | } |
4731 | |||
4732 | Stop(); | ||
4733 | } | 4727 | } |
4734 | 4728 | ||
4735 | else | 4729 | else |
@@ -5130,7 +5124,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
5130 | 5124 | ||
5131 | if (changeFlags == 0) | 5125 | if (changeFlags == 0) |
5132 | return; | 5126 | return; |
5133 | m_shape.TextureEntry = newTex.GetBytes(9); | 5127 | // we do need better compacter do just the trivial case |
5128 | if(nsides == 1 && newTex.FaceTextures[0] != null) | ||
5129 | { | ||
5130 | newTex.DefaultTexture = newTex.GetFace(0); | ||
5131 | newTex.FaceTextures[0] = null; | ||
5132 | } | ||
5133 | m_shape.TextureEntry = newTex.GetBytes(nsides); | ||
5134 | TriggerScriptChangedEvent(changeFlags); | 5134 | TriggerScriptChangedEvent(changeFlags); |
5135 | ParentGroup.HasGroupChanged = true; | 5135 | ParentGroup.HasGroupChanged = true; |
5136 | ScheduleUpdate(PrimUpdateFlags.Textures); | 5136 | ScheduleUpdate(PrimUpdateFlags.Textures); |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1c5d23d..f569d21 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -99,6 +99,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
99 | public bool IsViewerUIGod { get; set; } | 99 | public bool IsViewerUIGod { get; set; } |
100 | public bool IsGod { get; set; } | 100 | public bool IsGod { get; set; } |
101 | 101 | ||
102 | private bool m_gotRegionHandShake = false; | ||
103 | |||
102 | private PresenceType m_presenceType; | 104 | private PresenceType m_presenceType; |
103 | public PresenceType PresenceType | 105 | public PresenceType PresenceType |
104 | { | 106 | { |
@@ -163,6 +165,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
163 | public static readonly float MOVEMENT = .25f; | 165 | public static readonly float MOVEMENT = .25f; |
164 | public static readonly float SIGNIFICANT_MOVEMENT = 16.0f; | 166 | public static readonly float SIGNIFICANT_MOVEMENT = 16.0f; |
165 | public static readonly float CHILDUPDATES_MOVEMENT = 100.0f; | 167 | public static readonly float CHILDUPDATES_MOVEMENT = 100.0f; |
168 | public static readonly float CHILDAGENTSCHECK_MOVEMENT = 1024f; // 32m | ||
166 | public static readonly float CHILDUPDATES_TIME = 2000f; // min time between child updates (ms) | 169 | public static readonly float CHILDUPDATES_TIME = 2000f; // min time between child updates (ms) |
167 | 170 | ||
168 | private UUID m_previusParcelUUID = UUID.Zero; | 171 | private UUID m_previusParcelUUID = UUID.Zero; |
@@ -288,7 +291,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
288 | private Quaternion m_lastRotation; | 291 | private Quaternion m_lastRotation; |
289 | private Vector3 m_lastVelocity; | 292 | private Vector3 m_lastVelocity; |
290 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); | 293 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); |
291 | private bool SentInitialData = false; | 294 | private int NeedInitialData = -1; |
292 | 295 | ||
293 | private int m_userFlags; | 296 | private int m_userFlags; |
294 | public int UserFlags | 297 | public int UserFlags |
@@ -339,8 +342,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
339 | private int m_lastChildUpdatesTime; | 342 | private int m_lastChildUpdatesTime; |
340 | private int m_lastChildAgentUpdateGodLevel; | 343 | private int m_lastChildAgentUpdateGodLevel; |
341 | private float m_lastChildAgentUpdateDrawDistance; | 344 | private float m_lastChildAgentUpdateDrawDistance; |
345 | private float m_lastRegionsDrawDistance; | ||
342 | private Vector3 m_lastChildAgentUpdatePosition; | 346 | private Vector3 m_lastChildAgentUpdatePosition; |
343 | // private Vector3 m_lastChildAgentUpdateCamPosition; | 347 | private Vector3 m_lastChildAgentCheckPosition; |
348 | // private Vector3 m_lastChildAgentUpdateCamPosition; | ||
344 | 349 | ||
345 | private Vector3 m_lastCameraRayCastCam; | 350 | private Vector3 m_lastCameraRayCastCam; |
346 | private Vector3 m_lastCameraRayCastPos; | 351 | private Vector3 m_lastCameraRayCastPos; |
@@ -457,9 +462,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
457 | #region For teleports and crossings callbacks | 462 | #region For teleports and crossings callbacks |
458 | 463 | ||
459 | /// <summary> | 464 | /// <summary> |
460 | /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address. | 465 | /// the destination simulator sends ReleaseAgent to this address, for very long range tps, HG. |
461 | /// </summary> | 466 | /// </summary> |
462 | private string m_callbackURI; | 467 | private string m_callbackURI; // to remove with v1 support |
468 | private string m_newCallbackURI; | ||
463 | 469 | ||
464 | /// <summary> | 470 | /// <summary> |
465 | /// Records the region from which this presence originated, if not from login. | 471 | /// Records the region from which this presence originated, if not from login. |
@@ -595,9 +601,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
595 | public string Firstname { get; private set; } | 601 | public string Firstname { get; private set; } |
596 | public string Lastname { get; private set; } | 602 | public string Lastname { get; private set; } |
597 | 603 | ||
598 | public bool haveGroupInformation; | 604 | public bool m_haveGroupInformation; |
599 | public bool gotCrossUpdate; | 605 | public bool m_gotCrossUpdate; |
600 | public byte crossingFlags; | 606 | public byte m_crossingFlags; |
601 | 607 | ||
602 | public string Grouptitle | 608 | public string Grouptitle |
603 | { | 609 | { |
@@ -624,7 +630,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
624 | { | 630 | { |
625 | get | 631 | get |
626 | { | 632 | { |
627 | return Util.Clamp(m_drawDistance, 32f, m_scene.MaxRegionViewDistance); | 633 | return Util.Clamp(m_drawDistance + 64f, m_scene.MinRegionViewDistance, m_scene.MaxRegionViewDistance); |
628 | } | 634 | } |
629 | } | 635 | } |
630 | 636 | ||
@@ -880,7 +886,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
880 | } | 886 | } |
881 | 887 | ||
882 | public bool IsChildAgent { get; set; } | 888 | public bool IsChildAgent { get; set; } |
883 | public bool IsLoggingIn { get; set; } | ||
884 | 889 | ||
885 | /// <summary> | 890 | /// <summary> |
886 | /// If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero. | 891 | /// If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero. |
@@ -1073,12 +1078,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1073 | AttachmentsSyncLock = new Object(); | 1078 | AttachmentsSyncLock = new Object(); |
1074 | AllowMovement = true; | 1079 | AllowMovement = true; |
1075 | IsChildAgent = true; | 1080 | IsChildAgent = true; |
1076 | IsLoggingIn = false; | ||
1077 | m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; | 1081 | m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; |
1078 | Animator = new ScenePresenceAnimator(this); | 1082 | Animator = new ScenePresenceAnimator(this); |
1079 | Overrides = new MovementAnimationOverrides(); | 1083 | Overrides = new MovementAnimationOverrides(); |
1080 | PresenceType = type; | 1084 | PresenceType = type; |
1081 | DrawDistance = world.DefaultDrawDistance; | 1085 | m_drawDistance = client.StartFar; |
1086 | if(m_drawDistance > 32) | ||
1087 | { | ||
1088 | if(m_drawDistance > world.MaxDrawDistance) | ||
1089 | m_drawDistance = world.MaxDrawDistance; | ||
1090 | } | ||
1091 | else | ||
1092 | m_drawDistance = world.DefaultDrawDistance; | ||
1082 | RegionHandle = world.RegionInfo.RegionHandle; | 1093 | RegionHandle = world.RegionInfo.RegionHandle; |
1083 | ControllingClient = client; | 1094 | ControllingClient = client; |
1084 | Firstname = ControllingClient.FirstName; | 1095 | Firstname = ControllingClient.FirstName; |
@@ -1212,7 +1223,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1212 | ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; | 1223 | ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; |
1213 | ControllingClient.OnAutoPilotGo += MoveToTargetHandle; | 1224 | ControllingClient.OnAutoPilotGo += MoveToTargetHandle; |
1214 | ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles; | 1225 | ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles; |
1215 | // ControllingClient.OnAgentFOV += HandleAgentFOV; | 1226 | ControllingClient.OnRegionHandShakeReply += RegionHandShakeReply; |
1227 | |||
1228 | // ControllingClient.OnAgentFOV += HandleAgentFOV; | ||
1216 | 1229 | ||
1217 | // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); | 1230 | // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); |
1218 | // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); | 1231 | // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); |
@@ -1232,7 +1245,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1232 | ControllingClient.OnForceReleaseControls -= HandleForceReleaseControls; | 1245 | ControllingClient.OnForceReleaseControls -= HandleForceReleaseControls; |
1233 | ControllingClient.OnAutoPilotGo -= MoveToTargetHandle; | 1246 | ControllingClient.OnAutoPilotGo -= MoveToTargetHandle; |
1234 | ControllingClient.OnUpdateThrottles -= RaiseUpdateThrottles; | 1247 | ControllingClient.OnUpdateThrottles -= RaiseUpdateThrottles; |
1235 | // ControllingClient.OnAgentFOV += HandleAgentFOV; | 1248 | ControllingClient.OnRegionHandShakeReply -= RegionHandShakeReply; |
1249 | |||
1250 | // ControllingClient.OnAgentFOV += HandleAgentFOV; | ||
1236 | } | 1251 | } |
1237 | 1252 | ||
1238 | private void SetDirectionVectors() | 1253 | private void SetDirectionVectors() |
@@ -1302,13 +1317,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1302 | ParentPart = null; | 1317 | ParentPart = null; |
1303 | PrevSitOffset = Vector3.Zero; | 1318 | PrevSitOffset = Vector3.Zero; |
1304 | HandleForceReleaseControls(ControllingClient, UUID); // needs testing | 1319 | HandleForceReleaseControls(ControllingClient, UUID); // needs testing |
1305 | IsLoggingIn = false; | ||
1306 | } | 1320 | } |
1307 | else | 1321 | else |
1308 | { | 1322 | { |
1309 | part.AddSittingAvatar(this); | 1323 | part.AddSittingAvatar(this); |
1310 | // if not actually on the target invalidate it | 1324 | // if not actually on the target invalidate it |
1311 | if(gotCrossUpdate && (crossingFlags & 0x04) == 0) | 1325 | if(m_gotCrossUpdate && (m_crossingFlags & 0x04) == 0) |
1312 | part.SitTargetAvatar = UUID.Zero; | 1326 | part.SitTargetAvatar = UUID.Zero; |
1313 | 1327 | ||
1314 | ParentID = part.LocalId; | 1328 | ParentID = part.LocalId; |
@@ -1326,10 +1340,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1326 | } | 1340 | } |
1327 | ParentUUID = UUID.Zero; | 1341 | ParentUUID = UUID.Zero; |
1328 | } | 1342 | } |
1329 | else | ||
1330 | { | ||
1331 | IsLoggingIn = false; | ||
1332 | } | ||
1333 | 1343 | ||
1334 | IsChildAgent = false; | 1344 | IsChildAgent = false; |
1335 | } | 1345 | } |
@@ -1594,9 +1604,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1594 | public void MakeChildAgent(ulong newRegionHandle) | 1604 | public void MakeChildAgent(ulong newRegionHandle) |
1595 | { | 1605 | { |
1596 | m_updateAgentReceivedAfterTransferEvent.Reset(); | 1606 | m_updateAgentReceivedAfterTransferEvent.Reset(); |
1597 | haveGroupInformation = false; | 1607 | m_haveGroupInformation = false; |
1598 | gotCrossUpdate = false; | 1608 | m_gotCrossUpdate = false; |
1599 | crossingFlags = 0; | 1609 | m_crossingFlags = 0; |
1600 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; | 1610 | m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; |
1601 | 1611 | ||
1602 | RegionHandle = newRegionHandle; | 1612 | RegionHandle = newRegionHandle; |
@@ -1641,10 +1651,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1641 | m_previusParcelUUID = UUID.Zero; | 1651 | m_previusParcelUUID = UUID.Zero; |
1642 | m_currentParcelHide = false; | 1652 | m_currentParcelHide = false; |
1643 | m_currentParcelUUID = UUID.Zero; | 1653 | m_currentParcelUUID = UUID.Zero; |
1644 | // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into | 1654 | |
1645 | |||
1646 | CollisionPlane = Vector4.UnitW; | 1655 | CollisionPlane = Vector4.UnitW; |
1647 | 1656 | ||
1657 | // we need to kill this on agents that do not see the new region | ||
1658 | m_scene.ForEachRootScenePresence(delegate(ScenePresence p) | ||
1659 | { | ||
1660 | if (!p.knowsNeighbourRegion(newRegionHandle)) | ||
1661 | { | ||
1662 | SendKillTo(p); | ||
1663 | } | ||
1664 | }); | ||
1648 | m_scene.EventManager.TriggerOnMakeChildAgent(this); | 1665 | m_scene.EventManager.TriggerOnMakeChildAgent(this); |
1649 | } | 1666 | } |
1650 | 1667 | ||
@@ -1671,10 +1688,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1671 | // } | 1688 | // } |
1672 | } | 1689 | } |
1673 | 1690 | ||
1674 | /// <summary> | ||
1675 | /// Do not call this directly. Call Scene.RequestTeleportLocation() instead. | ||
1676 | /// </summary> | ||
1677 | /// <param name="pos"></param> | ||
1678 | public void Teleport(Vector3 pos) | 1691 | public void Teleport(Vector3 pos) |
1679 | { | 1692 | { |
1680 | TeleportWithMomentum(pos, Vector3.Zero); | 1693 | TeleportWithMomentum(pos, Vector3.Zero); |
@@ -1719,37 +1732,95 @@ namespace OpenSim.Region.Framework.Scenes | |||
1719 | SendTerseUpdateToAllClients(); | 1732 | SendTerseUpdateToAllClients(); |
1720 | } | 1733 | } |
1721 | 1734 | ||
1722 | public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY) | 1735 | public void LocalTeleport(Vector3 newpos, Vector3 newvel, Vector3 newlookat, int flags) |
1723 | { | 1736 | { |
1724 | if(!CheckLocalTPLandingPoint(ref newpos)) | 1737 | if (newpos.X <= 0) |
1725 | return; | 1738 | { |
1739 | newpos.X = 0.1f; | ||
1740 | if (newvel.X < 0) | ||
1741 | newvel.X = 0; | ||
1742 | } | ||
1743 | else if (newpos.X >= Scene.RegionInfo.RegionSizeX) | ||
1744 | { | ||
1745 | newpos.X = Scene.RegionInfo.RegionSizeX - 0.1f; | ||
1746 | if (newvel.X > 0) | ||
1747 | newvel.X = 0; | ||
1748 | } | ||
1749 | |||
1750 | if (newpos.Y <= 0) | ||
1751 | { | ||
1752 | newpos.Y = 0.1f; | ||
1753 | if (newvel.Y < 0) | ||
1754 | newvel.Y = 0; | ||
1755 | } | ||
1756 | else if (newpos.Y >= Scene.RegionInfo.RegionSizeY) | ||
1757 | { | ||
1758 | newpos.Y = Scene.RegionInfo.RegionSizeY - 0.1f; | ||
1759 | if (newvel.Y > 0) | ||
1760 | newvel.Y = 0; | ||
1761 | } | ||
1726 | 1762 | ||
1727 | AbsolutePosition = newpos; | 1763 | string reason; |
1764 | if (!m_scene.TestLandRestrictions(UUID, out reason, ref newpos.X, ref newpos.Y)) | ||
1765 | return ; | ||
1766 | |||
1767 | if (IsSatOnObject) | ||
1768 | StandUp(); | ||
1769 | |||
1770 | float localHalfAVHeight = 0.8f; | ||
1771 | if (Appearance != null) | ||
1772 | localHalfAVHeight = Appearance.AvatarHeight * 0.5f; | ||
1728 | 1773 | ||
1729 | if (newvel.HasValue) | 1774 | float posZLimit = (float)Scene.Heightmap[(int)newpos.X, (int)newpos.Y]; |
1775 | posZLimit += localHalfAVHeight + 0.1f; | ||
1776 | if (newpos.Z < posZLimit) | ||
1777 | newpos.Z = posZLimit; | ||
1778 | |||
1779 | if((flags & 0x1e) != 0) | ||
1730 | { | 1780 | { |
1731 | if ((Vector3)newvel == Vector3.Zero) | 1781 | if ((flags & 8) != 0) |
1782 | Flying = true; | ||
1783 | else if ((flags & 16) != 0) | ||
1784 | Flying = false; | ||
1785 | |||
1786 | uint tpflags = (uint)TeleportFlags.ViaLocation; | ||
1787 | if(Flying) | ||
1788 | tpflags |= (uint)TeleportFlags.IsFlying; | ||
1789 | |||
1790 | Vector3 lookat = Lookat; | ||
1791 | |||
1792 | if ((flags & 2) != 0) | ||
1732 | { | 1793 | { |
1733 | if (PhysicsActor != null) | 1794 | newlookat.Z = 0; |
1734 | PhysicsActor.SetMomentum(Vector3.Zero); | 1795 | newlookat.Normalize(); |
1735 | m_velocity = Vector3.Zero; | 1796 | if (Math.Abs(newlookat.X) > 0.001 || Math.Abs(newlookat.Y) > 0.001) |
1797 | lookat = newlookat; | ||
1736 | } | 1798 | } |
1737 | else | 1799 | else if((flags & 4) != 0) |
1738 | { | 1800 | { |
1739 | if (PhysicsActor != null) | 1801 | if((flags & 1) != 0) |
1740 | PhysicsActor.SetMomentum((Vector3)newvel); | 1802 | newlookat = newvel; |
1741 | m_velocity = (Vector3)newvel; | 1803 | else |
1742 | 1804 | newlookat = m_velocity; | |
1743 | if (rotateToVelXY) | 1805 | newlookat.Z = 0; |
1744 | { | 1806 | newlookat.Normalize(); |
1745 | Vector3 lookAt = (Vector3)newvel; | 1807 | if (Math.Abs(newlookat.X) > 0.001 || Math.Abs(newlookat.Y) > 0.001) |
1746 | lookAt.Z = 0; | 1808 | lookat = newlookat; |
1747 | lookAt.Normalize(); | ||
1748 | ControllingClient.SendLocalTeleport(newpos, lookAt, (uint)TeleportFlags.ViaLocation); | ||
1749 | return; | ||
1750 | } | ||
1751 | } | 1809 | } |
1810 | |||
1811 | AbsolutePosition = newpos; | ||
1812 | ControllingClient.SendLocalTeleport(newpos, lookat, tpflags); | ||
1752 | } | 1813 | } |
1814 | else | ||
1815 | AbsolutePosition = newpos; | ||
1816 | |||
1817 | if ((flags & 1) != 0) | ||
1818 | { | ||
1819 | if (PhysicsActor != null) | ||
1820 | PhysicsActor.SetMomentum(newvel); | ||
1821 | m_velocity = newvel; | ||
1822 | } | ||
1823 | |||
1753 | SendTerseUpdateToAllClients(); | 1824 | SendTerseUpdateToAllClients(); |
1754 | } | 1825 | } |
1755 | 1826 | ||
@@ -2126,277 +2197,233 @@ namespace OpenSim.Region.Framework.Scenes | |||
2126 | return; | 2197 | return; |
2127 | } | 2198 | } |
2128 | 2199 | ||
2200 | if(IsChildAgent) | ||
2201 | { | ||
2202 | return; // how? | ||
2203 | } | ||
2129 | 2204 | ||
2130 | //m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | 2205 | //m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
2131 | 2206 | ||
2132 | if(!haveGroupInformation && !IsChildAgent && !IsNPC) | 2207 | if (!IsNPC) |
2133 | { | 2208 | { |
2134 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); | 2209 | if (!m_haveGroupInformation) |
2135 | if (gm != null) | 2210 | { |
2136 | Grouptitle = gm.GetGroupTitle(m_uuid); | 2211 | IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); |
2212 | if (gm != null) | ||
2213 | Grouptitle = gm.GetGroupTitle(m_uuid); | ||
2137 | 2214 | ||
2138 | //m_log.DebugFormat("[CompleteMovement] Missing Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | 2215 | //m_log.DebugFormat("[CompleteMovement] Missing Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts)); |
2139 | 2216 | ||
2140 | InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46); | 2217 | InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46); |
2141 | if (cof == null) | 2218 | if (cof == null) |
2142 | COF = UUID.Zero; | 2219 | COF = UUID.Zero; |
2143 | else | 2220 | else |
2144 | COF = cof.ID; | 2221 | COF = cof.ID; |
2145 | 2222 | ||
2146 | m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF); | 2223 | m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF); |
2224 | } | ||
2147 | } | 2225 | } |
2148 | 2226 | ||
2149 | if (!string.IsNullOrEmpty(m_callbackURI)) | 2227 | if (m_teleportFlags > 0) |
2150 | { | 2228 | m_gotCrossUpdate = false; // sanity check |
2151 | // We cannot sleep here since this would hold up the inbound packet processing thread, as | ||
2152 | // CompleteMovement() is executed synchronously. However, it might be better to delay the release | ||
2153 | // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete | ||
2154 | // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this | ||
2155 | // region as the current region, meaning that a close sent before then will fail the teleport. | ||
2156 | // System.Threading.Thread.Sleep(2000); | ||
2157 | 2229 | ||
2158 | m_log.DebugFormat( | 2230 | if (!m_gotCrossUpdate) |
2159 | "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", | 2231 | RotateToLookAt(look); |
2160 | client.Name, client.AgentId, m_callbackURI); | ||
2161 | 2232 | ||
2162 | UUID originID; | 2233 | m_previusParcelHide = false; |
2234 | m_previusParcelUUID = UUID.Zero; | ||
2235 | m_currentParcelHide = false; | ||
2236 | m_currentParcelUUID = UUID.Zero; | ||
2237 | ParcelDwellTickMS = Util.GetTimeStampMS(); | ||
2163 | 2238 | ||
2164 | lock (m_originRegionIDAccessLock) | 2239 | m_inTransit = false; |
2165 | originID = m_originRegionID; | ||
2166 | 2240 | ||
2167 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); | 2241 | // Tell the client that we're ready to send rest |
2168 | m_callbackURI = null; | 2242 | if (!m_gotCrossUpdate) |
2169 | //m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | 2243 | { |
2244 | m_gotRegionHandShake = false; // allow it if not a crossing | ||
2245 | ControllingClient.SendRegionHandshake(); | ||
2170 | } | 2246 | } |
2171 | // else | ||
2172 | // { | ||
2173 | // m_log.DebugFormat( | ||
2174 | // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", | ||
2175 | // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); | ||
2176 | // } | ||
2177 | 2247 | ||
2178 | |||
2179 | // Tell the client that we're totally ready | ||
2180 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | 2248 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); |
2181 | //m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2182 | 2249 | ||
2183 | bool isHGTP = (m_teleportFlags & TeleportFlags.ViaHGLogin) != 0; | 2250 | bool isHGTP = (m_teleportFlags & TeleportFlags.ViaHGLogin) != 0; |
2184 | 2251 | ||
2185 | int delayctnr = Util.EnvironmentTickCount(); | 2252 | if(!IsNPC) |
2186 | |||
2187 | if (!IsChildAgent) | ||
2188 | { | 2253 | { |
2189 | if( ParentPart != null && !IsNPC && (crossingFlags & 0x08) != 0) | 2254 | if( ParentPart != null && (m_crossingFlags & 0x08) != 0) |
2190 | { | 2255 | { |
2191 | ParentPart.ParentGroup.SendFullAnimUpdateToClient(ControllingClient); | 2256 | ParentPart.ParentGroup.SendFullAnimUpdateToClient(ControllingClient); |
2192 | } | 2257 | } |
2193 | 2258 | ||
2194 | // verify baked textures and cache | 2259 | // verify baked textures and cache |
2195 | bool cachedbaked = false; | 2260 | if (m_scene.AvatarFactory != null && !isHGTP) |
2196 | |||
2197 | if (IsNPC) | ||
2198 | cachedbaked = true; | ||
2199 | else | ||
2200 | { | 2261 | { |
2201 | if (m_scene.AvatarFactory != null && !isHGTP) | 2262 | if (!m_scene.AvatarFactory.ValidateBakedTextureCache(this)) |
2202 | cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this); | 2263 | m_scene.AvatarFactory.QueueAppearanceSave(UUID); |
2203 | |||
2204 | // not sure we need this | ||
2205 | if (!cachedbaked) | ||
2206 | { | ||
2207 | if (m_scene.AvatarFactory != null) | ||
2208 | m_scene.AvatarFactory.QueueAppearanceSave(UUID); | ||
2209 | } | ||
2210 | } | 2264 | } |
2211 | //m_log.DebugFormat("[CompleteMovement] Baked check: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2212 | } | 2265 | } |
2213 | 2266 | ||
2214 | if(m_teleportFlags > 0) | ||
2215 | { | ||
2216 | gotCrossUpdate = false; // sanity check | ||
2217 | if(Util.EnvironmentTickCountSubtract(delayctnr)< 500) | ||
2218 | Thread.Sleep(500); // let viewers catch us | ||
2219 | } | ||
2220 | |||
2221 | if(!gotCrossUpdate) | ||
2222 | RotateToLookAt(look); | ||
2223 | |||
2224 | // HG | ||
2225 | if(isHGTP) | 2267 | if(isHGTP) |
2226 | { | 2268 | { |
2227 | // ControllingClient.SendNameReply(m_uuid, Firstname, Lastname); | 2269 | // ControllingClient.SendNameReply(m_uuid, Firstname, Lastname); |
2228 | m_log.DebugFormat("[CompleteMovement] HG"); | 2270 | m_log.DebugFormat("[CompleteMovement] HG"); |
2229 | } | 2271 | } |
2230 | 2272 | ||
2231 | m_previusParcelHide = false; | 2273 | if (!IsNPC) |
2232 | m_previusParcelUUID = UUID.Zero; | ||
2233 | m_currentParcelHide = false; | ||
2234 | m_currentParcelUUID = UUID.Zero; | ||
2235 | ParcelDwellTickMS = Util.GetTimeStampMS(); | ||
2236 | |||
2237 | if(!IsNPC) | ||
2238 | { | 2274 | { |
2239 | GodController.SyncViewerState(); | 2275 | GodController.SyncViewerState(); |
2240 | 2276 | ||
2241 | // start sending terrain patchs | 2277 | // start sending terrain patchs |
2242 | if (!gotCrossUpdate) | 2278 | if (!m_gotCrossUpdate) |
2243 | Scene.SendLayerData(ControllingClient); | 2279 | Scene.SendLayerData(ControllingClient); |
2244 | } | ||
2245 | // send initial land overlay and parcel | ||
2246 | ILandChannel landch = m_scene.LandChannel; | ||
2247 | if (landch != null) | ||
2248 | landch.sendClientInitialLandInfo(client); | ||
2249 | 2280 | ||
2250 | if (!IsChildAgent) | 2281 | // send initial land overlay and parcel |
2251 | { | 2282 | ILandChannel landch = m_scene.LandChannel; |
2252 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | 2283 | if (landch != null) |
2284 | landch.sendClientInitialLandInfo(client, !m_gotCrossUpdate); | ||
2285 | } | ||
2253 | 2286 | ||
2254 | // send avatar object to all presences including us, so they cross it into region | 2287 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); |
2255 | // then hide if necessary | ||
2256 | 2288 | ||
2257 | SendInitialAvatarDataToAllAgents(allpresences); | 2289 | // send avatar object to all presences including us, so they cross it into region |
2290 | // then hide if necessary | ||
2291 | SendInitialAvatarDataToAllAgents(allpresences); | ||
2258 | 2292 | ||
2259 | // send this look | 2293 | // send this look |
2294 | if (!IsNPC) | ||
2260 | SendAppearanceToAgent(this); | 2295 | SendAppearanceToAgent(this); |
2261 | 2296 | ||
2262 | // send this animations | 2297 | // send this animations |
2263 | 2298 | ||
2264 | UUID[] animIDs = null; | 2299 | UUID[] animIDs = null; |
2265 | int[] animseqs = null; | 2300 | int[] animseqs = null; |
2266 | UUID[] animsobjs = null; | 2301 | UUID[] animsobjs = null; |
2267 | 2302 | ||
2268 | if (Animator != null) | 2303 | if (Animator != null) |
2269 | Animator.GetArrays(out animIDs, out animseqs, out animsobjs); | 2304 | Animator.GetArrays(out animIDs, out animseqs, out animsobjs); |
2270 | 2305 | ||
2271 | bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null); | 2306 | bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null); |
2272 | 2307 | ||
2273 | if (haveAnims) | 2308 | if (!IsNPC && haveAnims) |
2274 | SendAnimPackToAgent(this, animIDs, animseqs, animsobjs); | 2309 | SendAnimPackToAgent(this, animIDs, animseqs, animsobjs); |
2275 | 2310 | ||
2276 | // we should be able to receive updates, etc | 2311 | // send look and animations to others |
2277 | // so release them | 2312 | // if not cached we send greys |
2278 | m_inTransit = false; | 2313 | // uncomented if will wait till avatar does baking |
2314 | //if (cachedbaked) | ||
2279 | 2315 | ||
2280 | // send look and animations to others | 2316 | { |
2281 | // if not cached we send greys | 2317 | foreach (ScenePresence p in allpresences) |
2282 | // uncomented if will wait till avatar does baking | ||
2283 | //if (cachedbaked) | ||
2284 | { | 2318 | { |
2285 | foreach (ScenePresence p in allpresences) | 2319 | if (p == this) |
2286 | { | 2320 | continue; |
2287 | if (p == this) | ||
2288 | continue; | ||
2289 | |||
2290 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
2291 | continue; | ||
2292 | |||
2293 | SendAppearanceToAgentNF(p); | ||
2294 | if (haveAnims) | ||
2295 | SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs); | ||
2296 | } | ||
2297 | } // greys if | ||
2298 | 2321 | ||
2299 | //m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | 2322 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) |
2323 | continue; | ||
2300 | 2324 | ||
2301 | // attachments | 2325 | SendAppearanceToAgentNF(p); |
2302 | if (IsNPC || IsRealLogin(m_teleportFlags)) | 2326 | if (haveAnims) |
2303 | { | 2327 | SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs); |
2304 | if (Scene.AttachmentsModule != null) | 2328 | } |
2305 | // Util.FireAndForget( | 2329 | } |
2306 | // o => | ||
2307 | // { | ||
2308 | 2330 | ||
2309 | if (!IsNPC) | 2331 | // attachments |
2310 | Scene.AttachmentsModule.RezAttachments(this); | 2332 | if (IsNPC || IsRealLogin(m_teleportFlags)) |
2311 | else | 2333 | { |
2312 | Util.FireAndForget(x => | 2334 | if (Scene.AttachmentsModule != null) |
2335 | { | ||
2336 | if(IsNPC) | ||
2337 | { | ||
2338 | Util.FireAndForget(x => | ||
2313 | { | 2339 | { |
2314 | Scene.AttachmentsModule.RezAttachments(this); | 2340 | Scene.AttachmentsModule.RezAttachments(this); |
2315 | }); | 2341 | }); |
2316 | 2342 | } | |
2317 | // }); | 2343 | else |
2344 | Scene.AttachmentsModule.RezAttachments(this); | ||
2318 | } | 2345 | } |
2319 | else | 2346 | } |
2347 | else | ||
2348 | { | ||
2349 | if (m_attachments.Count > 0) | ||
2320 | { | 2350 | { |
2321 | if (m_attachments.Count > 0) | 2351 | foreach (SceneObjectGroup sog in m_attachments) |
2322 | { | 2352 | { |
2323 | // m_log.DebugFormat( | 2353 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); |
2324 | // "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); | 2354 | sog.ResumeScripts(); |
2355 | } | ||
2325 | 2356 | ||
2326 | foreach (SceneObjectGroup sog in m_attachments) | 2357 | foreach (ScenePresence p in allpresences) |
2358 | { | ||
2359 | if (p == this) | ||
2327 | { | 2360 | { |
2328 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); | 2361 | SendAttachmentsToAgentNF(this); |
2329 | sog.ResumeScripts(); | 2362 | continue; |
2330 | } | 2363 | } |
2331 | 2364 | ||
2332 | foreach (ScenePresence p in allpresences) | 2365 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) |
2333 | { | 2366 | continue; |
2334 | if (p == this) | ||
2335 | { | ||
2336 | SendAttachmentsToAgentNF(this); | ||
2337 | continue; | ||
2338 | } | ||
2339 | |||
2340 | if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | ||
2341 | continue; | ||
2342 | 2367 | ||
2343 | SendAttachmentsToAgentNF(p); | 2368 | SendAttachmentsToAgentNF(p); |
2344 | } | ||
2345 | } | 2369 | } |
2346 | } | 2370 | } |
2371 | } | ||
2347 | 2372 | ||
2348 | //m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | 2373 | if (!IsNPC) |
2349 | if (openChildAgents) | 2374 | { |
2375 | if(m_gotCrossUpdate) | ||
2350 | { | 2376 | { |
2377 | SendOtherAgentsAvatarFullToMe(); | ||
2378 | |||
2351 | // Create child agents in neighbouring regions | 2379 | // Create child agents in neighbouring regions |
2352 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | 2380 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); |
2353 | if (m_agentTransfer != null) | 2381 | if (m_agentTransfer != null) |
2354 | { | 2382 | { |
2355 | m_agentTransfer.EnableChildAgents(this); | 2383 | m_agentTransfer.EnableChildAgents(this); |
2356 | } | 2384 | } |
2357 | } | ||
2358 | 2385 | ||
2359 | m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000; | 2386 | m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000; |
2360 | m_lastChildAgentUpdatePosition = AbsolutePosition; | 2387 | m_lastChildAgentUpdatePosition = AbsolutePosition; |
2361 | m_lastChildAgentUpdateDrawDistance = DrawDistance; | 2388 | m_lastChildAgentCheckPosition = m_lastChildAgentUpdatePosition; |
2389 | m_lastChildAgentUpdateDrawDistance = DrawDistance; | ||
2390 | m_lastRegionsDrawDistance = RegionViewDistance; | ||
2362 | 2391 | ||
2363 | m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; | 2392 | m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; |
2364 | m_childUpdatesBusy = false; // allow them | 2393 | m_childUpdatesBusy = false; // allow them |
2365 | } | ||
2366 | 2394 | ||
2367 | //m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | 2395 | } |
2368 | |||
2369 | // send the rest of the world | ||
2370 | if (m_teleportFlags > 0 && !IsNPC || m_currentParcelHide) | ||
2371 | SendInitialDataToMe(); | ||
2372 | 2396 | ||
2373 | // priority uses avatar position only | 2397 | // send the rest of the world |
2374 | // m_reprioritizationLastPosition = AbsolutePosition; | 2398 | //if (m_teleportFlags > 0 || m_currentParcelHide) |
2375 | // m_reprioritizationLastDrawDistance = DrawDistance; | 2399 | //SendInitialDataToMe(); |
2376 | // m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it | 2400 | //SendOtherAgentsAvatarFullToMe(); |
2377 | // m_reprioritizationBusy = false; | ||
2378 | 2401 | ||
2379 | //m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | 2402 | // priority uses avatar position only |
2403 | // m_reprioritizationLastPosition = AbsolutePosition; | ||
2404 | // m_reprioritizationLastDrawDistance = DrawDistance; | ||
2405 | // m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it | ||
2406 | // m_reprioritizationBusy = false; | ||
2380 | 2407 | ||
2381 | if (!IsChildAgent && openChildAgents) | 2408 | if (openChildAgents) |
2382 | { | ||
2383 | IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); | ||
2384 | if (friendsModule != null) | ||
2385 | { | 2409 | { |
2386 | if(gotCrossUpdate) | 2410 | IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); |
2387 | friendsModule.IsNowRoot(this); | 2411 | if (friendsModule != null) |
2388 | else | 2412 | { |
2389 | friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); | 2413 | if(m_gotCrossUpdate) |
2414 | friendsModule.IsNowRoot(this); | ||
2415 | else | ||
2416 | friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); | ||
2417 | } | ||
2418 | //m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2390 | } | 2419 | } |
2391 | //m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts)); | ||
2392 | |||
2393 | } | 2420 | } |
2394 | } | 2421 | } |
2395 | finally | 2422 | finally |
2396 | { | 2423 | { |
2397 | haveGroupInformation = false; | 2424 | m_haveGroupInformation = false; |
2398 | gotCrossUpdate = false; | 2425 | m_gotCrossUpdate = false; |
2399 | crossingFlags = 0; | 2426 | m_crossingFlags = 0; |
2400 | m_inTransit = false; | 2427 | m_inTransit = false; |
2401 | } | 2428 | } |
2402 | 2429 | ||
@@ -3108,10 +3135,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3108 | Vector2 regionSize; | 3135 | Vector2 regionSize; |
3109 | regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY); | 3136 | regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY); |
3110 | 3137 | ||
3111 | if (pos.X < 0 || pos.X >= regionSize.X | 3138 | if (pos.X < 0.5f) |
3112 | || pos.Y < 0 || pos.Y >= regionSize.Y | 3139 | pos.X = 0.5f; |
3113 | || pos.Z < 0) | 3140 | else if (pos.X > regionSize.X - 0.5f) |
3114 | return; | 3141 | pos.X = regionSize.X - 0.5f; |
3142 | if (pos.Y < 0.5f) | ||
3143 | pos.Y = 0.5f; | ||
3144 | else if (pos.Y > regionSize.Y - 0.5f) | ||
3145 | pos.Y = regionSize.Y - 0.5f; | ||
3115 | 3146 | ||
3116 | float terrainHeight; | 3147 | float terrainHeight; |
3117 | Scene targetScene = m_scene; | 3148 | Scene targetScene = m_scene; |
@@ -3709,10 +3740,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3709 | if (IsChildAgent) | 3740 | if (IsChildAgent) |
3710 | return; | 3741 | return; |
3711 | 3742 | ||
3712 | // m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. | ||
3713 | sitAnimation = "SIT_GROUND_CONSTRAINED"; | 3743 | sitAnimation = "SIT_GROUND_CONSTRAINED"; |
3714 | // Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); | ||
3715 | // TriggerScenePresenceUpdated(); | ||
3716 | SitGround = true; | 3744 | SitGround = true; |
3717 | RemoveFromPhysicalScene(); | 3745 | RemoveFromPhysicalScene(); |
3718 | 3746 | ||
@@ -3813,14 +3841,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3813 | direc.Z = 0; | 3841 | direc.Z = 0; |
3814 | } | 3842 | } |
3815 | 3843 | ||
3816 | // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); | ||
3817 | /* | ||
3818 | lock(m_forceToApplyLock) | ||
3819 | { | ||
3820 | m_forceToApply = direc; | ||
3821 | m_forceToApplyValid = true; | ||
3822 | } | ||
3823 | */ | ||
3824 | TargetVelocity = direc; | 3844 | TargetVelocity = direc; |
3825 | Animator.UpdateMovementAnimations(); | 3845 | Animator.UpdateMovementAnimations(); |
3826 | } | 3846 | } |
@@ -3837,15 +3857,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
3837 | 3857 | ||
3838 | public override void Update() | 3858 | public override void Update() |
3839 | { | 3859 | { |
3840 | if(IsChildAgent || IsDeleted) | 3860 | if (IsDeleted) |
3841 | return; | 3861 | return; |
3842 | 3862 | ||
3843 | CheckForBorderCrossing(); | 3863 | if (NeedInitialData > 0) |
3864 | { | ||
3865 | SendInitialData(); | ||
3866 | return; | ||
3867 | } | ||
3844 | 3868 | ||
3845 | if (IsInTransit || IsLoggingIn) | 3869 | if (IsChildAgent || IsInTransit) |
3846 | return; | 3870 | return; |
3847 | 3871 | ||
3848 | if(m_movingToTarget) | 3872 | CheckForBorderCrossing(); |
3873 | |||
3874 | if (m_movingToTarget) | ||
3849 | { | 3875 | { |
3850 | m_delayedStop = -1; | 3876 | m_delayedStop = -1; |
3851 | Vector3 control = Vector3.Zero; | 3877 | Vector3 control = Vector3.Zero; |
@@ -4020,29 +4046,95 @@ namespace OpenSim.Region.Framework.Scenes | |||
4020 | ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); | 4046 | ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); |
4021 | } | 4047 | } |
4022 | 4048 | ||
4023 | public void SendInitialDataToMe() | 4049 | public void RegionHandShakeReply (IClientAPI client) |
4024 | { | 4050 | { |
4025 | // Send all scene object to the new client | 4051 | if(IsNPC) |
4026 | SentInitialData = true; | 4052 | return; |
4053 | |||
4054 | lock (m_completeMovementLock) | ||
4055 | { | ||
4056 | if(m_gotRegionHandShake) | ||
4057 | return; | ||
4058 | m_gotRegionHandShake = true; | ||
4059 | NeedInitialData = 1; | ||
4060 | } | ||
4061 | } | ||
4062 | |||
4063 | private void SendInitialData() | ||
4064 | { | ||
4065 | uint flags = ControllingClient.GetViewerCaps(); | ||
4066 | if((flags & 0x1000) == 0) // wait for seeds sending | ||
4067 | return; | ||
4068 | |||
4069 | // lock (m_completeMovementLock) | ||
4070 | { | ||
4071 | if(NeedInitialData < 0) | ||
4072 | return; | ||
4073 | |||
4074 | // give some extra time to make sure viewers did process seeds | ||
4075 | if(++NeedInitialData < 4) // needs fix if update rate changes on heartbeat | ||
4076 | return; | ||
4077 | } | ||
4078 | |||
4079 | NeedInitialData = -1; | ||
4080 | |||
4081 | bool selfappearance = (flags & 4) != 0; | ||
4082 | |||
4083 | // this should enqueued on the client processing job to save threads | ||
4027 | Util.FireAndForget(delegate | 4084 | Util.FireAndForget(delegate |
4028 | { | 4085 | { |
4029 | // we created a new ScenePresence (a new child agent) in a fresh region. | 4086 | if(!IsChildAgent) |
4030 | // Request info about all the (root) agents in this region | 4087 | { |
4031 | // Note: This won't send data *to* other clients in that region (children don't send) | 4088 | // close v1 sender region obsolete |
4089 | if (!string.IsNullOrEmpty(m_callbackURI)) | ||
4090 | { | ||
4091 | m_log.DebugFormat( | ||
4092 | "[SCENE PRESENCE({0})]: Releasing {1} {2} with old callback to {3}", | ||
4093 | Scene.RegionInfo.RegionName, Name, UUID, m_callbackURI); | ||
4094 | |||
4095 | UUID originID; | ||
4096 | |||
4097 | lock (m_originRegionIDAccessLock) | ||
4098 | originID = m_originRegionID; | ||
4099 | |||
4100 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); | ||
4101 | m_callbackURI = null; | ||
4102 | } | ||
4103 | // v0.7 close HG sender region | ||
4104 | else if (!string.IsNullOrEmpty(m_newCallbackURI)) | ||
4105 | { | ||
4106 | m_log.DebugFormat( | ||
4107 | "[SCENE PRESENCE({0})]: Releasing {1} {2} with callback to {3}", | ||
4108 | Scene.RegionInfo.RegionName, Name, UUID, m_newCallbackURI); | ||
4109 | |||
4110 | UUID originID; | ||
4111 | |||
4112 | lock (m_originRegionIDAccessLock) | ||
4113 | originID = m_originRegionID; | ||
4114 | |||
4115 | Scene.SimulationService.ReleaseAgent(originID, UUID, m_newCallbackURI); | ||
4116 | m_newCallbackURI = null; | ||
4117 | } | ||
4118 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | ||
4119 | if (m_agentTransfer != null) | ||
4120 | { | ||
4121 | m_agentTransfer.CloseOldChildAgents(this); | ||
4122 | } | ||
4123 | } | ||
4124 | |||
4125 | m_log.DebugFormat("[SCENE PRESENCE({0})]: SendInitialData for {1}", Scene.RegionInfo.RegionName, UUID); | ||
4032 | if (m_teleportFlags <= 0) | 4126 | if (m_teleportFlags <= 0) |
4033 | { | 4127 | { |
4034 | Scene.SendLayerData(ControllingClient); | 4128 | Scene.SendLayerData(ControllingClient); |
4035 | 4129 | ||
4036 | ILandChannel landch = m_scene.LandChannel; | 4130 | ILandChannel landch = m_scene.LandChannel; |
4037 | if (landch != null) | 4131 | if (landch != null) |
4038 | { | 4132 | landch.sendClientInitialLandInfo(ControllingClient, true); |
4039 | landch.sendClientInitialLandInfo(ControllingClient); | ||
4040 | } | ||
4041 | } | 4133 | } |
4042 | 4134 | ||
4043 | SendOtherAgentsAvatarFullToMe(); | 4135 | SendOtherAgentsAvatarFullToMe(); |
4044 | 4136 | ||
4045 | if(m_scene.ObjectsCullingByDistance) | 4137 | if (m_scene.ObjectsCullingByDistance) |
4046 | { | 4138 | { |
4047 | m_reprioritizationBusy = true; | 4139 | m_reprioritizationBusy = true; |
4048 | m_reprioritizationLastPosition = AbsolutePosition; | 4140 | m_reprioritizationLastPosition = AbsolutePosition; |
@@ -4051,23 +4143,63 @@ namespace OpenSim.Region.Framework.Scenes | |||
4051 | ControllingClient.ReprioritizeUpdates(); | 4143 | ControllingClient.ReprioritizeUpdates(); |
4052 | m_reprioritizationLastTime = Util.EnvironmentTickCount(); | 4144 | m_reprioritizationLastTime = Util.EnvironmentTickCount(); |
4053 | m_reprioritizationBusy = false; | 4145 | m_reprioritizationBusy = false; |
4054 | return; | ||
4055 | } | 4146 | } |
4056 | 4147 | else | |
4057 | EntityBase[] entities = Scene.Entities.GetEntities(); | ||
4058 | foreach (EntityBase e in entities) | ||
4059 | { | 4148 | { |
4060 | if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) | 4149 | //bool cacheCulling = (flags & 1) != 0; |
4061 | ((SceneObjectGroup)e).SendFullAnimUpdateToClient(ControllingClient); | 4150 | bool cacheEmpty = (flags & 2) != 0;; |
4151 | |||
4152 | EntityBase[] entities = Scene.Entities.GetEntities(); | ||
4153 | if(cacheEmpty) | ||
4154 | { | ||
4155 | foreach (EntityBase e in entities) | ||
4156 | { | ||
4157 | if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) | ||
4158 | ((SceneObjectGroup)e).SendFullAnimUpdateToClient(ControllingClient); | ||
4159 | } | ||
4160 | } | ||
4161 | else | ||
4162 | { | ||
4163 | foreach (EntityBase e in entities) | ||
4164 | { | ||
4165 | if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) | ||
4166 | { | ||
4167 | SceneObjectGroup grp = e as SceneObjectGroup; | ||
4168 | if(grp.IsViewerCachable) | ||
4169 | grp.SendUpdateProbes(ControllingClient); | ||
4170 | else | ||
4171 | grp.SendFullAnimUpdateToClient(ControllingClient); | ||
4172 | } | ||
4173 | } | ||
4174 | } | ||
4175 | |||
4176 | m_reprioritizationLastPosition = AbsolutePosition; | ||
4177 | m_reprioritizationLastDrawDistance = DrawDistance; | ||
4178 | m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it | ||
4179 | |||
4180 | m_reprioritizationBusy = false; | ||
4062 | } | 4181 | } |
4063 | 4182 | ||
4064 | m_reprioritizationLastPosition = AbsolutePosition; | 4183 | if (!IsChildAgent) |
4065 | m_reprioritizationLastDrawDistance = DrawDistance; | 4184 | { |
4066 | m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it | 4185 | // Create child agents in neighbouring regions |
4186 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); | ||
4187 | if (m_agentTransfer != null) | ||
4188 | { | ||
4189 | m_agentTransfer.EnableChildAgents(this); | ||
4190 | } | ||
4067 | 4191 | ||
4068 | m_reprioritizationBusy = false; | 4192 | m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000; |
4193 | m_lastChildAgentUpdatePosition = AbsolutePosition; | ||
4194 | m_lastChildAgentCheckPosition = m_lastChildAgentUpdatePosition; | ||
4195 | m_lastChildAgentUpdateDrawDistance = DrawDistance; | ||
4196 | m_lastRegionsDrawDistance = RegionViewDistance; | ||
4069 | 4197 | ||
4198 | m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; | ||
4199 | m_childUpdatesBusy = false; // allow them | ||
4200 | } | ||
4070 | }); | 4201 | }); |
4202 | |||
4071 | } | 4203 | } |
4072 | 4204 | ||
4073 | /// <summary> | 4205 | /// <summary> |
@@ -4131,8 +4263,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
4131 | { | 4263 | { |
4132 | m_lastSize = Appearance.AvatarSize; | 4264 | m_lastSize = Appearance.AvatarSize; |
4133 | int count = 0; | 4265 | int count = 0; |
4266 | SceneObjectPart sitroot = null; | ||
4267 | if (ParentID != 0 && ParentPart != null) // we need to send the sitting root prim | ||
4268 | { | ||
4269 | sitroot = ParentPart.ParentGroup.RootPart; | ||
4270 | } | ||
4134 | foreach (ScenePresence p in presences) | 4271 | foreach (ScenePresence p in presences) |
4135 | { | 4272 | { |
4273 | if (sitroot != null) // we need to send the sitting root prim | ||
4274 | { | ||
4275 | p.ControllingClient.SendEntityFullUpdateImmediate(ParentPart.ParentGroup.RootPart); | ||
4276 | } | ||
4136 | p.ControllingClient.SendEntityFullUpdateImmediate(this); | 4277 | p.ControllingClient.SendEntityFullUpdateImmediate(this); |
4137 | if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | 4278 | if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) |
4138 | // either just kill the object | 4279 | // either just kill the object |
@@ -4146,6 +4287,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
4146 | 4287 | ||
4147 | public void SendInitialAvatarDataToAgent(ScenePresence p) | 4288 | public void SendInitialAvatarDataToAgent(ScenePresence p) |
4148 | { | 4289 | { |
4290 | if(ParentID != 0 && ParentPart != null) // we need to send the sitting root prim | ||
4291 | { | ||
4292 | p.ControllingClient.SendEntityFullUpdateImmediate(ParentPart.ParentGroup.RootPart); | ||
4293 | } | ||
4149 | p.ControllingClient.SendEntityFullUpdateImmediate(this); | 4294 | p.ControllingClient.SendEntityFullUpdateImmediate(this); |
4150 | if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) | 4295 | if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) |
4151 | // either just kill the object | 4296 | // either just kill the object |
@@ -4273,12 +4418,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4273 | if(IsDeleted || !ControllingClient.IsActive) | 4418 | if(IsDeleted || !ControllingClient.IsActive) |
4274 | return; | 4419 | return; |
4275 | 4420 | ||
4276 | if(!SentInitialData) | ||
4277 | { | ||
4278 | SendInitialDataToMe(); | ||
4279 | return; | ||
4280 | } | ||
4281 | |||
4282 | if(m_reprioritizationBusy) | 4421 | if(m_reprioritizationBusy) |
4283 | return; | 4422 | return; |
4284 | 4423 | ||
@@ -4339,62 +4478,91 @@ namespace OpenSim.Region.Framework.Scenes | |||
4339 | m_scene.EventManager.TriggerSignificantClientMovement(this); | 4478 | m_scene.EventManager.TriggerSignificantClientMovement(this); |
4340 | } | 4479 | } |
4341 | 4480 | ||
4481 | if(IsNPC) | ||
4482 | return; | ||
4483 | |||
4342 | // updates priority recalc | 4484 | // updates priority recalc |
4343 | checkRePrioritization(); | 4485 | checkRePrioritization(); |
4344 | 4486 | ||
4345 | if(m_childUpdatesBusy) | 4487 | if(m_childUpdatesBusy || RegionViewDistance == 0) |
4346 | return; | 4488 | return; |
4347 | 4489 | ||
4348 | //possible KnownRegionHandles always contains current region and this check is not needed | 4490 | int tdiff = Util.EnvironmentTickCountSubtract(m_lastChildUpdatesTime); |
4349 | int minhandles = KnownRegionHandles.Contains(RegionHandle) ? 1 : 0; | 4491 | if (tdiff < CHILDUPDATES_TIME) |
4350 | if(KnownRegionHandles.Count > minhandles) | 4492 | return; |
4351 | { | ||
4352 | int tdiff = Util.EnvironmentTickCountSubtract(m_lastChildUpdatesTime); | ||
4353 | if(tdiff < CHILDUPDATES_TIME) | ||
4354 | return; | ||
4355 | 4493 | ||
4356 | bool doUpdate = false; | 4494 | bool viewchanged = Math.Abs(RegionViewDistance - m_lastRegionsDrawDistance) > 32.0f; |
4357 | if(m_lastChildAgentUpdateGodLevel != GodController.ViwerUIGodLevel) | ||
4358 | doUpdate = true; | ||
4359 | |||
4360 | if(!doUpdate && Math.Abs(DrawDistance - m_lastChildAgentUpdateDrawDistance) > 32.0f) | ||
4361 | doUpdate = true; | ||
4362 | 4495 | ||
4363 | if(!doUpdate) | 4496 | IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); |
4497 | float dx = pos.X - m_lastChildAgentCheckPosition.X; | ||
4498 | float dy = pos.Y - m_lastChildAgentCheckPosition.Y; | ||
4499 | if ((m_agentTransfer != null) && (viewchanged || ((dx * dx + dy * dy) > CHILDAGENTSCHECK_MOVEMENT))) | ||
4500 | { | ||
4501 | m_childUpdatesBusy = true; | ||
4502 | m_lastChildAgentCheckPosition = pos; | ||
4503 | m_lastChildAgentUpdatePosition = pos; | ||
4504 | m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; | ||
4505 | m_lastChildAgentUpdateDrawDistance = DrawDistance; | ||
4506 | m_lastRegionsDrawDistance = RegionViewDistance; | ||
4507 | // m_lastChildAgentUpdateCamPosition = CameraPosition; | ||
4508 | |||
4509 | Util.FireAndForget( | ||
4510 | o => | ||
4511 | { | ||
4512 | m_agentTransfer.EnableChildAgents(this); | ||
4513 | m_lastChildUpdatesTime = Util.EnvironmentTickCount(); | ||
4514 | m_childUpdatesBusy = false; | ||
4515 | }, null, "ScenePresence.CheckChildAgents"); | ||
4516 | } | ||
4517 | else | ||
4518 | { | ||
4519 | //possible KnownRegionHandles always contains current region and this check is not needed | ||
4520 | int minhandles = KnownRegionHandles.Contains(RegionHandle) ? 1 : 0; | ||
4521 | if(KnownRegionHandles.Count > minhandles) | ||
4364 | { | 4522 | { |
4365 | diff = pos - m_lastChildAgentUpdatePosition; | 4523 | bool doUpdate = false; |
4366 | if (diff.LengthSquared() > CHILDUPDATES_MOVEMENT) | 4524 | if (m_lastChildAgentUpdateGodLevel != GodController.ViwerUIGodLevel) |
4367 | doUpdate = true; | 4525 | doUpdate = true; |
4368 | } | ||
4369 | 4526 | ||
4370 | if(doUpdate) | 4527 | if (Math.Abs(DrawDistance - m_lastChildAgentUpdateDrawDistance) > 32.0f) |
4371 | { | 4528 | doUpdate = true; |
4372 | m_childUpdatesBusy = true; | 4529 | |
4373 | m_lastChildAgentUpdatePosition = pos; | 4530 | if(!doUpdate) |
4374 | m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; | 4531 | { |
4375 | m_lastChildAgentUpdateDrawDistance = DrawDistance; | 4532 | diff = pos - m_lastChildAgentUpdatePosition; |
4376 | // m_lastChildAgentUpdateCamPosition = CameraPosition; | 4533 | if (diff.LengthSquared() > CHILDUPDATES_MOVEMENT) |
4377 | 4534 | doUpdate = true; | |
4378 | AgentPosition agentpos = new AgentPosition(); | 4535 | } |
4379 | agentpos.AgentID = new UUID(UUID.Guid); | 4536 | |
4380 | agentpos.SessionID = ControllingClient.SessionId; | 4537 | if (doUpdate) |
4381 | agentpos.Size = Appearance.AvatarSize; | 4538 | { |
4382 | agentpos.Center = CameraPosition; | 4539 | m_childUpdatesBusy = true; |
4383 | agentpos.Far = DrawDistance; | 4540 | m_lastChildAgentUpdatePosition = pos; |
4384 | agentpos.Position = AbsolutePosition; | 4541 | m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; |
4385 | agentpos.Velocity = Velocity; | 4542 | m_lastChildAgentUpdateDrawDistance = DrawDistance; |
4386 | agentpos.RegionHandle = RegionHandle; | 4543 | // m_lastChildAgentUpdateCamPosition = CameraPosition; |
4387 | agentpos.GodData = GodController.State(); | 4544 | |
4388 | agentpos.Throttles = ControllingClient.GetThrottlesPacked(1); | 4545 | AgentPosition agentpos = new AgentPosition(); |
4389 | 4546 | agentpos.AgentID = new UUID(UUID.Guid); | |
4390 | // Let's get this out of the update loop | 4547 | agentpos.SessionID = ControllingClient.SessionId; |
4391 | Util.FireAndForget( | 4548 | agentpos.Size = Appearance.AvatarSize; |
4392 | o => | 4549 | agentpos.Center = CameraPosition; |
4393 | { | 4550 | agentpos.Far = DrawDistance; |
4394 | m_scene.SendOutChildAgentUpdates(agentpos, this); | 4551 | agentpos.Position = AbsolutePosition; |
4395 | m_lastChildUpdatesTime = Util.EnvironmentTickCount(); | 4552 | agentpos.Velocity = Velocity; |
4396 | m_childUpdatesBusy = false; | 4553 | agentpos.RegionHandle = RegionHandle; |
4397 | }, null, "ScenePresence.SendOutChildAgentUpdates"); | 4554 | agentpos.GodData = GodController.State(); |
4555 | agentpos.Throttles = ControllingClient.GetThrottlesPacked(1); | ||
4556 | |||
4557 | // Let's get this out of the update loop | ||
4558 | Util.FireAndForget( | ||
4559 | o => | ||
4560 | { | ||
4561 | m_scene.SendOutChildAgentUpdates(agentpos, this); | ||
4562 | m_lastChildUpdatesTime = Util.EnvironmentTickCount(); | ||
4563 | m_childUpdatesBusy = false; | ||
4564 | }, null, "ScenePresence.SendOutChildAgentUpdates"); | ||
4565 | } | ||
4398 | } | 4566 | } |
4399 | } | 4567 | } |
4400 | } | 4568 | } |
@@ -4547,12 +4715,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
4547 | byebyeRegions.Add(handle); | 4715 | byebyeRegions.Add(handle); |
4548 | else if(handle == curRegionHandle) | 4716 | else if(handle == curRegionHandle) |
4549 | { | 4717 | { |
4718 | continue; | ||
4719 | /* | ||
4550 | RegionInfo curreg = m_scene.RegionInfo; | 4720 | RegionInfo curreg = m_scene.RegionInfo; |
4551 | if (Util.IsOutsideView(255, curreg.RegionLocX, newRegionX, curreg.RegionLocY, newRegionY, | 4721 | if (Util.IsOutsideView(255, curreg.RegionLocX, newRegionX, curreg.RegionLocY, newRegionY, |
4552 | (int)curreg.RegionSizeX, (int)curreg.RegionSizeX, newRegionSizeX, newRegionSizeY)) | 4722 | (int)curreg.RegionSizeX, (int)curreg.RegionSizeX, newRegionSizeX, newRegionSizeY)) |
4553 | { | 4723 | { |
4554 | byebyeRegions.Add(handle); | 4724 | byebyeRegions.Add(handle); |
4555 | } | 4725 | } |
4726 | */ | ||
4556 | } | 4727 | } |
4557 | else | 4728 | else |
4558 | { | 4729 | { |
@@ -4732,6 +4903,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4732 | public void CopyTo(AgentData cAgent, bool isCrossUpdate) | 4903 | public void CopyTo(AgentData cAgent, bool isCrossUpdate) |
4733 | { | 4904 | { |
4734 | cAgent.CallbackURI = m_callbackURI; | 4905 | cAgent.CallbackURI = m_callbackURI; |
4906 | cAgent.NewCallbackURI = m_newCallbackURI; | ||
4735 | 4907 | ||
4736 | cAgent.AgentID = UUID; | 4908 | cAgent.AgentID = UUID; |
4737 | cAgent.RegionID = Scene.RegionInfo.RegionID; | 4909 | cAgent.RegionID = Scene.RegionInfo.RegionID; |
@@ -4792,7 +4964,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4792 | 4964 | ||
4793 | if(isCrossUpdate) | 4965 | if(isCrossUpdate) |
4794 | { | 4966 | { |
4795 | cAgent.CrossingFlags = crossingFlags; | 4967 | cAgent.CrossingFlags = m_crossingFlags; |
4796 | cAgent.CrossingFlags |= 1; | 4968 | cAgent.CrossingFlags |= 1; |
4797 | cAgent.CrossExtraFlags = 0; | 4969 | cAgent.CrossExtraFlags = 0; |
4798 | if((LastCommands & ScriptControlled.CONTROL_LBUTTON) != 0) | 4970 | if((LastCommands & ScriptControlled.CONTROL_LBUTTON) != 0) |
@@ -4818,9 +4990,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
4818 | private void CopyFrom(AgentData cAgent) | 4990 | private void CopyFrom(AgentData cAgent) |
4819 | { | 4991 | { |
4820 | m_callbackURI = cAgent.CallbackURI; | 4992 | m_callbackURI = cAgent.CallbackURI; |
4821 | // m_log.DebugFormat( | 4993 | m_newCallbackURI = cAgent.NewCallbackURI; |
4822 | // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", | 4994 | // m_log.DebugFormat( |
4823 | // Name, m_scene.RegionInfo.RegionName, m_callbackURI); | 4995 | // "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", |
4996 | // Name, m_scene.RegionInfo.RegionName, m_callbackURI); | ||
4824 | 4997 | ||
4825 | GodController.SetState(cAgent.GodData); | 4998 | GodController.SetState(cAgent.GodData); |
4826 | 4999 | ||
@@ -4928,9 +5101,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
4928 | if (cAgent.MotionState != 0) | 5101 | if (cAgent.MotionState != 0) |
4929 | Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState; | 5102 | Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState; |
4930 | 5103 | ||
4931 | crossingFlags = cAgent.CrossingFlags; | 5104 | m_crossingFlags = cAgent.CrossingFlags; |
4932 | gotCrossUpdate = (crossingFlags != 0); | 5105 | m_gotCrossUpdate = (m_crossingFlags != 0); |
4933 | if(gotCrossUpdate) | 5106 | if(m_gotCrossUpdate) |
4934 | { | 5107 | { |
4935 | LastCommands &= ~(ScriptControlled.CONTROL_LBUTTON | ScriptControlled.CONTROL_ML_LBUTTON); | 5108 | LastCommands &= ~(ScriptControlled.CONTROL_LBUTTON | ScriptControlled.CONTROL_ML_LBUTTON); |
4936 | if((cAgent.CrossExtraFlags & 1) != 0) | 5109 | if((cAgent.CrossExtraFlags & 1) != 0) |
@@ -4940,11 +5113,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
4940 | MouseDown = (cAgent.CrossExtraFlags & 3) != 0; | 5113 | MouseDown = (cAgent.CrossExtraFlags & 3) != 0; |
4941 | } | 5114 | } |
4942 | 5115 | ||
4943 | haveGroupInformation = false; | 5116 | m_haveGroupInformation = false; |
4944 | // using this as protocol detection don't want to mess with the numbers for now | 5117 | // using this as protocol detection don't want to mess with the numbers for now |
4945 | if(cAgent.ActiveGroupTitle != null) | 5118 | if(cAgent.ActiveGroupTitle != null) |
4946 | { | 5119 | { |
4947 | haveGroupInformation = true; | 5120 | m_haveGroupInformation = true; |
4948 | COF = cAgent.agentCOF; | 5121 | COF = cAgent.agentCOF; |
4949 | if(ControllingClient.IsGroupMember(cAgent.ActiveGroupID)) | 5122 | if(ControllingClient.IsGroupMember(cAgent.ActiveGroupID)) |
4950 | { | 5123 | { |
@@ -6624,7 +6797,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
6624 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) | 6797 | if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) |
6625 | continue; | 6798 | continue; |
6626 | 6799 | ||
6627 | // only those on previus parcel need receive kills | 6800 | // only those on previous parcel need receive kills |
6628 | if (previusParcelID == p.currentParcelUUID) | 6801 | if (previusParcelID == p.currentParcelUUID) |
6629 | { | 6802 | { |
6630 | if(!p.IsViewerUIGod) | 6803 | if(!p.IsViewerUIGod) |
@@ -6756,7 +6929,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
6756 | } | 6929 | } |
6757 | else | 6930 | else |
6758 | { | 6931 | { |
6759 | GodController.HasMovedAway(); | 6932 | lock (m_completeMovementLock) |
6933 | { | ||
6934 | GodController.HasMovedAway(); | ||
6935 | NeedInitialData = -1; | ||
6936 | m_gotRegionHandShake = false; | ||
6937 | } | ||
6938 | |||
6760 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); | 6939 | List<ScenePresence> allpresences = m_scene.GetScenePresences(); |
6761 | foreach (ScenePresence p in allpresences) | 6940 | foreach (ScenePresence p in allpresences) |
6762 | { | 6941 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index bc440fc..50b0cb5 100755 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | |||
@@ -556,7 +556,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
556 | sb[27].StatID = (uint)Stats.PhysicsLodTasks; | 556 | sb[27].StatID = (uint)Stats.PhysicsLodTasks; |
557 | sb[27].StatValue = 0; | 557 | sb[27].StatValue = 0; |
558 | 558 | ||
559 | sb[28].StatID = (uint)Stats.ScriptEps; // we actuall have this, but not messing array order AGAIN | 559 | sb[28].StatID = (uint)Stats.ScriptEps; // we actually have this, but not messing array order AGAIN |
560 | sb[28].StatValue = (float)Math.Round(m_scriptEventsPerSecond * updateTimeFactor); | 560 | sb[28].StatValue = (float)Math.Round(m_scriptEventsPerSecond * updateTimeFactor); |
561 | 561 | ||
562 | sb[29].StatID = (uint)Stats.SimAIStepTimeMS; | 562 | sb[29].StatID = (uint)Stats.SimAIStepTimeMS; |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs index abf8c48..7c3eab1 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs | |||
@@ -155,11 +155,15 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
155 | sp1SceneA.AbsolutePosition = so1StartPos; | 155 | sp1SceneA.AbsolutePosition = so1StartPos; |
156 | sp1SceneA.HandleAgentRequestSit(sp1SceneA.ControllingClient, sp1SceneA.UUID, so1.UUID, Vector3.Zero); | 156 | sp1SceneA.HandleAgentRequestSit(sp1SceneA.ControllingClient, sp1SceneA.UUID, so1.UUID, Vector3.Zero); |
157 | 157 | ||
158 | sceneA.Update(4); | ||
159 | sceneB.Update(4); | ||
158 | // Cross | 160 | // Cross |
159 | sceneA.SceneGraph.UpdatePrimGroupPosition( | 161 | sceneA.SceneGraph.UpdatePrimGroupPosition( |
160 | so1.LocalId, new Vector3(so1StartPos.X, so1StartPos.Y - 20, so1StartPos.Z), sp1SceneA.ControllingClient); | 162 | so1.LocalId, new Vector3(so1StartPos.X, so1StartPos.Y - 20, so1StartPos.Z), sp1SceneA.ControllingClient); |
161 | 163 | ||
162 | // crossing is async | 164 | // crossing is async |
165 | sceneA.Update(4); | ||
166 | sceneB.Update(4); | ||
163 | Thread.Sleep(500); | 167 | Thread.Sleep(500); |
164 | 168 | ||
165 | SceneObjectGroup so1PostCross; | 169 | SceneObjectGroup so1PostCross; |
@@ -171,6 +175,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
171 | TestClient sceneBTc = ((TestClient)sp1SceneBPostCross.ControllingClient); | 175 | TestClient sceneBTc = ((TestClient)sp1SceneBPostCross.ControllingClient); |
172 | sceneBTc.CompleteMovement(); | 176 | sceneBTc.CompleteMovement(); |
173 | 177 | ||
178 | sceneA.Update(4); | ||
179 | sceneB.Update(4); | ||
180 | |||
174 | Assert.IsFalse(sp1SceneBPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true"); | 181 | Assert.IsFalse(sp1SceneBPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true"); |
175 | Assert.IsTrue(sp1SceneBPostCross.IsSatOnObject); | 182 | Assert.IsTrue(sp1SceneBPostCross.IsSatOnObject); |
176 | 183 | ||
@@ -188,6 +195,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
188 | sceneB.SceneGraph.UpdatePrimGroupPosition( | 195 | sceneB.SceneGraph.UpdatePrimGroupPosition( |
189 | so1PostCross.LocalId, new Vector3(so1PostCrossPos.X, so1PostCrossPos.Y + 20, so1PostCrossPos.Z), sp1SceneBPostCross.ControllingClient); | 196 | so1PostCross.LocalId, new Vector3(so1PostCrossPos.X, so1PostCrossPos.Y + 20, so1PostCrossPos.Z), sp1SceneBPostCross.ControllingClient); |
190 | 197 | ||
198 | sceneA.Update(4); | ||
199 | sceneB.Update(4); | ||
191 | // crossing is async | 200 | // crossing is async |
192 | Thread.Sleep(500); | 201 | Thread.Sleep(500); |
193 | 202 | ||
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs index 94e6b99..676d7eb 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs | |||
@@ -212,6 +212,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
212 | ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); | 212 | ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); |
213 | sp.AbsolutePosition = new Vector3(30, 31, 32); | 213 | sp.AbsolutePosition = new Vector3(30, 31, 32); |
214 | 214 | ||
215 | sceneA.Update(4); | ||
216 | sceneB.Update(4); | ||
217 | |||
215 | List<TestClient> destinationTestClients = new List<TestClient>(); | 218 | List<TestClient> destinationTestClients = new List<TestClient>(); |
216 | EntityTransferHelpers.SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement( | 219 | EntityTransferHelpers.SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement( |
217 | (TestClient)sp.ControllingClient, destinationTestClients); | 220 | (TestClient)sp.ControllingClient, destinationTestClients); |
@@ -224,11 +227,14 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
224 | (uint)TeleportFlags.ViaLocation); | 227 | (uint)TeleportFlags.ViaLocation); |
225 | 228 | ||
226 | // Assert.That(sceneA.GetScenePresence(userId), Is.Null); | 229 | // Assert.That(sceneA.GetScenePresence(userId), Is.Null); |
230 | sceneA.Update(4); | ||
231 | sceneB.Update(4); | ||
227 | 232 | ||
228 | ScenePresence sceneBSp = sceneB.GetScenePresence(userId); | 233 | ScenePresence sceneBSp = sceneB.GetScenePresence(userId); |
229 | Assert.That(sceneBSp, Is.Not.Null); | 234 | Assert.That(sceneBSp, Is.Not.Null); |
230 | Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); | 235 | Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); |
231 | Assert.That(sceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition)); | 236 | Assert.That(sceneBSp.AbsolutePosition.X, Is.EqualTo(teleportPosition.X)); |
237 | Assert.That(sceneBSp.AbsolutePosition.Y, Is.EqualTo(teleportPosition.Y)); | ||
232 | 238 | ||
233 | //Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0)); | 239 | //Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0)); |
234 | //Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); | 240 | //Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); |
@@ -239,7 +245,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
239 | 245 | ||
240 | // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera | 246 | // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera |
241 | // position instead). | 247 | // position instead). |
242 | // Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); | 248 | // Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); |
243 | } | 249 | } |
244 | 250 | ||
245 | /// <summary> | 251 | /// <summary> |
@@ -310,7 +316,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
310 | ScenePresence sceneASp = sceneA.GetScenePresence(userId); | 316 | ScenePresence sceneASp = sceneA.GetScenePresence(userId); |
311 | Assert.That(sceneASp, Is.Not.Null); | 317 | Assert.That(sceneASp, Is.Not.Null); |
312 | Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); | 318 | Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); |
313 | Assert.That(sceneASp.AbsolutePosition, Is.EqualTo(preTeleportPosition)); | 319 | Assert.That(sceneASp.AbsolutePosition.X, Is.EqualTo(preTeleportPosition.X)); |
320 | Assert.That(sceneASp.AbsolutePosition.Y, Is.EqualTo(preTeleportPosition.Y)); | ||
314 | 321 | ||
315 | Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); | 322 | Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); |
316 | Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); | 323 | Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); |
@@ -369,6 +376,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
369 | ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); | 376 | ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); |
370 | sp.AbsolutePosition = preTeleportPosition; | 377 | sp.AbsolutePosition = preTeleportPosition; |
371 | 378 | ||
379 | sceneA.Update(4); | ||
380 | sceneB.Update(4); | ||
381 | |||
372 | // Make sceneB refuse CreateAgent | 382 | // Make sceneB refuse CreateAgent |
373 | sceneB.LoginsEnabled = false; | 383 | sceneB.LoginsEnabled = false; |
374 | 384 | ||
@@ -379,14 +389,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
379 | teleportLookAt, | 389 | teleportLookAt, |
380 | (uint)TeleportFlags.ViaLocation); | 390 | (uint)TeleportFlags.ViaLocation); |
381 | 391 | ||
382 | // ((TestClient)sp.ControllingClient).CompleteTeleportClientSide(); | 392 | // ((TestClient)sp.ControllingClient).CompleteTeleportClientSide(); |
393 | |||
394 | sceneA.Update(4); | ||
395 | sceneB.Update(4); | ||
383 | 396 | ||
384 | Assert.That(sceneB.GetScenePresence(userId), Is.Null); | 397 | Assert.That(sceneB.GetScenePresence(userId), Is.Null); |
385 | 398 | ||
386 | ScenePresence sceneASp = sceneA.GetScenePresence(userId); | 399 | ScenePresence sceneASp = sceneA.GetScenePresence(userId); |
387 | Assert.That(sceneASp, Is.Not.Null); | 400 | Assert.That(sceneASp, Is.Not.Null); |
388 | Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); | 401 | Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); |
389 | Assert.That(sceneASp.AbsolutePosition, Is.EqualTo(preTeleportPosition)); | 402 | Assert.That(sceneASp.AbsolutePosition.X, Is.EqualTo(preTeleportPosition.X)); |
403 | Assert.That(sceneASp.AbsolutePosition.Y, Is.EqualTo(preTeleportPosition.Y)); | ||
390 | 404 | ||
391 | Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); | 405 | Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); |
392 | Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); | 406 | Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); |
@@ -458,6 +472,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
458 | ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); | 472 | ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId); |
459 | sp.AbsolutePosition = preTeleportPosition; | 473 | sp.AbsolutePosition = preTeleportPosition; |
460 | 474 | ||
475 | sceneA.Update(4); | ||
476 | sceneB.Update(4); | ||
477 | |||
461 | sceneA.RequestTeleportLocation( | 478 | sceneA.RequestTeleportLocation( |
462 | sp.ControllingClient, | 479 | sp.ControllingClient, |
463 | sceneB.RegionInfo.RegionHandle, | 480 | sceneB.RegionInfo.RegionHandle, |
@@ -468,13 +485,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
468 | // FIXME: Not setting up InformClientOfNeighbour on the TestClient means that it does not initiate | 485 | // FIXME: Not setting up InformClientOfNeighbour on the TestClient means that it does not initiate |
469 | // communication with the destination region. But this is a very non-obvious way of doing it - really we | 486 | // communication with the destination region. But this is a very non-obvious way of doing it - really we |
470 | // should be forced to expicitly set this up. | 487 | // should be forced to expicitly set this up. |
488 | sceneA.Update(4); | ||
489 | sceneB.Update(4); | ||
471 | 490 | ||
472 | Assert.That(sceneB.GetScenePresence(userId), Is.Null); | 491 | Assert.That(sceneB.GetScenePresence(userId), Is.Null); |
473 | 492 | ||
474 | ScenePresence sceneASp = sceneA.GetScenePresence(userId); | 493 | ScenePresence sceneASp = sceneA.GetScenePresence(userId); |
475 | Assert.That(sceneASp, Is.Not.Null); | 494 | Assert.That(sceneASp, Is.Not.Null); |
476 | Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); | 495 | Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName)); |
477 | Assert.That(sceneASp.AbsolutePosition, Is.EqualTo(preTeleportPosition)); | 496 | Assert.That(sceneASp.AbsolutePosition.X, Is.EqualTo(preTeleportPosition.X)); |
497 | Assert.That(sceneASp.AbsolutePosition.Y, Is.EqualTo(preTeleportPosition.Y)); | ||
478 | 498 | ||
479 | Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); | 499 | Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1)); |
480 | Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); | 500 | Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0)); |
@@ -614,6 +634,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
614 | ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd); | 634 | ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd); |
615 | beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32); | 635 | beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32); |
616 | 636 | ||
637 | sceneA.Update(4); | ||
638 | sceneB.Update(4); | ||
639 | |||
617 | Assert.That(beforeSceneASp, Is.Not.Null); | 640 | Assert.That(beforeSceneASp, Is.Not.Null); |
618 | Assert.That(beforeSceneASp.IsChildAgent, Is.False); | 641 | Assert.That(beforeSceneASp.IsChildAgent, Is.False); |
619 | 642 | ||
@@ -638,6 +661,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
638 | teleportLookAt, | 661 | teleportLookAt, |
639 | (uint)TeleportFlags.ViaLocation); | 662 | (uint)TeleportFlags.ViaLocation); |
640 | 663 | ||
664 | sceneA.Update(4); | ||
665 | sceneB.Update(4); | ||
666 | |||
641 | ScenePresence afterSceneASp = sceneA.GetScenePresence(userId); | 667 | ScenePresence afterSceneASp = sceneA.GetScenePresence(userId); |
642 | Assert.That(afterSceneASp, Is.Not.Null); | 668 | Assert.That(afterSceneASp, Is.Not.Null); |
643 | Assert.That(afterSceneASp.IsChildAgent, Is.True); | 669 | Assert.That(afterSceneASp.IsChildAgent, Is.True); |
@@ -646,7 +672,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
646 | Assert.That(afterSceneBSp, Is.Not.Null); | 672 | Assert.That(afterSceneBSp, Is.Not.Null); |
647 | Assert.That(afterSceneBSp.IsChildAgent, Is.False); | 673 | Assert.That(afterSceneBSp.IsChildAgent, Is.False); |
648 | Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); | 674 | Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName)); |
649 | Assert.That(afterSceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition)); | 675 | Assert.That(afterSceneBSp.AbsolutePosition.X, Is.EqualTo(teleportPosition.X)); |
676 | Assert.That(afterSceneBSp.AbsolutePosition.Y, Is.EqualTo(teleportPosition.Y)); | ||
650 | 677 | ||
651 | Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0)); | 678 | Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0)); |
652 | Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1)); | 679 | Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1)); |
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 0fc724b..e27bbc3 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs | |||
@@ -524,6 +524,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
524 | set { } | 524 | set { } |
525 | } | 525 | } |
526 | 526 | ||
527 | public float StartFar { get; set; } | ||
528 | |||
527 | public bool TryGet<T>(out T iface) | 529 | public bool TryGet<T>(out T iface) |
528 | { | 530 | { |
529 | iface = default(T); | 531 | iface = default(T); |
@@ -932,7 +934,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
932 | OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(),appearance.AvatarSize, new WearableCacheItem[0]); | 934 | OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(),appearance.AvatarSize, new WearableCacheItem[0]); |
933 | } | 935 | } |
934 | 936 | ||
935 | public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) | 937 | public void SendRegionHandshake() |
936 | { | 938 | { |
937 | m_log.Info("[IRCd ClientStack] Completing Handshake to Region"); | 939 | m_log.Info("[IRCd ClientStack] Completing Handshake to Region"); |
938 | 940 | ||
@@ -943,7 +945,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
943 | 945 | ||
944 | if (OnCompleteMovementToRegion != null) | 946 | if (OnCompleteMovementToRegion != null) |
945 | { | 947 | { |
946 | OnCompleteMovementToRegion(this, true); | 948 | OnCompleteMovementToRegion(this, false); |
947 | } | 949 | } |
948 | } | 950 | } |
949 | 951 | ||
@@ -967,11 +969,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
967 | 969 | ||
968 | } | 970 | } |
969 | 971 | ||
970 | public void SendStartPingCheck(byte seq) | ||
971 | { | ||
972 | |||
973 | } | ||
974 | |||
975 | public void SendKillObject(List<uint> localID) | 972 | public void SendKillObject(List<uint> localID) |
976 | { | 973 | { |
977 | 974 | ||
@@ -1160,7 +1157,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
1160 | 1157 | ||
1161 | } | 1158 | } |
1162 | 1159 | ||
1163 | public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory) | 1160 | public void SendXferPacket(ulong xferID, uint packet, |
1161 | byte[] XferData, int XferDataOffset, int XferDatapktLen, bool isTaskInventory) | ||
1164 | { | 1162 | { |
1165 | 1163 | ||
1166 | } | 1164 | } |
@@ -1778,7 +1776,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
1778 | return 0; | 1776 | return 0; |
1779 | } | 1777 | } |
1780 | 1778 | ||
1781 | public void CheckViewerCaps() { } | 1779 | public uint GetViewerCaps() |
1780 | { | ||
1781 | return 0; | ||
1782 | } | ||
1782 | 1783 | ||
1783 | } | 1784 | } |
1784 | } | 1785 | } |
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 65d50bb..4b81838 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | |||
@@ -278,7 +278,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
278 | // There might be some problem with the thread we're generating this on but not | 278 | // There might be some problem with the thread we're generating this on but not |
279 | // doing the update at this time causes problems (Mantis #7920 and #7915) | 279 | // doing the update at this time causes problems (Mantis #7920 and #7915) |
280 | // TODO: move sending this update to a later time in the rootification of the client. | 280 | // TODO: move sending this update to a later time in the rootification of the client. |
281 | if(!sp.haveGroupInformation) | 281 | if(!sp.m_haveGroupInformation) |
282 | SendAgentGroupDataUpdate(sp.ControllingClient, false); | 282 | SendAgentGroupDataUpdate(sp.ControllingClient, false); |
283 | } | 283 | } |
284 | 284 | ||
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs index 822439f..2aea7f9 100644 --- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs +++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs | |||
@@ -133,7 +133,7 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
133 | if(m_changed.Count == 0) | 133 | if(m_changed.Count == 0) |
134 | return; | 134 | return; |
135 | 135 | ||
136 | if(forcedBackup) | 136 | if (forcedBackup) |
137 | { | 137 | { |
138 | toStore = new List<FaceMaterial>(m_changed.Keys); | 138 | toStore = new List<FaceMaterial>(m_changed.Keys); |
139 | m_changed.Clear(); | 139 | m_changed.Clear(); |
@@ -154,16 +154,29 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
154 | m_changed.Remove(fm); | 154 | m_changed.Remove(fm); |
155 | } | 155 | } |
156 | } | 156 | } |
157 | } | ||
157 | 158 | ||
158 | if(toStore.Count > 0) | 159 | if(toStore.Count > 0) |
159 | Util.FireAndForget(delegate | 160 | { |
161 | if (forcedBackup) | ||
160 | { | 162 | { |
161 | foreach(FaceMaterial fm in toStore) | 163 | foreach (FaceMaterial fm in toStore) |
162 | { | 164 | { |
163 | AssetBase a = MakeAsset(fm, false); | 165 | AssetBase a = MakeAsset(fm, false); |
164 | m_scene.AssetService.Store(a); | 166 | m_scene.AssetService.Store(a); |
165 | } | 167 | } |
166 | }); | 168 | } |
169 | else | ||
170 | { | ||
171 | Util.FireAndForget(delegate | ||
172 | { | ||
173 | foreach (FaceMaterial fm in toStore) | ||
174 | { | ||
175 | AssetBase a = MakeAsset(fm, false); | ||
176 | m_scene.AssetService.Store(a); | ||
177 | } | ||
178 | }); | ||
179 | } | ||
167 | } | 180 | } |
168 | } | 181 | } |
169 | 182 | ||
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 9c13061..d3eb25f 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs | |||
@@ -562,6 +562,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
562 | set { } | 562 | set { } |
563 | } | 563 | } |
564 | 564 | ||
565 | public float StartFar { get; set; } | ||
566 | |||
565 | public virtual UUID AgentId | 567 | public virtual UUID AgentId |
566 | { | 568 | { |
567 | get { return m_uuid; } | 569 | get { return m_uuid; } |
@@ -668,10 +670,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
668 | { | 670 | { |
669 | } | 671 | } |
670 | 672 | ||
671 | public virtual void SendStartPingCheck(byte seq) | ||
672 | { | ||
673 | } | ||
674 | |||
675 | public virtual void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data) | 673 | public virtual void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data) |
676 | { | 674 | { |
677 | } | 675 | } |
@@ -870,9 +868,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
870 | { | 868 | { |
871 | } | 869 | } |
872 | 870 | ||
873 | public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory) | 871 | public virtual void SendXferPacket(ulong xferID, uint packet, |
872 | byte[] XferData, int XferDataOffset, int XferDatapktLen, bool isTaskInventory) | ||
874 | { | 873 | { |
875 | } | 874 | } |
875 | |||
876 | public virtual void SendAbortXferPacket(ulong xferID) | 876 | public virtual void SendAbortXferPacket(ulong xferID) |
877 | { | 877 | { |
878 | 878 | ||
@@ -928,7 +928,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
928 | { | 928 | { |
929 | } | 929 | } |
930 | 930 | ||
931 | public virtual void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) | 931 | public virtual void SendRegionHandshake() |
932 | { | 932 | { |
933 | if (OnRegionHandShakeReply != null) | 933 | if (OnRegionHandShakeReply != null) |
934 | { | 934 | { |
@@ -1388,7 +1388,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
1388 | return 0; | 1388 | return 0; |
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | public void CheckViewerCaps() { } | 1391 | public uint GetViewerCaps() |
1392 | { | ||
1393 | return 0; | ||
1394 | } | ||
1392 | 1395 | ||
1393 | } | 1396 | } |
1394 | } | 1397 | } |
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs index 0d4b6b9..de39d0e 100644 --- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs +++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs | |||
@@ -597,28 +597,22 @@ namespace OpenSim.Region.PhysicsModule.Meshing | |||
597 | { | 597 | { |
598 | OSD decodedOsd = null; | 598 | OSD decodedOsd = null; |
599 | 599 | ||
600 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | 600 | using (MemoryStream outMs = new MemoryStream()) |
601 | { | 601 | { |
602 | using (MemoryStream outMs = new MemoryStream()) | 602 | using (MemoryStream inMs = new MemoryStream(meshBytes)) |
603 | { | 603 | { |
604 | using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress)) | 604 | using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress)) |
605 | { | 605 | { |
606 | byte[] readBuffer = new byte[2048]; | 606 | byte[] readBuffer = new byte[8192]; |
607 | inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header | 607 | inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header |
608 | int readLen = 0; | 608 | int readLen = 0; |
609 | 609 | ||
610 | while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0) | 610 | while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0) |
611 | outMs.Write(readBuffer, 0, readLen); | 611 | outMs.Write(readBuffer, 0, readLen); |
612 | |||
613 | outMs.Flush(); | ||
614 | |||
615 | outMs.Seek(0, SeekOrigin.Begin); | ||
616 | |||
617 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
618 | |||
619 | decodedOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
620 | } | 612 | } |
621 | } | 613 | } |
614 | outMs.Seek(0, SeekOrigin.Begin); | ||
615 | decodedOsd = OSDParser.DeserializeLLSDBinary(outMs); | ||
622 | } | 616 | } |
623 | return decodedOsd; | 617 | return decodedOsd; |
624 | } | 618 | } |
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs index 7ad5e3d..b86be0f 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs | |||
@@ -1603,7 +1603,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde | |||
1603 | } | 1603 | } |
1604 | else | 1604 | else |
1605 | { | 1605 | { |
1606 | Vector3 a = _velocity; // previus velocity | 1606 | Vector3 a = _velocity; // previous velocity |
1607 | SetSmooth(ref _velocity,ref vel,2); | 1607 | SetSmooth(ref _velocity,ref vel,2); |
1608 | a = (_velocity - a) * invtimeStep; | 1608 | a = (_velocity - a) * invtimeStep; |
1609 | SetSmooth(ref _acceleration,ref a,2); | 1609 | SetSmooth(ref _acceleration,ref a,2); |
@@ -1921,6 +1921,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde | |||
1921 | 1921 | ||
1922 | _position = newPos; | 1922 | _position = newPos; |
1923 | m_freemove = false; | 1923 | m_freemove = false; |
1924 | _zeroFlag = false; | ||
1924 | m_pidControllerActive = true; | 1925 | m_pidControllerActive = true; |
1925 | } | 1926 | } |
1926 | 1927 | ||
@@ -1976,8 +1977,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde | |||
1976 | 1977 | ||
1977 | private void changeTargetVelocity(Vector3 newVel) | 1978 | private void changeTargetVelocity(Vector3 newVel) |
1978 | { | 1979 | { |
1979 | m_pidControllerActive = true; | 1980 | //m_pidControllerActive = true; |
1980 | m_freemove = false; | 1981 | //m_freemove = false; |
1981 | _target_velocity = newVel; | 1982 | _target_velocity = newVel; |
1982 | if (Body != IntPtr.Zero) | 1983 | if (Body != IntPtr.Zero) |
1983 | SafeNativeMethods.BodyEnable(Body); | 1984 | SafeNativeMethods.BodyEnable(Body); |
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs index 6950f2d..8449596 100644 --- a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs +++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs | |||
@@ -425,31 +425,24 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing | |||
425 | return false; // no mesh data in asset | 425 | return false; // no mesh data in asset |
426 | 426 | ||
427 | OSD decodedMeshOsd = new OSD(); | 427 | OSD decodedMeshOsd = new OSD(); |
428 | byte[] meshBytes = new byte[physSize]; | ||
429 | System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); | ||
430 | |||
431 | try | 428 | try |
432 | { | 429 | { |
433 | using (MemoryStream inMs = new MemoryStream(meshBytes)) | 430 | using (MemoryStream outMs = new MemoryStream(4 * physSize)) |
434 | { | 431 | { |
435 | using (MemoryStream outMs = new MemoryStream()) | 432 | using (MemoryStream inMs = new MemoryStream(primShape.SculptData, physOffset, physSize)) |
436 | { | 433 | { |
437 | using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress)) | 434 | using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress)) |
438 | { | 435 | { |
439 | byte[] readBuffer = new byte[2048]; | 436 | byte[] readBuffer = new byte[8192]; |
440 | inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header | 437 | inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header |
441 | int readLen = 0; | 438 | int readLen = 0; |
442 | 439 | ||
443 | while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0) | 440 | while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0) |
444 | outMs.Write(readBuffer, 0, readLen); | 441 | outMs.Write(readBuffer, 0, readLen); |
445 | |||
446 | outMs.Seek(0, SeekOrigin.Begin); | ||
447 | |||
448 | byte[] decompressedBuf = outMs.GetBuffer(); | ||
449 | |||
450 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); | ||
451 | } | 442 | } |
452 | } | 443 | } |
444 | outMs.Seek(0, SeekOrigin.Begin); | ||
445 | decodedMeshOsd = OSDParser.DeserializeLLSDBinary(outMs); | ||
453 | } | 446 | } |
454 | } | 447 | } |
455 | catch (Exception e) | 448 | catch (Exception e) |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ab3562f..5d72858 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -2403,6 +2403,70 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2403 | ScriptSleep(m_sleepMsOnSetLinkTexture); | 2403 | ScriptSleep(m_sleepMsOnSetLinkTexture); |
2404 | } | 2404 | } |
2405 | 2405 | ||
2406 | protected void SetTextureParams(SceneObjectPart part, string texture, double scaleU, double ScaleV, | ||
2407 | double offsetU, double offsetV, double rotation, int face) | ||
2408 | { | ||
2409 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) | ||
2410 | return; | ||
2411 | |||
2412 | UUID textureID = new UUID(); | ||
2413 | bool dotexture = true; | ||
2414 | if(String.IsNullOrEmpty(texture) || texture == ScriptBaseClass.NULL_KEY) | ||
2415 | dotexture = false; | ||
2416 | else | ||
2417 | { | ||
2418 | textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); | ||
2419 | if (textureID == UUID.Zero) | ||
2420 | { | ||
2421 | if (!UUID.TryParse(texture, out textureID)) | ||
2422 | dotexture = false; | ||
2423 | } | ||
2424 | } | ||
2425 | |||
2426 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
2427 | int nsides = GetNumberOfSides(part); | ||
2428 | |||
2429 | if (face >= 0 && face < nsides) | ||
2430 | { | ||
2431 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
2432 | if (dotexture) | ||
2433 | texface.TextureID = textureID; | ||
2434 | texface.RepeatU = (float)scaleU; | ||
2435 | texface.RepeatV = (float)ScaleV; | ||
2436 | texface.OffsetU = (float)offsetU; | ||
2437 | texface.OffsetV = (float)offsetV; | ||
2438 | texface.Rotation = (float)rotation; | ||
2439 | tex.FaceTextures[face] = texface; | ||
2440 | part.UpdateTextureEntry(tex); | ||
2441 | return; | ||
2442 | } | ||
2443 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
2444 | { | ||
2445 | for (uint i = 0; i < nsides; i++) | ||
2446 | { | ||
2447 | if (tex.FaceTextures[i] != null) | ||
2448 | { | ||
2449 | if (dotexture) | ||
2450 | tex.FaceTextures[i].TextureID = textureID; | ||
2451 | tex.FaceTextures[i].RepeatU = (float)scaleU; | ||
2452 | tex.FaceTextures[i].RepeatV = (float)ScaleV; | ||
2453 | tex.FaceTextures[i].OffsetU = (float)offsetU; | ||
2454 | tex.FaceTextures[i].OffsetV = (float)offsetV; | ||
2455 | tex.FaceTextures[i].Rotation = (float)rotation; | ||
2456 | } | ||
2457 | } | ||
2458 | if (dotexture) | ||
2459 | tex.DefaultTexture.TextureID = textureID; | ||
2460 | tex.DefaultTexture.RepeatU = (float)scaleU; | ||
2461 | tex.DefaultTexture.RepeatV = (float)ScaleV; | ||
2462 | tex.DefaultTexture.OffsetU = (float)offsetU; | ||
2463 | tex.DefaultTexture.OffsetV = (float)offsetV; | ||
2464 | tex.DefaultTexture.Rotation = (float)rotation; | ||
2465 | part.UpdateTextureEntry(tex); | ||
2466 | return; | ||
2467 | } | ||
2468 | } | ||
2469 | |||
2406 | protected void SetTexture(SceneObjectPart part, string texture, int face) | 2470 | protected void SetTexture(SceneObjectPart part, string texture, int face) |
2407 | { | 2471 | { |
2408 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) | 2472 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) |
@@ -3830,6 +3894,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3830 | if (m_item.PermsGranter != m_host.OwnerID) | 3894 | if (m_item.PermsGranter != m_host.OwnerID) |
3831 | return; | 3895 | return; |
3832 | 3896 | ||
3897 | SceneObjectGroup grp = m_host.ParentGroup; | ||
3898 | if (grp == null || grp.IsDeleted || grp.IsAttachment) | ||
3899 | return; | ||
3900 | |||
3833 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) | 3901 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) |
3834 | AttachToAvatar(attachmentPoint); | 3902 | AttachToAvatar(attachmentPoint); |
3835 | } | 3903 | } |
@@ -7991,13 +8059,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7991 | public void llSetTouchText(string text) | 8059 | public void llSetTouchText(string text) |
7992 | { | 8060 | { |
7993 | m_host.AddScriptLPS(1); | 8061 | m_host.AddScriptLPS(1); |
7994 | m_host.TouchName = text; | 8062 | if(text.Length <= 9) |
8063 | m_host.TouchName = text; | ||
8064 | else | ||
8065 | m_host.TouchName = text.Substring(0, 9); | ||
7995 | } | 8066 | } |
7996 | 8067 | ||
7997 | public void llSetSitText(string text) | 8068 | public void llSetSitText(string text) |
7998 | { | 8069 | { |
7999 | m_host.AddScriptLPS(1); | 8070 | m_host.AddScriptLPS(1); |
8000 | m_host.SitName = text; | 8071 | if (text.Length <= 9) |
8072 | m_host.SitName = text; | ||
8073 | else | ||
8074 | m_host.SitName = text.Substring(0, 9); | ||
8001 | } | 8075 | } |
8002 | 8076 | ||
8003 | public void llSetCameraEyeOffset(LSL_Vector offset) | 8077 | public void llSetCameraEyeOffset(LSL_Vector offset) |
@@ -9722,11 +9796,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9722 | return new LSL_List(); | 9796 | return new LSL_List(); |
9723 | } | 9797 | } |
9724 | 9798 | ||
9725 | SetTexture(part, tex, face); | 9799 | SetTextureParams(part, tex, repeats.x, repeats.y, offsets.x, offsets.y, rotation, face); |
9726 | ScaleTexture(part, repeats.x, repeats.y, face); | ||
9727 | OffsetTexture(part, offsets.x, offsets.y, face); | ||
9728 | RotateTexture(part, rotation, face); | ||
9729 | |||
9730 | break; | 9800 | break; |
9731 | 9801 | ||
9732 | case ScriptBaseClass.PRIM_COLOR: | 9802 | case ScriptBaseClass.PRIM_COLOR: |
@@ -10360,17 +10430,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10360 | } | 10430 | } |
10361 | 10431 | ||
10362 | string mapname = rules.Data[idx++].ToString(); | 10432 | string mapname = rules.Data[idx++].ToString(); |
10363 | 10433 | UUID mapID = UUID.Zero; | |
10364 | UUID mapID = ScriptUtils.GetAssetIdFromItemName(m_host, mapname, (int)AssetType.Texture); | 10434 | if (!string.IsNullOrEmpty(mapname)) |
10365 | if (mapID == UUID.Zero) | ||
10366 | { | 10435 | { |
10367 | if (!UUID.TryParse(mapname, out mapID)) | 10436 | mapID = ScriptUtils.GetAssetIdFromItemName(m_host, mapname, (int)AssetType.Texture); |
10437 | if (mapID == UUID.Zero) | ||
10368 | { | 10438 | { |
10369 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be a UUID or a texture name on object inventory", rulesParsed, idx - idxStart - 1)); | 10439 | if (!UUID.TryParse(mapname, out mapID)) |
10370 | return new LSL_List(); | 10440 | { |
10441 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be a UUID or a texture name on object inventory", rulesParsed, idx - idxStart - 1)); | ||
10442 | return new LSL_List(); | ||
10443 | } | ||
10371 | } | 10444 | } |
10372 | } | 10445 | } |
10373 | |||
10374 | LSL_Vector mnrepeat; | 10446 | LSL_Vector mnrepeat; |
10375 | try | 10447 | try |
10376 | { | 10448 | { |
@@ -10427,17 +10499,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10427 | } | 10499 | } |
10428 | 10500 | ||
10429 | string smapname = rules.Data[idx++].ToString(); | 10501 | string smapname = rules.Data[idx++].ToString(); |
10430 | 10502 | UUID smapID = UUID.Zero; | |
10431 | UUID smapID = ScriptUtils.GetAssetIdFromItemName(m_host, smapname, (int)AssetType.Texture); | 10503 | if(!string.IsNullOrEmpty(smapname)) |
10432 | if (smapID == UUID.Zero) | ||
10433 | { | 10504 | { |
10434 | if (!UUID.TryParse(smapname, out smapID)) | 10505 | smapID = ScriptUtils.GetAssetIdFromItemName(m_host, smapname, (int)AssetType.Texture); |
10506 | if (smapID == UUID.Zero) | ||
10435 | { | 10507 | { |
10436 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be a UUID or a texture name on object inventory", rulesParsed, idx - idxStart - 1)); | 10508 | if (!UUID.TryParse(smapname, out smapID)) |
10437 | return new LSL_List(); | 10509 | { |
10510 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be a UUID or a texture name on object inventory", rulesParsed, idx - idxStart - 1)); | ||
10511 | return new LSL_List(); | ||
10512 | } | ||
10438 | } | 10513 | } |
10439 | } | 10514 | } |
10440 | |||
10441 | LSL_Vector msrepeat; | 10515 | LSL_Vector msrepeat; |
10442 | try | 10516 | try |
10443 | { | 10517 | { |
@@ -10653,24 +10727,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10653 | FaceMaterial mat = null; | 10727 | FaceMaterial mat = null; |
10654 | UUID oldid = texface.MaterialID; | 10728 | UUID oldid = texface.MaterialID; |
10655 | 10729 | ||
10656 | if(oldid != UUID.Zero) | 10730 | if(mapID != UUID.Zero) |
10657 | mat = m_materialsModule.GetMaterialCopy(oldid); | 10731 | { |
10732 | if(oldid != UUID.Zero) | ||
10733 | mat = m_materialsModule.GetMaterialCopy(oldid); | ||
10658 | 10734 | ||
10659 | if(mat == null) | 10735 | if(mat == null) |
10660 | mat = new FaceMaterial(); | 10736 | mat = new FaceMaterial(); |
10661 | 10737 | ||
10662 | mat.NormalMapID = mapID; | 10738 | mat.NormalMapID = mapID; |
10663 | mat.NormalOffsetX = offsetX; | 10739 | mat.NormalOffsetX = offsetX; |
10664 | mat.NormalOffsetY = offsetY; | 10740 | mat.NormalOffsetY = offsetY; |
10665 | mat.NormalRepeatX = repeatX; | 10741 | mat.NormalRepeatX = repeatX; |
10666 | mat.NormalRepeatY = repeatY; | 10742 | mat.NormalRepeatY = repeatY; |
10667 | mat.NormalRotation = rot; | 10743 | mat.NormalRotation = rot; |
10668 | 10744 | ||
10669 | UUID id = m_materialsModule.AddNewMaterial(mat); | 10745 | mapID = m_materialsModule.AddNewMaterial(mat); |
10670 | if(oldid == id) | 10746 | } |
10747 | if(oldid == mapID) | ||
10671 | return false; | 10748 | return false; |
10672 | 10749 | ||
10673 | texface.MaterialID = id; | 10750 | texface.MaterialID = mapID; |
10674 | part.Shape.TextureEntry = tex.GetBytes(9); | 10751 | part.Shape.TextureEntry = tex.GetBytes(9); |
10675 | m_materialsModule.RemoveMaterial(oldid); | 10752 | m_materialsModule.RemoveMaterial(oldid); |
10676 | return true; | 10753 | return true; |
@@ -10715,29 +10792,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10715 | FaceMaterial mat = null; | 10792 | FaceMaterial mat = null; |
10716 | UUID oldid = texface.MaterialID; | 10793 | UUID oldid = texface.MaterialID; |
10717 | 10794 | ||
10718 | if(oldid != UUID.Zero) | 10795 | if (mapID != UUID.Zero) |
10719 | mat = m_materialsModule.GetMaterialCopy(oldid); | 10796 | { |
10797 | if (oldid != UUID.Zero) | ||
10798 | mat = m_materialsModule.GetMaterialCopy(oldid); | ||
10720 | 10799 | ||
10721 | if(mat == null) | 10800 | if (mat == null) |
10722 | mat = new FaceMaterial(); | 10801 | mat = new FaceMaterial(); |
10723 | 10802 | ||
10724 | mat.SpecularMapID = mapID; | 10803 | mat.SpecularMapID = mapID; |
10725 | mat.SpecularOffsetX = offsetX; | 10804 | mat.SpecularOffsetX = offsetX; |
10726 | mat.SpecularOffsetY = offsetY; | 10805 | mat.SpecularOffsetY = offsetY; |
10727 | mat.SpecularRepeatX = repeatX; | 10806 | mat.SpecularRepeatX = repeatX; |
10728 | mat.SpecularRepeatY = repeatY; | 10807 | mat.SpecularRepeatY = repeatY; |
10729 | mat.SpecularRotation = rot; | 10808 | mat.SpecularRotation = rot; |
10730 | mat.SpecularLightColorR = colorR; | 10809 | mat.SpecularLightColorR = colorR; |
10731 | mat.SpecularLightColorG = colorG; | 10810 | mat.SpecularLightColorG = colorG; |
10732 | mat.SpecularLightColorB = colorB; | 10811 | mat.SpecularLightColorB = colorB; |
10733 | mat.SpecularLightExponent = gloss; | 10812 | mat.SpecularLightExponent = gloss; |
10734 | mat.EnvironmentIntensity = env; | 10813 | mat.EnvironmentIntensity = env; |
10735 | 10814 | ||
10736 | UUID id = m_materialsModule.AddNewMaterial(mat); | 10815 | mapID = m_materialsModule.AddNewMaterial(mat); |
10737 | if(oldid == id) | 10816 | } |
10817 | |||
10818 | if(oldid == mapID) | ||
10738 | return false; | 10819 | return false; |
10739 | 10820 | ||
10740 | texface.MaterialID = id; | 10821 | texface.MaterialID = mapID; |
10741 | part.Shape.TextureEntry = tex.GetBytes(9); | 10822 | part.Shape.TextureEntry = tex.GetBytes(9); |
10742 | m_materialsModule.RemoveMaterial(oldid); | 10823 | m_materialsModule.RemoveMaterial(oldid); |
10743 | return true; | 10824 | return true; |
@@ -14111,15 +14192,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
14111 | { | 14192 | { |
14112 | m_host.AddScriptLPS(1); | 14193 | m_host.AddScriptLPS(1); |
14113 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; | 14194 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; |
14114 | if (land.OwnerID == m_host.OwnerID) | 14195 | if (land.OwnerID == m_host.OwnerID && land.ParcelAccessList.Count > 0) |
14115 | { | 14196 | { |
14197 | var todelete = new List<LandAccessEntry>(); | ||
14116 | foreach (LandAccessEntry entry in land.ParcelAccessList) | 14198 | foreach (LandAccessEntry entry in land.ParcelAccessList) |
14117 | { | 14199 | { |
14118 | if (entry.Flags == AccessList.Ban) | 14200 | if (entry.Flags == AccessList.Ban) |
14119 | { | 14201 | todelete.Add(entry); |
14120 | land.ParcelAccessList.Remove(entry); | ||
14121 | } | ||
14122 | } | 14202 | } |
14203 | foreach (LandAccessEntry entry in todelete) | ||
14204 | land.ParcelAccessList.Remove(entry); | ||
14123 | } | 14205 | } |
14124 | ScriptSleep(m_sleepMsOnResetLandBanList); | 14206 | ScriptSleep(m_sleepMsOnResetLandBanList); |
14125 | } | 14207 | } |
@@ -14128,15 +14210,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
14128 | { | 14210 | { |
14129 | m_host.AddScriptLPS(1); | 14211 | m_host.AddScriptLPS(1); |
14130 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; | 14212 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; |
14131 | if (land.OwnerID == m_host.OwnerID) | 14213 | if (land.OwnerID == m_host.OwnerID && land.ParcelAccessList.Count > 0) |
14132 | { | 14214 | { |
14215 | var todelete = new List<LandAccessEntry>(); | ||
14133 | foreach (LandAccessEntry entry in land.ParcelAccessList) | 14216 | foreach (LandAccessEntry entry in land.ParcelAccessList) |
14134 | { | 14217 | { |
14135 | if (entry.Flags == AccessList.Access) | 14218 | if (entry.Flags == AccessList.Access) |
14136 | { | 14219 | todelete.Add(entry); |
14137 | land.ParcelAccessList.Remove(entry); | ||
14138 | } | ||
14139 | } | 14220 | } |
14221 | foreach (LandAccessEntry entry in todelete) | ||
14222 | land.ParcelAccessList.Remove(entry); | ||
14140 | } | 14223 | } |
14141 | ScriptSleep(m_sleepMsOnResetLandPassList); | 14224 | ScriptSleep(m_sleepMsOnResetLandPassList); |
14142 | } | 14225 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index dabd399..7d3c832 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -145,6 +145,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
145 | protected IUrlModule m_UrlModule = null; | 145 | protected IUrlModule m_UrlModule = null; |
146 | protected ISoundModule m_SoundModule = null; | 146 | protected ISoundModule m_SoundModule = null; |
147 | internal IConfig m_osslconfig; | 147 | internal IConfig m_osslconfig; |
148 | internal TimeZoneInfo PSTTimeZone = null; | ||
148 | 149 | ||
149 | public void Initialize( | 150 | public void Initialize( |
150 | IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item) | 151 | IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item) |
@@ -201,7 +202,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
201 | default: | 202 | default: |
202 | break; | 203 | break; |
203 | } | 204 | } |
204 | } | 205 | |
206 | try | ||
207 | { | ||
208 | PSTTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); | ||
209 | } | ||
210 | catch | ||
211 | { | ||
212 | PSTTimeZone = null; | ||
213 | } | ||
214 | if(PSTTimeZone == null) | ||
215 | { | ||
216 | try | ||
217 | { | ||
218 | PSTTimeZone = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles"); | ||
219 | } | ||
220 | catch | ||
221 | { | ||
222 | PSTTimeZone = null; | ||
223 | } | ||
224 | } | ||
225 | } | ||
205 | 226 | ||
206 | public override Object InitializeLifetimeService() | 227 | public override Object InitializeLifetimeService() |
207 | { | 228 | { |
@@ -903,6 +924,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
903 | } | 924 | } |
904 | 925 | ||
905 | // Teleport functions | 926 | // Teleport functions |
927 | public void osLocalTeleportAgent(LSL_Key agent, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, LSL_Types.Vector3 lookat, LSL_Integer flags) | ||
928 | { | ||
929 | UUID agentId; | ||
930 | if (!UUID.TryParse(agent, out agentId)) | ||
931 | return; | ||
932 | |||
933 | ScenePresence presence = World.GetScenePresence(agentId); | ||
934 | if (presence == null || presence.IsDeleted || presence.IsInTransit) | ||
935 | return; | ||
936 | |||
937 | Vector3 pos = presence.AbsolutePosition; | ||
938 | if (!checkAllowAgentTPbyLandOwner(agentId, pos)) | ||
939 | return; | ||
940 | |||
941 | World.RequestLocalTeleport(presence, position, velocity, lookat, flags); | ||
942 | } | ||
943 | |||
906 | public void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) | 944 | public void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) |
907 | { | 945 | { |
908 | // High because there is no security check. High griefer potential | 946 | // High because there is no security check. High griefer potential |
@@ -3780,7 +3818,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3780 | 3818 | ||
3781 | public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules) | 3819 | public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules) |
3782 | { | 3820 | { |
3783 | CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); | 3821 | CheckThreatLevel(); |
3784 | 3822 | ||
3785 | InitLSL(); | 3823 | InitLSL(); |
3786 | return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); | 3824 | return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); |
@@ -3788,7 +3826,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3788 | 3826 | ||
3789 | public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) | 3827 | public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) |
3790 | { | 3828 | { |
3791 | CheckThreatLevel(ThreatLevel.High, "osSetPrimitiveParams"); | 3829 | CheckThreatLevel(); |
3792 | 3830 | ||
3793 | InitLSL(); | 3831 | InitLSL(); |
3794 | m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); | 3832 | m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); |
@@ -3797,15 +3835,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3797 | /// <summary> | 3835 | /// <summary> |
3798 | /// Set parameters for light projection in host prim | 3836 | /// Set parameters for light projection in host prim |
3799 | /// </summary> | 3837 | /// </summary> |
3800 | public void osSetProjectionParams(bool projection, LSL_Key texture, double fov, double focus, double amb) | 3838 | public void osSetProjectionParams(LSL_Integer projection, LSL_Key texture, LSL_Float fov, LSL_Float focus, LSL_Float amb) |
3839 | { | ||
3840 | SetProjectionParams(m_host, projection, texture, fov, focus, amb); | ||
3841 | } | ||
3842 | |||
3843 | /// <summary> | ||
3844 | /// Set parameters for light projection of a linkset prim | ||
3845 | /// </summary> | ||
3846 | public void osSetProjectionParams(LSL_Integer linknum, LSL_Integer projection, LSL_Key texture, LSL_Float fov, LSL_Float focus, LSL_Float amb) | ||
3801 | { | 3847 | { |
3802 | osSetProjectionParams(UUID.Zero.ToString(), projection, texture, fov, focus, amb); | 3848 | if (linknum == ScriptBaseClass.LINK_THIS || linknum == m_host.LinkNum) |
3849 | { | ||
3850 | SetProjectionParams(m_host, projection, texture, fov, focus, amb); | ||
3851 | return; | ||
3852 | } | ||
3853 | |||
3854 | if (linknum < 0 || linknum > m_host.ParentGroup.PrimCount) | ||
3855 | return; | ||
3856 | |||
3857 | if(linknum < 2 && m_host.LinkNum < 2) | ||
3858 | { | ||
3859 | SetProjectionParams(m_host, projection, texture, fov, focus, amb); | ||
3860 | return; | ||
3861 | } | ||
3862 | |||
3863 | SceneObjectPart obj = m_host.ParentGroup.GetLinkNumPart(linknum); | ||
3864 | if(obj != null) | ||
3865 | SetProjectionParams(obj, projection, texture, fov, focus, amb); | ||
3803 | } | 3866 | } |
3804 | 3867 | ||
3805 | /// <summary> | 3868 | /// <summary> |
3806 | /// Set parameters for light projection with uuid of target prim | 3869 | /// Set parameters for light projection with uuid of target prim |
3807 | /// </summary> | 3870 | /// </summary> |
3808 | public void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb) | 3871 | public void osSetProjectionParams(LSL_Key prim, LSL_Integer llprojection, LSL_Key texture, LSL_Float fov, LSL_Float focus, LSL_Float amb) |
3809 | { | 3872 | { |
3810 | CheckThreatLevel(ThreatLevel.High, "osSetProjectionParams"); | 3873 | CheckThreatLevel(ThreatLevel.High, "osSetProjectionParams"); |
3811 | 3874 | ||
@@ -3820,7 +3883,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3820 | if (obj == null) | 3883 | if (obj == null) |
3821 | return; | 3884 | return; |
3822 | } | 3885 | } |
3886 | SetProjectionParams(obj, llprojection, texture, fov, focus, amb); | ||
3887 | } | ||
3823 | 3888 | ||
3889 | private void SetProjectionParams(SceneObjectPart obj, LSL_Integer llprojection, LSL_Key texture, LSL_Float fov, LSL_Float focus, LSL_Float amb) | ||
3890 | { | ||
3891 | bool projection = llprojection != 0; | ||
3824 | obj.Shape.ProjectionEntry = projection; | 3892 | obj.Shape.ProjectionEntry = projection; |
3825 | obj.Shape.ProjectionTextureUUID = new UUID(texture); | 3893 | obj.Shape.ProjectionTextureUUID = new UUID(texture); |
3826 | obj.Shape.ProjectionFOV = (float)fov; | 3894 | obj.Shape.ProjectionFOV = (float)fov; |
@@ -5441,5 +5509,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5441 | return String.Empty; | 5509 | return String.Empty; |
5442 | return detectedParams.Key.ToString(); | 5510 | return detectedParams.Key.ToString(); |
5443 | } | 5511 | } |
5512 | |||
5513 | // returns PST or PDT wall clock | ||
5514 | public LSL_Float osGetPSTWallclock() | ||
5515 | { | ||
5516 | m_host.AddScriptLPS(1); | ||
5517 | if(PSTTimeZone == null) | ||
5518 | return DateTime.Now.TimeOfDay.TotalSeconds; | ||
5519 | |||
5520 | DateTime time = TimeZoneInfo.ConvertTime(DateTime.UtcNow, PSTTimeZone); | ||
5521 | return time.TimeOfDay.TotalSeconds; | ||
5522 | } | ||
5444 | } | 5523 | } |
5445 | } \ No newline at end of file | 5524 | } \ No newline at end of file |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 49b3f74..194df36 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | |||
@@ -150,6 +150,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
150 | string osGetAgentIP(string agent); | 150 | string osGetAgentIP(string agent); |
151 | 151 | ||
152 | // Teleport commands | 152 | // Teleport commands |
153 | void osLocalTeleportAgent(LSL_Key agent, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, LSL_Types.Vector3 lookat, LSL_Integer flags); | ||
153 | void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); | 154 | void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); |
154 | void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); | 155 | void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); |
155 | void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); | 156 | void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); |
@@ -393,8 +394,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
393 | void osForceOtherSit(string avatar, string target); | 394 | void osForceOtherSit(string avatar, string target); |
394 | LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); | 395 | LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); |
395 | void osSetPrimitiveParams(LSL_Key prim, LSL_List rules); | 396 | void osSetPrimitiveParams(LSL_Key prim, LSL_List rules); |
396 | void osSetProjectionParams(bool projection, LSL_Key texture, double fov, double focus, double amb); | 397 | void osSetProjectionParams(LSL_Integer projection, LSL_Key texture, LSL_Float fov, LSL_Float focus, LSL_Float amb); |
397 | void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb); | 398 | void osSetProjectionParams(LSL_Key prim, LSL_Integer projection, LSL_Key texture, LSL_Float fov, LSL_Float focus, LSL_Float amb); |
399 | void osSetProjectionParams(LSL_Integer linknumber, LSL_Integer projection, LSL_Key texture, LSL_Float fov, LSL_Float focus, LSL_Float amb); | ||
398 | 400 | ||
399 | LSL_List osGetAvatarList(); | 401 | LSL_List osGetAvatarList(); |
400 | LSL_List osGetNPCList(); | 402 | LSL_List osGetNPCList(); |
@@ -549,5 +551,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
549 | LSL_String osGetInventoryName(LSL_Key itemId); | 551 | LSL_String osGetInventoryName(LSL_Key itemId); |
550 | LSL_String osGetInventoryDesc(LSL_String itemNameOrId); | 552 | LSL_String osGetInventoryDesc(LSL_String itemNameOrId); |
551 | LSL_Key osGetLastChangedEventKey(); | 553 | LSL_Key osGetLastChangedEventKey(); |
554 | LSL_Float osGetPSTWallclock(); | ||
552 | } | 555 | } |
553 | } | 556 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 8b70128..fa0e25c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | |||
@@ -35,7 +35,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
35 | public partial class ScriptBaseClass | 35 | public partial class ScriptBaseClass |
36 | { | 36 | { |
37 | // SCRIPTS CONSTANTS | 37 | // SCRIPTS CONSTANTS |
38 | public static readonly LSLInteger OS_APIVERSION = 3; | 38 | public static readonly LSLInteger OS_APIVERSION = 4; |
39 | 39 | ||
40 | public static readonly LSLInteger TRUE = 1; | 40 | public static readonly LSLInteger TRUE = 1; |
41 | public static readonly LSLInteger FALSE = 0; | 41 | public static readonly LSLInteger FALSE = 0; |
@@ -189,6 +189,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
189 | public const int VEHICLE_RANGE_BLOCK = 45; | 189 | public const int VEHICLE_RANGE_BLOCK = 45; |
190 | public const int VEHICLE_ROLL_FRAME = 46; | 190 | public const int VEHICLE_ROLL_FRAME = 46; |
191 | public const int VEHICLE_FLAG_NO_DEFLECTION_UP = 1; | 191 | public const int VEHICLE_FLAG_NO_DEFLECTION_UP = 1; |
192 | public const int VEHICLE_FLAG_NO_FLY_UP = 1; //legacy | ||
192 | public const int VEHICLE_FLAG_LIMIT_ROLL_ONLY = 2; | 193 | public const int VEHICLE_FLAG_LIMIT_ROLL_ONLY = 2; |
193 | public const int VEHICLE_FLAG_HOVER_WATER_ONLY = 4; | 194 | public const int VEHICLE_FLAG_HOVER_WATER_ONLY = 4; |
194 | public const int VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 8; | 195 | public const int VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 8; |
@@ -898,6 +899,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
898 | //ApiDesc osTeleportObject flag: the rotation is the final rotation, otherwise is a added rotation | 899 | //ApiDesc osTeleportObject flag: the rotation is the final rotation, otherwise is a added rotation |
899 | public const int OSTPOBJ_SETROT = 0x4; | 900 | public const int OSTPOBJ_SETROT = 0x4; |
900 | 901 | ||
902 | //ApiDesc osLocalTeleportAgent no flags | ||
903 | public const int OS_LTPAG_NONE = 0x0; | ||
904 | //ApiDesc osLocalTeleportAgent use velocity | ||
905 | public const int OS_LTPAG_USEVEL = 0x1; | ||
906 | //ApiDesc osLocalTeleportAgent use lookat | ||
907 | public const int OS_LTPAG_USELOOKAT = 0x2; | ||
908 | //ApiDesc osLocalTeleportAgent align lookat to velocity | ||
909 | public const int OS_LTPAG_ALGNLV = 0x4; | ||
910 | //ApiDesc osLocalTeleportAgent force fly | ||
911 | public const int OS_LTPAG_FORCEFLY = 0x8; | ||
912 | //ApiDesc osLocalTeleportAgent force no fly | ||
913 | public const int OS_LTPAG_FORCENOFLY = 0x16; | ||
914 | |||
901 | // Constants for Windlight | 915 | // Constants for Windlight |
902 | public const int WL_WATER_COLOR = 0; | 916 | public const int WL_WATER_COLOR = 0; |
903 | public const int WL_WATER_FOG_DENSITY_EXPONENT = 1; | 917 | public const int WL_WATER_FOG_DENSITY_EXPONENT = 1; |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index fb491e4..88ea9d5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | |||
@@ -247,6 +247,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
247 | 247 | ||
248 | // Teleport Functions | 248 | // Teleport Functions |
249 | 249 | ||
250 | public void osLocalTeleportAgent(LSL_Key agent, vector position, vector velocity, vector lookat, LSL_Integer flags) | ||
251 | { | ||
252 | m_OSSL_Functions.osLocalTeleportAgent(agent, position, velocity, lookat, flags); | ||
253 | } | ||
254 | |||
250 | public void osTeleportAgent(string agent, string regionName, vector position, vector lookat) | 255 | public void osTeleportAgent(string agent, string regionName, vector position, vector lookat) |
251 | { | 256 | { |
252 | m_OSSL_Functions.osTeleportAgent(agent, regionName, position, lookat); | 257 | m_OSSL_Functions.osTeleportAgent(agent, regionName, position, lookat); |
@@ -1035,16 +1040,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
1035 | m_OSSL_Functions.osSetPrimitiveParams(prim, rules); | 1040 | m_OSSL_Functions.osSetPrimitiveParams(prim, rules); |
1036 | } | 1041 | } |
1037 | 1042 | ||
1038 | public void osSetProjectionParams(bool projection, LSL_Key texture, double fov, double focus, double amb) | 1043 | public void osSetProjectionParams(LSL_Integer projection, LSL_Key texture, double fov, double focus, double amb) |
1039 | { | 1044 | { |
1040 | m_OSSL_Functions.osSetProjectionParams(projection, texture, fov, focus, amb); | 1045 | m_OSSL_Functions.osSetProjectionParams(projection, texture, fov, focus, amb); |
1041 | } | 1046 | } |
1042 | 1047 | ||
1043 | public void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb) | 1048 | public void osSetProjectionParams(LSL_Key prim, LSL_Integer projection, LSL_Key texture, double fov, double focus, double amb) |
1044 | { | 1049 | { |
1045 | m_OSSL_Functions.osSetProjectionParams(prim, projection, texture, fov, focus, amb); | 1050 | m_OSSL_Functions.osSetProjectionParams(prim, projection, texture, fov, focus, amb); |
1046 | } | 1051 | } |
1047 | 1052 | ||
1053 | public void osSetProjectionParams(LSL_Integer linknumber, LSL_Integer projection, LSL_Key texture, LSL_Float fov, LSL_Float focus, LSL_Float amb) | ||
1054 | { | ||
1055 | m_OSSL_Functions.osSetProjectionParams(linknumber, projection, texture, fov, focus, amb); | ||
1056 | } | ||
1057 | |||
1048 | public LSL_List osGetAvatarList() | 1058 | public LSL_List osGetAvatarList() |
1049 | { | 1059 | { |
1050 | return m_OSSL_Functions.osGetAvatarList(); | 1060 | return m_OSSL_Functions.osGetAvatarList(); |
@@ -1381,5 +1391,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
1381 | { | 1391 | { |
1382 | return m_OSSL_Functions.osGetLastChangedEventKey(); | 1392 | return m_OSSL_Functions.osGetLastChangedEventKey(); |
1383 | } | 1393 | } |
1394 | |||
1395 | public LSL_Float osGetPSTWallclock() | ||
1396 | { | ||
1397 | return m_OSSL_Functions.osGetPSTWallclock(); | ||
1398 | } | ||
1399 | |||
1384 | } | 1400 | } |
1385 | } | 1401 | } |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs index 5f00f86..27fde5b 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs | |||
@@ -69,7 +69,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
69 | 69 | ||
70 | public static readonly string OBJECT_CODE_MAGIC = "YObjectCode"; | 70 | public static readonly string OBJECT_CODE_MAGIC = "YObjectCode"; |
71 | // reserve positive version values for original xmr | 71 | // reserve positive version values for original xmr |
72 | public static int COMPILED_VERSION_VALUE = -1; // decremented when compiler or object file changes | 72 | public static int COMPILED_VERSION_VALUE = -2; // decremented when compiler or object file changes |
73 | 73 | ||
74 | public static readonly int CALL_FRAME_MEMUSE = 64; | 74 | public static readonly int CALL_FRAME_MEMUSE = 64; |
75 | public static readonly int STRING_LEN_TO_MEMUSE = 2; | 75 | public static readonly int STRING_LEN_TO_MEMUSE = 2; |
@@ -197,7 +197,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
197 | public CallLabel openCallLabel = null; // only one call label can be open at a time | 197 | public CallLabel openCallLabel = null; // only one call label can be open at a time |
198 | // - the call label is open from the time of CallPre() until corresponding CallPost() | 198 | // - the call label is open from the time of CallPre() until corresponding CallPost() |
199 | // - so no non-trivial pushes/pops etc allowed between a CallPre() and a CallPost() | 199 | // - so no non-trivial pushes/pops etc allowed between a CallPre() and a CallPost() |
200 | 200 | public List<ScriptMyLocal> HeapLocals = new List<ScriptMyLocal>(); | |
201 | private ScriptMyILGen _ilGen; | 201 | private ScriptMyILGen _ilGen; |
202 | public ScriptMyILGen ilGen | 202 | public ScriptMyILGen ilGen |
203 | { | 203 | { |
@@ -1258,6 +1258,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
1258 | // resume at the correct spot. | 1258 | // resume at the correct spot. |
1259 | actCallLabels.Clear(); | 1259 | actCallLabels.Clear(); |
1260 | allCallLabels.Clear(); | 1260 | allCallLabels.Clear(); |
1261 | HeapLocals.Clear(); | ||
1261 | openCallLabel = null; | 1262 | openCallLabel = null; |
1262 | 1263 | ||
1263 | // Alloc stack space for local vars. | 1264 | // Alloc stack space for local vars. |
@@ -1398,19 +1399,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
1398 | _ilGen = collector.WriteOutAll(); | 1399 | _ilGen = collector.WriteOutAll(); |
1399 | collector = null; | 1400 | collector = null; |
1400 | 1401 | ||
1401 | // Output code to restore stack frame from stream. | ||
1402 | // It jumps back to the call labels within the function body. | ||
1403 | List<ScriptMyLocal> activeTemps = null; | 1402 | List<ScriptMyLocal> activeTemps = null; |
1404 | if(!isTrivial) | 1403 | if (!isTrivial) |
1405 | { | 1404 | { |
1406 | // Build list of locals and temps active at all the call labels. | 1405 | // Build list of locals and temps active at all the call labels. |
1407 | activeTemps = new List<ScriptMyLocal>(); | 1406 | activeTemps = new List<ScriptMyLocal>(); |
1408 | foreach(CallLabel cl in allCallLabels) | 1407 | foreach (CallLabel cl in allCallLabels) |
1409 | { | ||
1410 | foreach(ScriptMyLocal lcl in cl.callLabel.whereAmI.localsReadBeforeWritten) | ||
1411 | { | 1408 | { |
1412 | if(!activeTemps.Contains(lcl)) | 1409 | foreach(ScriptMyLocal lcl in cl.callLabel.whereAmI.localsReadBeforeWritten) |
1413 | { | 1410 | { |
1411 | if(!activeTemps.Contains(lcl)) | ||
1412 | { | ||
1414 | activeTemps.Add(lcl); | 1413 | activeTemps.Add(lcl); |
1415 | } | 1414 | } |
1416 | } | 1415 | } |
@@ -1452,11 +1451,34 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
1452 | } | 1451 | } |
1453 | 1452 | ||
1454 | // Output the 'real' return opcode. | 1453 | // Output the 'real' return opcode. |
1454 | // push return value | ||
1455 | ilGen.MarkLabel(retLabel); | 1455 | ilGen.MarkLabel(retLabel); |
1456 | if(!(curDeclFunc.retType is TokenTypeVoid)) | 1456 | if (!(curDeclFunc.retType is TokenTypeVoid)) |
1457 | { | 1457 | { |
1458 | ilGen.Emit(curDeclFunc, OpCodes.Ldloc, retValue); | 1458 | ilGen.Emit(curDeclFunc, OpCodes.Ldloc, retValue); |
1459 | } | 1459 | } |
1460 | |||
1461 | // pseudo free memory usage | ||
1462 | foreach (ScriptMyLocal sml in HeapLocals) | ||
1463 | { | ||
1464 | Type t = sml.type; | ||
1465 | if (t == typeof(HeapTrackerList)) | ||
1466 | { | ||
1467 | ilGen.Emit(curDeclFunc, OpCodes.Ldloc, sml); | ||
1468 | HeapTrackerList.GenFree(curDeclFunc, ilGen); | ||
1469 | } | ||
1470 | else if (t == typeof(HeapTrackerString)) | ||
1471 | { | ||
1472 | ilGen.Emit(curDeclFunc, OpCodes.Ldloc, sml); | ||
1473 | HeapTrackerString.GenFree(curDeclFunc, ilGen); | ||
1474 | } | ||
1475 | else if (t == typeof(HeapTrackerObject)) | ||
1476 | { | ||
1477 | ilGen.Emit(curDeclFunc, OpCodes.Ldloc, sml); | ||
1478 | HeapTrackerObject.GenFree(curDeclFunc, ilGen); | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1460 | ilGen.Emit(curDeclFunc, OpCodes.Ret); | 1482 | ilGen.Emit(curDeclFunc, OpCodes.Ret); |
1461 | retLabel = null; | 1483 | retLabel = null; |
1462 | retValue = null; | 1484 | retValue = null; |
@@ -1675,11 +1697,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
1675 | if(u != t) | 1697 | if(u != t) |
1676 | { | 1698 | { |
1677 | if(t == typeof(HeapTrackerList)) | 1699 | if(t == typeof(HeapTrackerList)) |
1678 | HeapTrackerList.GenPop(curDeclFunc, ilGen); | 1700 | HeapTrackerList.GenRestore(curDeclFunc, ilGen); |
1679 | if(t == typeof(HeapTrackerObject)) | 1701 | if(t == typeof(HeapTrackerObject)) |
1680 | HeapTrackerObject.GenPop(curDeclFunc, ilGen); | 1702 | HeapTrackerObject.GenRestore(curDeclFunc, ilGen); |
1681 | if(t == typeof(HeapTrackerString)) | 1703 | if(t == typeof(HeapTrackerString)) |
1682 | HeapTrackerString.GenPop(curDeclFunc, ilGen); | 1704 | HeapTrackerString.GenRestore(curDeclFunc, ilGen); |
1683 | } | 1705 | } |
1684 | else | 1706 | else |
1685 | { | 1707 | { |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCollector.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCollector.cs index 75eae53..e92f429 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCollector.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCollector.cs | |||
@@ -2611,10 +2611,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
2611 | // everything required by any blocks it can branch to. | 2611 | // everything required by any blocks it can branch to. |
2612 | do | 2612 | do |
2613 | { | 2613 | { |
2614 | this.resolvedSomething = false; | 2614 | resolvedSomething = false; |
2615 | this.resolveSequence++; | 2615 | resolveSequence++; |
2616 | this.ResolveBlock((GraphNodeBlock)firstLin); | 2616 | ResolveBlock((GraphNodeBlock)firstLin); |
2617 | } while(this.resolvedSomething); | 2617 | } while(resolvedSomething); |
2618 | 2618 | ||
2619 | // Repeat the cutting loops as long as we keep finding stuff. | 2619 | // Repeat the cutting loops as long as we keep finding stuff. |
2620 | bool didSomething; | 2620 | bool didSomething; |
@@ -2939,7 +2939,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
2939 | return; | 2939 | return; |
2940 | 2940 | ||
2941 | // So we don't recurse forever on a backward branch. | 2941 | // So we don't recurse forever on a backward branch. |
2942 | currentBlock.hasBeenResolved = this.resolveSequence; | 2942 | currentBlock.hasBeenResolved = resolveSequence; |
2943 | 2943 | ||
2944 | // Assume we haven't written any locals yet. | 2944 | // Assume we haven't written any locals yet. |
2945 | List<ScriptMyLocal> localsWrittenSoFar = new List<ScriptMyLocal>(); | 2945 | List<ScriptMyLocal> localsWrittenSoFar = new List<ScriptMyLocal>(); |
@@ -2975,7 +2975,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
2975 | !currentBlock.localsReadBeforeWritten.Contains(readByNextBlock)) | 2975 | !currentBlock.localsReadBeforeWritten.Contains(readByNextBlock)) |
2976 | { | 2976 | { |
2977 | currentBlock.localsReadBeforeWritten.Add(readByNextBlock); | 2977 | currentBlock.localsReadBeforeWritten.Add(readByNextBlock); |
2978 | this.resolvedSomething = true; | 2978 | resolvedSomething = true; |
2979 | } | 2979 | } |
2980 | } | 2980 | } |
2981 | } | 2981 | } |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompValu.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompValu.cs index 675ab9a..486d822 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompValu.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompValu.cs | |||
@@ -1483,7 +1483,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
1483 | { | 1483 | { |
1484 | if(type.ToHeapTrackerType() != null) | 1484 | if(type.ToHeapTrackerType() != null) |
1485 | { | 1485 | { |
1486 | this.localBuilder = scg.ilGen.DeclareLocal(type.ToHeapTrackerType(), name); | 1486 | localBuilder = scg.ilGen.DeclareLocal(type.ToHeapTrackerType(), name); |
1487 | scg.HeapLocals.Add(localBuilder); | ||
1487 | scg.PushXMRInst(); | 1488 | scg.PushXMRInst(); |
1488 | scg.ilGen.Emit(type, OpCodes.Newobj, type.GetHeapTrackerCtor()); | 1489 | scg.ilGen.Emit(type, OpCodes.Newobj, type.GetHeapTrackerCtor()); |
1489 | scg.ilGen.Emit(type, OpCodes.Stloc, localBuilder); | 1490 | scg.ilGen.Emit(type, OpCodes.Stloc, localBuilder); |
@@ -1547,6 +1548,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
1547 | scg.ilGen.Emit(errorAt, OpCodes.Ldloc, localBuilder); | 1548 | scg.ilGen.Emit(errorAt, OpCodes.Ldloc, localBuilder); |
1548 | scg.ilGen.Emit(errorAt, OpCodes.Ldloc, htpop); | 1549 | scg.ilGen.Emit(errorAt, OpCodes.Ldloc, htpop); |
1549 | type.CallHeapTrackerPopMeth(errorAt, scg.ilGen); | 1550 | type.CallHeapTrackerPopMeth(errorAt, scg.ilGen); |
1551 | scg.HeapLocals.Add(htpop); | ||
1550 | } | 1552 | } |
1551 | else | 1553 | else |
1552 | { | 1554 | { |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompile.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompile.cs index f37efd4..8e15402 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompile.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompile.cs | |||
@@ -130,7 +130,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
130 | // Since we just wrote the .xmrobj file, maybe save disassembly. | 130 | // Since we just wrote the .xmrobj file, maybe save disassembly. |
131 | if (m_Engine.m_ScriptDebugSaveIL) | 131 | if (m_Engine.m_ScriptDebugSaveIL) |
132 | { | 132 | { |
133 | string asmFileName = GetScriptFileName (m_ScriptObjCodeKey + ".yasm"); | 133 | string asmFileName = GetScriptILFileName(m_ScriptObjCodeKey + ".yasm"); |
134 | // m_log.Debug ("[YEngine]: MMRScriptCompileSaveILGen: saving to " + asmFileName); | 134 | // m_log.Debug ("[YEngine]: MMRScriptCompileSaveILGen: saving to " + asmFileName); |
135 | asmFileWriter = File.CreateText (asmFileName); | 135 | asmFileWriter = File.CreateText (asmFileName); |
136 | } | 136 | } |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRArray.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRArray.cs index 3d0525b..930a8d6 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRArray.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRArray.cs | |||
@@ -125,7 +125,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
125 | 125 | ||
126 | // Save new value in array, replacing one of same key if there. | 126 | // Save new value in array, replacing one of same key if there. |
127 | // null means remove the value, ie, script did array[key] = undef. | 127 | // null means remove the value, ie, script did array[key] = undef. |
128 | if(value != null) | 128 | if (value != null) |
129 | { | 129 | { |
130 | dnary[key] = value; | 130 | dnary[key] = value; |
131 | } | 131 | } |
@@ -285,10 +285,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
285 | public void RecvArrayObj(RecvArrayObjDelegate recvObj) | 285 | public void RecvArrayObj(RecvArrayObjDelegate recvObj) |
286 | { | 286 | { |
287 | heapUse = inst.UpdateHeapUse(heapUse, EMPTYHEAP); | 287 | heapUse = inst.UpdateHeapUse(heapUse, EMPTYHEAP); |
288 | 288 | // Cause any enumeration to refill the array from the sorted dictionary. | |
289 | // Cause any enumeration to refill the array from the sorted dictionary. | 289 | // Since it is a sorted dictionary, any enumerations will be in the same |
290 | // Since it is a sorted dictionary, any enumerations will be in the same | 290 | // order as on the sending side. |
291 | // order as on the sending side. | ||
292 | arrayValid = 0; | 291 | arrayValid = 0; |
293 | enumrValid = false; | 292 | enumrValid = false; |
294 | 293 | ||
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs index 6acc293..e1f8c4c 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs | |||
@@ -1535,15 +1535,38 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
1535 | */ | 1535 | */ |
1536 | public void QueueToStart(XMRInstance inst) | 1536 | public void QueueToStart(XMRInstance inst) |
1537 | { | 1537 | { |
1538 | if(inst.m_IState != XMRInstState.ONSTARTQ) | 1538 | if (inst.m_IState != XMRInstState.ONSTARTQ) |
1539 | throw new Exception("bad state"); | 1539 | throw new Exception("bad state"); |
1540 | 1540 | ||
1541 | lock(m_StartQueue) | 1541 | lock (m_StartQueue) |
1542 | m_StartQueue.InsertTail(inst); | 1542 | m_StartQueue.InsertTail(inst); |
1543 | 1543 | ||
1544 | WakeUpOne(); | 1544 | WakeUpOne(); |
1545 | } | 1545 | } |
1546 | 1546 | ||
1547 | public void QueueToYield(XMRInstance inst) | ||
1548 | { | ||
1549 | if (inst.m_IState != XMRInstState.ONYIELDQ) | ||
1550 | throw new Exception("bad state"); | ||
1551 | |||
1552 | lock (m_YieldQueue) | ||
1553 | m_YieldQueue.InsertTail(inst); | ||
1554 | |||
1555 | WakeUpOne(); | ||
1556 | } | ||
1557 | |||
1558 | public void RemoveFromSleep(XMRInstance inst) | ||
1559 | { | ||
1560 | lock (m_SleepQueue) | ||
1561 | { | ||
1562 | if (inst.m_IState != XMRInstState.ONSLEEPQ) | ||
1563 | return; | ||
1564 | |||
1565 | m_SleepQueue.Remove(inst); | ||
1566 | inst.m_IState = XMRInstState.REMDFROMSLPQ; | ||
1567 | } | ||
1568 | } | ||
1569 | |||
1547 | /** | 1570 | /** |
1548 | * @brief A script may be sleeping, in which case we wake it. | 1571 | * @brief A script may be sleeping, in which case we wake it. |
1549 | */ | 1572 | */ |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs index 33eb8bf..8b67349 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs | |||
@@ -58,11 +58,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
58 | if(inst == null) | 58 | if(inst == null) |
59 | throw new ArgumentNullException("inst"); | 59 | throw new ArgumentNullException("inst"); |
60 | instance = inst; | 60 | instance = inst; |
61 | } | 61 | usage = 0; |
62 | |||
63 | ~HeapTrackerBase() | ||
64 | { | ||
65 | usage = instance.UpdateHeapUse(usage, 0); | ||
66 | } | 62 | } |
67 | } | 63 | } |
68 | 64 | ||
@@ -73,24 +69,33 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
73 | { | 69 | { |
74 | private static FieldInfo listValueField = typeof(HeapTrackerList).GetField("value"); | 70 | private static FieldInfo listValueField = typeof(HeapTrackerList).GetField("value"); |
75 | private static MethodInfo listSaveMethod = typeof(HeapTrackerList).GetMethod("Save"); | 71 | private static MethodInfo listSaveMethod = typeof(HeapTrackerList).GetMethod("Save"); |
72 | private static MethodInfo listRestoreMethod = typeof(HeapTrackerList).GetMethod("Restore"); | ||
73 | private static MethodInfo listFreeMethod = typeof(HeapTrackerList).GetMethod("Free"); | ||
76 | 74 | ||
77 | public LSL_List value; | 75 | public LSL_List value; |
78 | 76 | ||
79 | public HeapTrackerList(XMRInstAbstract inst) : base(inst) { } | 77 | public HeapTrackerList(XMRInstAbstract inst) : base(inst) {} |
80 | 78 | ||
81 | // generate CIL code to pop the value from the CIL stack | 79 | // generate CIL code to pop the value ie store in value |
82 | // input: | 80 | // input: |
83 | // 'this' pointer already pushed on CIL stack | 81 | // 'this' pointer already pushed on CIL stack |
84 | // new value pushed on CIL stack | 82 | // new value |
85 | // output: | 83 | // output: |
86 | // 'this' pointer popped from stack | ||
87 | // new value popped from CIL stack | ||
88 | // heap usage updated | ||
89 | public static void GenPop(Token errorAt, ScriptMyILGen ilGen) | 84 | public static void GenPop(Token errorAt, ScriptMyILGen ilGen) |
90 | { | 85 | { |
91 | ilGen.Emit(errorAt, OpCodes.Call, listSaveMethod); | 86 | ilGen.Emit(errorAt, OpCodes.Call, listSaveMethod); |
92 | } | 87 | } |
93 | 88 | ||
89 | public static void GenRestore(Token errorAt, ScriptMyILGen ilGen) | ||
90 | { | ||
91 | ilGen.Emit(errorAt, OpCodes.Call, listRestoreMethod); | ||
92 | } | ||
93 | |||
94 | public static void GenFree(Token errorAt, ScriptMyILGen ilGen) | ||
95 | { | ||
96 | ilGen.Emit(errorAt, OpCodes.Call, listFreeMethod); | ||
97 | } | ||
98 | |||
94 | // generate CIL code to push the value on the CIL stack | 99 | // generate CIL code to push the value on the CIL stack |
95 | // input: | 100 | // input: |
96 | // 'this' pointer already pushed on CIL stack | 101 | // 'this' pointer already pushed on CIL stack |
@@ -106,23 +111,32 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
106 | 111 | ||
107 | public void Save(LSL_List lis) | 112 | public void Save(LSL_List lis) |
108 | { | 113 | { |
109 | int newuse = Size(lis); | 114 | if (lis == null) |
110 | usage = instance.UpdateHeapUse(usage, newuse); | 115 | usage = instance.UpdateHeapUse(usage, 0); |
116 | else | ||
117 | usage = instance.UpdateHeapUse(usage, Size(lis)); | ||
111 | value = lis; | 118 | value = lis; |
112 | } | 119 | } |
113 | 120 | ||
114 | //private static int counter = 5; | 121 | public void Restore(LSL_List lis) |
115 | public static int Size(LSL_List lis) | ||
116 | { | 122 | { |
117 | // VS2017 in debug mode seems to have a problem running this statement quickly: | 123 | value = lis; |
118 | //SLOW: return (!typeof(LSL_List).IsValueType && (lis == null)) ? 0 : lis.Size; | 124 | if (lis != null) |
119 | 125 | usage = Size(lis); | |
120 | //FAST: return 33; | 126 | else |
121 | //SLOW: return (lis == null) ? 0 : 99; | 127 | usage = 0; |
122 | //FAST: return ++ counter; | 128 | } |
123 | 129 | ||
124 | // VS2017 in debug mode seems content to run this quickly though: | 130 | public void Free() |
131 | { | ||
132 | usage = instance.UpdateHeapUse(usage, 0); | ||
133 | value = null; | ||
134 | instance = null; | ||
135 | } | ||
125 | 136 | ||
137 | //private static int counter = 5; | ||
138 | public static int Size(LSL_List lis) | ||
139 | { | ||
126 | try | 140 | try |
127 | { | 141 | { |
128 | return lis.Size; | 142 | return lis.Size; |
@@ -141,6 +155,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
141 | { | 155 | { |
142 | private static FieldInfo objectValueField = typeof(HeapTrackerObject).GetField("value"); | 156 | private static FieldInfo objectValueField = typeof(HeapTrackerObject).GetField("value"); |
143 | private static MethodInfo objectSaveMethod = typeof(HeapTrackerObject).GetMethod("Save"); | 157 | private static MethodInfo objectSaveMethod = typeof(HeapTrackerObject).GetMethod("Save"); |
158 | private static MethodInfo objectRestoreMethod = typeof(HeapTrackerObject).GetMethod("Restore"); | ||
159 | private static MethodInfo objectFreeMethod = typeof(HeapTrackerObject).GetMethod("Free"); | ||
144 | 160 | ||
145 | public const int HT_CHAR = 2; | 161 | public const int HT_CHAR = 2; |
146 | public const int HT_DELE = 8; | 162 | public const int HT_DELE = 8; |
@@ -168,6 +184,16 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
168 | ilGen.Emit(errorAt, OpCodes.Call, objectSaveMethod); | 184 | ilGen.Emit(errorAt, OpCodes.Call, objectSaveMethod); |
169 | } | 185 | } |
170 | 186 | ||
187 | public static void GenRestore(Token errorAt, ScriptMyILGen ilGen) | ||
188 | { | ||
189 | ilGen.Emit(errorAt, OpCodes.Call, objectRestoreMethod); | ||
190 | } | ||
191 | |||
192 | public static void GenFree(Token errorAt, ScriptMyILGen ilGen) | ||
193 | { | ||
194 | ilGen.Emit(errorAt, OpCodes.Call, objectFreeMethod); | ||
195 | } | ||
196 | |||
171 | // generate CIL code to push the value on the CIL stack | 197 | // generate CIL code to push the value on the CIL stack |
172 | // input: | 198 | // input: |
173 | // 'this' pointer already pushed on CIL stack | 199 | // 'this' pointer already pushed on CIL stack |
@@ -188,6 +214,19 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
188 | value = obj; | 214 | value = obj; |
189 | } | 215 | } |
190 | 216 | ||
217 | public void Restore(object obj) | ||
218 | { | ||
219 | value = obj; | ||
220 | usage = Size(obj); | ||
221 | } | ||
222 | |||
223 | public void Free() | ||
224 | { | ||
225 | usage = instance.UpdateHeapUse(usage, 0); | ||
226 | value = null; | ||
227 | instance = null; | ||
228 | } | ||
229 | |||
191 | // public so it can be used by XMRArray | 230 | // public so it can be used by XMRArray |
192 | public static int Size(object obj) | 231 | public static int Size(object obj) |
193 | { | 232 | { |
@@ -204,8 +243,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
204 | return HT_SING; | 243 | return HT_SING; |
205 | if(obj is int) | 244 | if(obj is int) |
206 | return HT_INT; | 245 | return HT_INT; |
207 | if(obj is LSL_Float) | 246 | if(obj is LSL_Float) // lsl floats are stupid doubles |
208 | return HT_SFLT; | 247 | return HT_DOUB; |
209 | if(obj is LSL_Integer) | 248 | if(obj is LSL_Integer) |
210 | return HT_INT; | 249 | return HT_INT; |
211 | if(obj is LSL_List) | 250 | if(obj is LSL_List) |
@@ -252,7 +291,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
252 | public class HeapTrackerString: HeapTrackerBase | 291 | public class HeapTrackerString: HeapTrackerBase |
253 | { | 292 | { |
254 | private static FieldInfo stringValueField = typeof(HeapTrackerString).GetField("value"); | 293 | private static FieldInfo stringValueField = typeof(HeapTrackerString).GetField("value"); |
294 | private static MethodInfo stringRestoreMethod = typeof(HeapTrackerString).GetMethod("Restore"); | ||
255 | private static MethodInfo stringSaveMethod = typeof(HeapTrackerString).GetMethod("Save"); | 295 | private static MethodInfo stringSaveMethod = typeof(HeapTrackerString).GetMethod("Save"); |
296 | private static MethodInfo stringFreeMethod = typeof(HeapTrackerString).GetMethod("Free"); | ||
256 | 297 | ||
257 | public string value; | 298 | public string value; |
258 | 299 | ||
@@ -271,6 +312,16 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
271 | ilGen.Emit(errorAt, OpCodes.Call, stringSaveMethod); | 312 | ilGen.Emit(errorAt, OpCodes.Call, stringSaveMethod); |
272 | } | 313 | } |
273 | 314 | ||
315 | public static void GenRestore(Token errorAt, ScriptMyILGen ilGen) | ||
316 | { | ||
317 | ilGen.Emit(errorAt, OpCodes.Call, stringRestoreMethod); | ||
318 | } | ||
319 | |||
320 | public static void GenFree(Token errorAt, ScriptMyILGen ilGen) | ||
321 | { | ||
322 | ilGen.Emit(errorAt, OpCodes.Call, stringFreeMethod); | ||
323 | } | ||
324 | |||
274 | // generate CIL code to push the value on the CIL stack | 325 | // generate CIL code to push the value on the CIL stack |
275 | // input: | 326 | // input: |
276 | // 'this' pointer already pushed on CIL stack | 327 | // 'this' pointer already pushed on CIL stack |
@@ -291,6 +342,19 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
291 | value = str; | 342 | value = str; |
292 | } | 343 | } |
293 | 344 | ||
345 | public void Restore(string str) | ||
346 | { | ||
347 | value = str; | ||
348 | usage = Size(str); | ||
349 | } | ||
350 | |||
351 | public void Free() | ||
352 | { | ||
353 | usage = instance.UpdateHeapUse(usage, 0); | ||
354 | value = null; | ||
355 | instance = null; | ||
356 | } | ||
357 | |||
294 | public static int Size(string str) | 358 | public static int Size(string str) |
295 | { | 359 | { |
296 | return (str == null) ? 0 : str.Length * HeapTrackerObject.HT_CHAR; | 360 | return (str == null) ? 0 : str.Length * HeapTrackerObject.HT_CHAR; |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs index a440cf3..dec775f 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs | |||
@@ -60,7 +60,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
60 | public Delegate[][] iarSDTIntfObjs; | 60 | public Delegate[][] iarSDTIntfObjs; |
61 | 61 | ||
62 | private XMRInstAbstract instance; | 62 | private XMRInstAbstract instance; |
63 | private int heapUse; | 63 | private int arraysHeapUse; |
64 | 64 | ||
65 | private static readonly XMR_Array[] noArrays = new XMR_Array[0]; | 65 | private static readonly XMR_Array[] noArrays = new XMR_Array[0]; |
66 | private static readonly char[] noChars = new char[0]; | 66 | private static readonly char[] noChars = new char[0]; |
@@ -81,20 +81,49 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
81 | 81 | ||
82 | ~XMRInstArrays() | 82 | ~XMRInstArrays() |
83 | { | 83 | { |
84 | heapUse = instance.UpdateHeapUse(heapUse, 0); | 84 | arraysHeapUse = instance.UpdateHeapUse(arraysHeapUse, 0); |
85 | } | 85 | } |
86 | 86 | ||
87 | public void AllocVarArrays(XMRInstArSizes ars) | 87 | public void Clear() |
88 | { | ||
89 | int newheapUse = 0; | ||
90 | if(iarArrays != null) | ||
91 | { | ||
92 | foreach(XMR_Array xa in iarArrays) | ||
93 | xa.__pub_clear(); | ||
94 | } | ||
95 | if(iarChars != null) | ||
96 | iarChars = new char[iarChars.Length]; | ||
97 | if (iarLists != null) | ||
98 | iarLists = new LSL_List[iarLists.Length]; | ||
99 | if (iarObjects != null) | ||
100 | iarObjects = new object[iarObjects.Length]; | ||
101 | if(iarStrings != null) | ||
102 | iarStrings = new string[iarStrings.Length]; | ||
103 | if (iarFloats != null) | ||
104 | newheapUse += iarFloats.Length * HeapTrackerObject.HT_DOUB; | ||
105 | if (iarIntegers != null) | ||
106 | newheapUse += iarIntegers.Length * HeapTrackerObject.HT_INT; | ||
107 | if (iarRotations != null) | ||
108 | newheapUse += iarRotations.Length * HeapTrackerObject.HT_ROT; | ||
109 | if (iarVectors != null) | ||
110 | newheapUse += iarVectors.Length * HeapTrackerObject.HT_VEC; | ||
111 | |||
112 | arraysHeapUse = instance.UpdateHeapUse(0, newheapUse); | ||
113 | } | ||
114 | |||
115 | public void AllocVarArrays(XMRInstArSizes ars) | ||
88 | { | 116 | { |
89 | ClearOldArrays(); | 117 | ClearOldArrays(); |
118 | int newuse = arraysHeapUse + | ||
119 | ars.iasChars* HeapTrackerObject.HT_CHAR + | ||
120 | ars.iasFloats * HeapTrackerObject.HT_SFLT + | ||
121 | ars.iasIntegers * HeapTrackerObject.HT_INT + | ||
122 | ars.iasRotations * HeapTrackerObject.HT_ROT + | ||
123 | ars.iasVectors * HeapTrackerObject.HT_VEC + | ||
124 | ars.iasSDTIntfObjs * HeapTrackerObject.HT_DELE; | ||
90 | 125 | ||
91 | heapUse = instance.UpdateHeapUse(heapUse, | 126 | arraysHeapUse = instance.UpdateHeapUse(arraysHeapUse, newuse); |
92 | ars.iasChars * HeapTrackerObject.HT_CHAR + | ||
93 | ars.iasFloats * HeapTrackerObject.HT_SFLT + | ||
94 | ars.iasIntegers * HeapTrackerObject.HT_INT + | ||
95 | ars.iasRotations * HeapTrackerObject.HT_ROT + | ||
96 | ars.iasVectors * HeapTrackerObject.HT_VEC + | ||
97 | ars.iasSDTIntfObjs * HeapTrackerObject.HT_DELE); | ||
98 | 127 | ||
99 | iarArrays = (ars.iasArrays > 0) ? new XMR_Array[ars.iasArrays] : noArrays; | 128 | iarArrays = (ars.iasArrays > 0) ? new XMR_Array[ars.iasArrays] : noArrays; |
100 | iarChars = (ars.iasChars > 0) ? new char[ars.iasChars] : noChars; | 129 | iarChars = (ars.iasChars > 0) ? new char[ars.iasChars] : noChars; |
@@ -114,9 +143,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
114 | */ | 143 | */ |
115 | public void PopList(int index, LSL_List lis) | 144 | public void PopList(int index, LSL_List lis) |
116 | { | 145 | { |
117 | LSL_List old = iarLists[index]; | 146 | int delta = HeapTrackerObject.Size(lis) - HeapTrackerObject.Size(iarLists[index]); |
118 | int newheapuse = heapUse + HeapTrackerList.Size(lis) - HeapTrackerList.Size(old); | 147 | instance.UpdateHeapUse(0, delta); |
119 | heapUse = instance.UpdateHeapUse(heapUse, newheapuse); | 148 | Interlocked.Add(ref arraysHeapUse, delta); |
120 | iarLists[index] = lis; | 149 | iarLists[index] = lis; |
121 | } | 150 | } |
122 | 151 | ||
@@ -125,9 +154,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
125 | */ | 154 | */ |
126 | public void PopObject(int index, object obj) | 155 | public void PopObject(int index, object obj) |
127 | { | 156 | { |
128 | object old = iarObjects[index]; | 157 | int delta = HeapTrackerObject.Size(obj) - HeapTrackerObject.Size(iarObjects[index]); |
129 | int newheapuse = heapUse + HeapTrackerObject.Size(obj) - HeapTrackerObject.Size(old); | 158 | instance.UpdateHeapUse(0, delta); |
130 | heapUse = instance.UpdateHeapUse(heapUse, newheapuse); | 159 | Interlocked.Add(ref arraysHeapUse, delta); |
131 | iarObjects[index] = obj; | 160 | iarObjects[index] = obj; |
132 | } | 161 | } |
133 | 162 | ||
@@ -136,9 +165,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
136 | */ | 165 | */ |
137 | public void PopString(int index, string str) | 166 | public void PopString(int index, string str) |
138 | { | 167 | { |
139 | string old = iarStrings[index]; | 168 | int delta = HeapTrackerString.Size(str) - HeapTrackerString.Size(iarStrings[index]); |
140 | int newheapuse = heapUse + HeapTrackerString.Size(str) - HeapTrackerString.Size(old); | 169 | instance.UpdateHeapUse(0, delta); |
141 | heapUse = instance.UpdateHeapUse(heapUse, newheapuse); | 170 | Interlocked.Add(ref arraysHeapUse, delta); |
142 | iarStrings[index] = str; | 171 | iarStrings[index] = str; |
143 | } | 172 | } |
144 | 173 | ||
@@ -181,11 +210,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
181 | iarSDTClObjs = (XMRSDTypeClObj[])recver(); | 210 | iarSDTClObjs = (XMRSDTypeClObj[])recver(); |
182 | Delegate[][] dels = (Delegate[][])recver(); | 211 | Delegate[][] dels = (Delegate[][])recver(); |
183 | 212 | ||
184 | int newheapuse = heapUse; | 213 | int newheapuse = arraysHeapUse; |
185 | 214 | ||
186 | // value types simply are the size of the value * number of values | 215 | // value types simply are the size of the value * number of values |
187 | newheapuse += chrs.Length * HeapTrackerObject.HT_CHAR; | 216 | newheapuse += chrs.Length * HeapTrackerObject.HT_CHAR; |
188 | newheapuse += flts.Length * HeapTrackerObject.HT_SFLT; | 217 | newheapuse += flts.Length * HeapTrackerObject.HT_DOUB; |
189 | newheapuse += ints.Length * HeapTrackerObject.HT_INT; | 218 | newheapuse += ints.Length * HeapTrackerObject.HT_INT; |
190 | newheapuse += rots.Length * HeapTrackerObject.HT_ROT; | 219 | newheapuse += rots.Length * HeapTrackerObject.HT_ROT; |
191 | newheapuse += vecs.Length * HeapTrackerObject.HT_VEC; | 220 | newheapuse += vecs.Length * HeapTrackerObject.HT_VEC; |
@@ -204,7 +233,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
204 | // others (XMR_Array, XMRSDTypeClObj) keep track of their own heap usage | 233 | // others (XMR_Array, XMRSDTypeClObj) keep track of their own heap usage |
205 | 234 | ||
206 | // update script heap usage, throwing an exception before finalizing changes | 235 | // update script heap usage, throwing an exception before finalizing changes |
207 | heapUse = instance.UpdateHeapUse(heapUse, newheapuse); | 236 | arraysHeapUse = instance.UpdateHeapUse(arraysHeapUse, newheapuse); |
208 | 237 | ||
209 | iarChars = chrs; | 238 | iarChars = chrs; |
210 | iarFloats = flts; | 239 | iarFloats = flts; |
@@ -219,7 +248,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
219 | 248 | ||
220 | private void ClearOldArrays() | 249 | private void ClearOldArrays() |
221 | { | 250 | { |
222 | int newheapuse = heapUse; | 251 | int newheapuse = arraysHeapUse; |
223 | 252 | ||
224 | iarArrays = null; | 253 | iarArrays = null; |
225 | if(iarChars != null) | 254 | if(iarChars != null) |
@@ -272,7 +301,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
272 | iarSDTIntfObjs = null; | 301 | iarSDTIntfObjs = null; |
273 | } | 302 | } |
274 | 303 | ||
275 | heapUse = instance.UpdateHeapUse(heapUse, newheapuse); | 304 | arraysHeapUse = instance.UpdateHeapUse(arraysHeapUse, newheapuse); |
276 | } | 305 | } |
277 | } | 306 | } |
278 | 307 | ||
@@ -424,31 +453,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
424 | \**************************************************/ | 453 | \**************************************************/ |
425 | 454 | ||
426 | protected int heapLimit; | 455 | protected int heapLimit; |
427 | private int heapUsed; | 456 | protected int heapUsed; |
428 | 457 | ||
429 | public virtual int UpdateHeapUse(int olduse, int newuse) | 458 | public virtual int UpdateHeapUse(int olduse, int newuse) |
430 | { | 459 | { |
431 | if(newuse <= olduse) | 460 | int newtotal = Interlocked.Add(ref heapUsed, newuse - olduse); |
432 | Interlocked.Add(ref heapUsed, newuse - olduse); | 461 | if(newtotal > heapLimit) |
433 | else | 462 | throw new OutOfHeapException(newtotal + olduse - newuse, newtotal, heapLimit); |
434 | { | ||
435 | int newtotal, oldtotal; | ||
436 | do | ||
437 | { | ||
438 | oldtotal = Interlocked.Add(ref heapUsed, 0); | ||
439 | newtotal = oldtotal + newuse - olduse; | ||
440 | if(newtotal > heapLimit) | ||
441 | { | ||
442 | // System.GC.Collect (); | ||
443 | // System.GC.WaitForPendingFinalizers (); | ||
444 | oldtotal = Interlocked.Add(ref heapUsed, 0); | ||
445 | newtotal = oldtotal + newuse - olduse; | ||
446 | if(newtotal > heapLimit) | ||
447 | throw new OutOfHeapException(oldtotal, newtotal, heapLimit); | ||
448 | } | ||
449 | } while(Interlocked.CompareExchange(ref heapUsed, newtotal, oldtotal) != oldtotal); | ||
450 | } | ||
451 | |||
452 | return newuse; | 463 | return newuse; |
453 | } | 464 | } |
454 | 465 | ||
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs index 7fc97e9..7ef1b9f 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs | |||
@@ -218,7 +218,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
218 | // do not do llResetScript on entry | 218 | // do not do llResetScript on entry |
219 | if(eventCode == ScriptEventCode.state_entry && stateCode == 0) | 219 | if(eventCode == ScriptEventCode.state_entry && stateCode == 0) |
220 | return; | 220 | return; |
221 | ClearQueueExceptLinkMessages(); | 221 | // do clear the events queue on reset |
222 | ClearQueue(); | ||
223 | //ClearQueueExceptLinkMessages(); | ||
222 | throw new ScriptResetException(); | 224 | throw new ScriptResetException(); |
223 | } | 225 | } |
224 | 226 | ||
@@ -583,6 +585,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
583 | * Tell outer layers to cancel any event triggers, like llListen(), | 585 | * Tell outer layers to cancel any event triggers, like llListen(), |
584 | * then tell outer layers which events the new state has handlers for. | 586 | * then tell outer layers which events the new state has handlers for. |
585 | * We also clear the event queue as per http://wiki.secondlife.com/wiki/State | 587 | * We also clear the event queue as per http://wiki.secondlife.com/wiki/State |
588 | * old scripts may want linked messages, but that is not as SL does now | ||
586 | */ | 589 | */ |
587 | public override void StateChange() | 590 | public override void StateChange() |
588 | { | 591 | { |
@@ -595,7 +598,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
595 | // Tell whoever cares which event handlers the new state has. | 598 | // Tell whoever cares which event handlers the new state has. |
596 | m_Part.SetScriptEvents(m_ItemID, GetStateEventFlags(stateCode)); | 599 | m_Part.SetScriptEvents(m_ItemID, GetStateEventFlags(stateCode)); |
597 | 600 | ||
598 | // Clear out any old events from the queue. | 601 | // keep link messages |
602 | //ClearQueueExceptLinkMessages(); | ||
603 | // or Clear out all old events from the queue. | ||
599 | lock(m_QueueLock) | 604 | lock(m_QueueLock) |
600 | { | 605 | { |
601 | m_EventQueue.Clear(); | 606 | m_EventQueue.Clear(); |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs index 12feb7b..e97c71e 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs | |||
@@ -236,6 +236,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
236 | return GetScriptFileName(m_ScriptBasePath, filename); | 236 | return GetScriptFileName(m_ScriptBasePath, filename); |
237 | } | 237 | } |
238 | 238 | ||
239 | public string GetScriptILFileName(string filename) | ||
240 | { | ||
241 | string path = Path.Combine(m_ScriptBasePath, "DebugIL"); | ||
242 | Directory.CreateDirectory(path); | ||
243 | return Path.Combine(path, filename); | ||
244 | } | ||
245 | |||
239 | public static string GetScriptFileName(string scriptBasePath, string filename) | 246 | public static string GetScriptFileName(string scriptBasePath, string filename) |
240 | { | 247 | { |
241 | // Get old path, ie, all files lumped in a single huge directory. | 248 | // Get old path, ie, all files lumped in a single huge directory. |
@@ -363,8 +370,33 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
363 | lock(m_QueueLock) | 370 | lock(m_QueueLock) |
364 | { | 371 | { |
365 | m_Running = value; | 372 | m_Running = value; |
366 | if(!value) | 373 | if(value) |
374 | { | ||
375 | if (m_IState == XMRInstState.SUSPENDED && m_SuspendCount == 0) | ||
376 | { | ||
377 | if(eventCode != ScriptEventCode.None) | ||
378 | { | ||
379 | m_IState = XMRInstState.ONYIELDQ; | ||
380 | m_Engine.QueueToYield(this); | ||
381 | } | ||
382 | else if ((m_EventQueue != null) && (m_EventQueue.First != null)) | ||
383 | { | ||
384 | m_IState = XMRInstState.ONSTARTQ; | ||
385 | m_Engine.QueueToStart(this); | ||
386 | } | ||
387 | else | ||
388 | m_IState = XMRInstState.IDLE; | ||
389 | } | ||
390 | else if(m_SuspendCount != 0) | ||
391 | m_IState = XMRInstState.IDLE; | ||
392 | } | ||
393 | else | ||
367 | { | 394 | { |
395 | if(m_IState == XMRInstState.ONSLEEPQ) | ||
396 | { | ||
397 | m_Engine.RemoveFromSleep(this); | ||
398 | m_IState = XMRInstState.SUSPENDED; | ||
399 | } | ||
368 | EmptyEventQueues(); | 400 | EmptyEventQueues(); |
369 | } | 401 | } |
370 | } | 402 | } |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs index 1b735e3..987e22c 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs | |||
@@ -80,10 +80,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
80 | !m_HaveEventHandlers[(int)evc]) // don't bother if we don't have such a handler in any state | 80 | !m_HaveEventHandlers[(int)evc]) // don't bother if we don't have such a handler in any state |
81 | return; | 81 | return; |
82 | 82 | ||
83 | // Not running means we ignore any incoming events. | 83 | // Not running means we ignore any incoming events. |
84 | // But queue if still constructing because m_Running is not yet valid. | 84 | // But queue if still constructing because m_Running is not yet valid. |
85 | |||
85 | if(!m_Running && !construct) | 86 | if(!m_Running && !construct) |
87 | { | ||
88 | if(m_IState == XMRInstState.SUSPENDED) | ||
89 | { | ||
90 | if(evc == ScriptEventCode.state_entry && m_EventQueue.Count == 0) | ||
91 | { | ||
92 | LinkedListNode<EventParams> llns = new LinkedListNode<EventParams>(evt); | ||
93 | m_EventQueue.AddFirst(llns); | ||
94 | } | ||
95 | } | ||
86 | return; | 96 | return; |
97 | } | ||
87 | 98 | ||
88 | if(m_minEventDelay != 0) | 99 | if(m_minEventDelay != 0) |
89 | { | 100 | { |
@@ -250,13 +261,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
250 | return XMRInstState.SUSPENDED; | 261 | return XMRInstState.SUSPENDED; |
251 | } | 262 | } |
252 | 263 | ||
253 | // Make sure we aren't being migrated in or out and prevent that | 264 | // Make sure we aren't being migrated in or out and prevent that |
254 | // whilst we are in here. If migration has it locked, don't call | 265 | // whilst we are in here. If migration has it locked, don't call |
255 | // back right away, delay a bit so we don't get in infinite loop. | 266 | // back right away, delay a bit so we don't get in infinite loop. |
256 | m_RunOnePhase = "lock m_RunLock"; | 267 | m_RunOnePhase = "lock m_RunLock"; |
257 | if(!Monitor.TryEnter(m_RunLock)) | 268 | if(!Monitor.TryEnter(m_RunLock)) |
258 | { | 269 | { |
259 | m_SleepUntil = now.AddMilliseconds(3); | 270 | m_SleepUntil = now.AddMilliseconds(15); |
260 | m_RunOnePhase = "return was locked"; | 271 | m_RunOnePhase = "return was locked"; |
261 | return XMRInstState.ONSLEEPQ; | 272 | return XMRInstState.ONSLEEPQ; |
262 | } | 273 | } |
@@ -273,6 +284,12 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
273 | return XMRInstState.DISPOSED; | 284 | return XMRInstState.DISPOSED; |
274 | } | 285 | } |
275 | 286 | ||
287 | if(!m_Running) | ||
288 | { | ||
289 | m_RunOnePhase = "return is not running"; | ||
290 | return XMRInstState.SUSPENDED; | ||
291 | } | ||
292 | |||
276 | // Do some more of the last event if it didn't finish. | 293 | // Do some more of the last event if it didn't finish. |
277 | if(this.eventCode != ScriptEventCode.None) | 294 | if(this.eventCode != ScriptEventCode.None) |
278 | { | 295 | { |
@@ -325,10 +342,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
325 | if(m_EventQueue.First != null) | 342 | if(m_EventQueue.First != null) |
326 | { | 343 | { |
327 | evt = m_EventQueue.First.Value; | 344 | evt = m_EventQueue.First.Value; |
328 | if(m_DetachQuantum > 0) | 345 | evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), evt.EventName); |
346 | if (m_DetachQuantum > 0) | ||
329 | { | 347 | { |
330 | evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), | ||
331 | evt.EventName); | ||
332 | if(evc != ScriptEventCode.attach) | 348 | if(evc != ScriptEventCode.attach) |
333 | { | 349 | { |
334 | // This is the case where the attach event | 350 | // This is the case where the attach event |
@@ -343,8 +359,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
343 | } | 359 | } |
344 | } | 360 | } |
345 | m_EventQueue.RemoveFirst(); | 361 | m_EventQueue.RemoveFirst(); |
346 | evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), | ||
347 | evt.EventName); | ||
348 | if((int)evc >= 0) | 362 | if((int)evc >= 0) |
349 | m_EventCounts[(int)evc]--; | 363 | m_EventCounts[(int)evc]--; |
350 | } | 364 | } |
@@ -730,11 +744,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
730 | case XMRInstState.DISPOSED: | 744 | case XMRInstState.DISPOSED: |
731 | return; | 745 | return; |
732 | 746 | ||
733 | // Some other thread is already resetting it, let it finish. | 747 | // Some other thread is already resetting it, let it finish. |
734 | 748 | ||
735 | case XMRInstState.RESETTING: | 749 | case XMRInstState.RESETTING: |
736 | return; | 750 | return; |
737 | 751 | ||
752 | case XMRInstState.SUSPENDED: | ||
753 | break; | ||
754 | |||
738 | default: | 755 | default: |
739 | throw new Exception("bad state"); | 756 | throw new Exception("bad state"); |
740 | } | 757 | } |
@@ -744,17 +761,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
744 | { | 761 | { |
745 | CheckRunLockInvariants(true); | 762 | CheckRunLockInvariants(true); |
746 | 763 | ||
747 | // No other thread should have transitioned it from RESETTING. | 764 | // No other thread should have transitioned it from RESETTING. |
748 | if(m_IState != XMRInstState.RESETTING) | 765 | if (m_IState != XMRInstState.SUSPENDED) |
749 | throw new Exception("bad state"); | 766 | { |
767 | if (m_IState != XMRInstState.RESETTING) | ||
768 | throw new Exception("bad state"); | ||
750 | 769 | ||
751 | // Mark it idle now so it can get queued to process new stuff. | 770 | m_IState = XMRInstState.IDLE; |
752 | m_IState = XMRInstState.IDLE; | 771 | } |
753 | 772 | ||
754 | // Reset everything and queue up default's start_entry() event. | 773 | // Reset everything and queue up default's start_entry() event. |
755 | ClearQueue(); | 774 | ClearQueue(); |
756 | ResetLocked("external Reset"); | 775 | ResetLocked("external Reset"); |
757 | 776 | ||
777 | // Mark it idle now so it can get queued to process new stuff. | ||
778 | |||
758 | CheckRunLockInvariants(true); | 779 | CheckRunLockInvariants(true); |
759 | } | 780 | } |
760 | } | 781 | } |
@@ -820,6 +841,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
820 | m_SleepUntil = DateTime.MinValue; // not doing llSleep() | 841 | m_SleepUntil = DateTime.MinValue; // not doing llSleep() |
821 | m_ResetCount++; // has been reset once more | 842 | m_ResetCount++; // has been reset once more |
822 | 843 | ||
844 | heapUsed = 0; | ||
845 | glblVars.Clear(); | ||
846 | |||
823 | // Tell next call to 'default state_entry()' to reset all global | 847 | // Tell next call to 'default state_entry()' to reset all global |
824 | // vars to their initial values. | 848 | // vars to their initial values. |
825 | doGblInit = true; | 849 | doGblInit = true; |
@@ -827,7 +851,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
827 | // Throw away all its stack frames. | 851 | // Throw away all its stack frames. |
828 | // If the script is resetting itself, there shouldn't be any stack frames. | 852 | // If the script is resetting itself, there shouldn't be any stack frames. |
829 | // If the script is being reset by something else, we throw them away cuz we want to start from the beginning of an event handler. | 853 | // If the script is being reset by something else, we throw them away cuz we want to start from the beginning of an event handler. |
830 | stackFrames = null; | 854 | stackFrames = null; |
831 | 855 | ||
832 | // Set script to 'default' state and queue call to its | 856 | // Set script to 'default' state and queue call to its |
833 | // 'state_entry()' event handler. | 857 | // 'state_entry()' event handler. |
@@ -937,7 +961,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
937 | lock(m_QueueLock) | 961 | lock(m_QueueLock) |
938 | { | 962 | { |
939 | m_Suspended = false; | 963 | m_Suspended = false; |
940 | if((m_EventQueue != null) && | 964 | m_DetachQuantum = 0; |
965 | m_DetachReady.Set(); | ||
966 | if ((m_EventQueue != null) && | ||
941 | (m_EventQueue.First != null) && | 967 | (m_EventQueue.First != null) && |
942 | (m_IState == XMRInstState.IDLE)) | 968 | (m_IState == XMRInstState.IDLE)) |
943 | { | 969 | { |
diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs index 08c7e80..f68fd51 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs | |||
@@ -166,7 +166,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
166 | 166 | ||
167 | if(inst == null) | 167 | if(inst == null) |
168 | break; | 168 | break; |
169 | if(inst.m_IState != XMRInstState.ONSTARTQ) | 169 | if (inst.m_IState == XMRInstState.SUSPENDED) |
170 | continue; | ||
171 | if (inst.m_IState != XMRInstState.ONSTARTQ) | ||
170 | throw new Exception("bad state"); | 172 | throw new Exception("bad state"); |
171 | RunInstance(inst, tid); | 173 | RunInstance(inst, tid); |
172 | if(m_SuspendScriptThreadFlag || m_Exiting) | 174 | if(m_SuspendScriptThreadFlag || m_Exiting) |
@@ -187,7 +189,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine | |||
187 | 189 | ||
188 | if(inst != null) | 190 | if(inst != null) |
189 | { | 191 | { |
190 | if(inst.m_IState != XMRInstState.ONYIELDQ) | 192 | if (inst.m_IState == XMRInstState.SUSPENDED) |
193 | continue; | ||
194 | if (inst.m_IState != XMRInstState.ONYIELDQ) | ||
191 | throw new Exception("bad state"); | 195 | throw new Exception("bad state"); |
192 | RunInstance(inst, tid); | 196 | RunInstance(inst, tid); |
193 | continue; | 197 | continue; |