aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorMelanie2019-07-27 12:10:28 +0100
committerMelanie2019-07-27 12:10:28 +0100
commitd6723dab37d86af22c712e2705af34fd2c82b174 (patch)
tree041be46cdcc778660fe3083794dabd2a2805283f /OpenSim/Region
parentWhen using FSAssets, the HGAssetService would still use AssetService. (diff)
parentmantis 8563: do not modify collection inside a loop on it a foreach on it (diff)
downloadopensim-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')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/AgentPreferencesModule.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs45
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs88
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs3188
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs105
-rwxr-xr-xOpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs329
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPZeroEncoder.cs82
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs32
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs8
-rw-r--r--OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs122
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/Tests/ChatModuleTests.cs16
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs514
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs92
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs233
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs41
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs13
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs19
-rwxr-xr-xOpenSim/Region/Framework/Scenes/Scene.cs67
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs80
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs68
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs849
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SimStatsReporter.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs19
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs21
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs17
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs16
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs7
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs17
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs203
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs91
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs7
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs16
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs20
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs50
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptCollector.cs12
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompValu.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptCompile.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRArray.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs27
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRHeapTracker.cs112
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstAbstract.cs103
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstBackend.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs34
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs66
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs8
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;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Framework.Capabilities; 41using OpenSim.Framework.Capabilities;
42 42
43using ComponentAce.Compression.Libs.zlib; 43using System.IO.Compression;
44 44
45using OSDArray = OpenMetaverse.StructuredData.OSDArray; 45using OSDArray = OpenMetaverse.StructuredData.OSDArray;
46using OSDMap = OpenMetaverse.StructuredData.OSDMap; 46using 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
28using System; 28using System;
29using System.Text;
29using OpenSim.Framework; 30using OpenSim.Framework;
30using Nini.Config; 31using Nini.Config;
31using OpenMetaverse; 32using 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;