diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
4 files changed, 398 insertions, 54 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs index dd6928f..8fe3565 100644 --- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs | |||
@@ -113,26 +113,26 @@ namespace OpenSim.Region.Framework.Scenes.Hypergrid | |||
113 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, | 113 | UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, |
114 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) | 114 | bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) |
115 | { | 115 | { |
116 | //m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID); | 116 | m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID); |
117 | 117 | ||
118 | if (fromTaskID.Equals(UUID.Zero)) | 118 | //if (fromTaskID.Equals(UUID.Zero)) |
119 | //{ | ||
120 | InventoryItemBase item = new InventoryItemBase(itemID); | ||
121 | item.Owner = remoteClient.AgentId; | ||
122 | item = InventoryService.GetItem(item); | ||
123 | //if (item == null) | ||
124 | //{ // Fetch the item | ||
125 | // item = new InventoryItemBase(); | ||
126 | // item.Owner = remoteClient.AgentId; | ||
127 | // item.ID = itemID; | ||
128 | // item = m_assMapper.Get(item, userInfo.RootFolder.ID, userInfo); | ||
129 | //} | ||
130 | if (item != null) | ||
119 | { | 131 | { |
120 | InventoryItemBase item = new InventoryItemBase(itemID); | 132 | m_assMapper.Get(item.AssetID, remoteClient.AgentId); |
121 | item.Owner = remoteClient.AgentId; | 133 | |
122 | item = InventoryService.GetItem(item); | ||
123 | //if (item == null) | ||
124 | //{ // Fetch the item | ||
125 | // item = new InventoryItemBase(); | ||
126 | // item.Owner = remoteClient.AgentId; | ||
127 | // item.ID = itemID; | ||
128 | // item = m_assMapper.Get(item, userInfo.RootFolder.ID, userInfo); | ||
129 | //} | ||
130 | if (item != null) | ||
131 | { | ||
132 | m_assMapper.Get(item.AssetID, remoteClient.AgentId); | ||
133 | |||
134 | } | ||
135 | } | 134 | } |
135 | //} | ||
136 | 136 | ||
137 | // OK, we're done fetching. Pass it up to the default RezObject | 137 | // OK, we're done fetching. Pass it up to the default RezObject |
138 | return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, | 138 | return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1d0da4c..3b91dd0 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -220,11 +220,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
220 | private bool m_scripts_enabled = true; | 220 | private bool m_scripts_enabled = true; |
221 | private string m_defaultScriptEngine; | 221 | private string m_defaultScriptEngine; |
222 | private int m_LastLogin = 0; | 222 | private int m_LastLogin = 0; |
223 | private Thread HeartbeatThread; | 223 | private Thread HeartbeatThread = null; |
224 | private volatile bool shuttingdown = false; | 224 | private volatile bool shuttingdown = false; |
225 | 225 | ||
226 | private int m_lastUpdate = Environment.TickCount; | 226 | private int m_lastUpdate = Environment.TickCount; |
227 | private int m_maxPrimsPerFrame = 200; | 227 | private int m_maxPrimsPerFrame = 200; |
228 | private bool m_firstHeartbeat = true; | ||
228 | 229 | ||
229 | private object m_deleting_scene_object = new object(); | 230 | private object m_deleting_scene_object = new object(); |
230 | 231 | ||
@@ -876,6 +877,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
876 | //m_heartbeatTimer.Enabled = true; | 877 | //m_heartbeatTimer.Enabled = true; |
877 | //m_heartbeatTimer.Interval = (int)(m_timespan * 1000); | 878 | //m_heartbeatTimer.Interval = (int)(m_timespan * 1000); |
878 | //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); | 879 | //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); |
880 | if (HeartbeatThread != null) | ||
881 | { | ||
882 | ThreadTracker.Remove(HeartbeatThread); | ||
883 | HeartbeatThread.Abort(); | ||
884 | HeartbeatThread = null; | ||
885 | } | ||
886 | m_lastUpdate = Environment.TickCount; | ||
879 | HeartbeatThread = new Thread(new ParameterizedThreadStart(Heartbeat)); | 887 | HeartbeatThread = new Thread(new ParameterizedThreadStart(Heartbeat)); |
880 | HeartbeatThread.SetApartmentState(ApartmentState.MTA); | 888 | HeartbeatThread.SetApartmentState(ApartmentState.MTA); |
881 | HeartbeatThread.Name = string.Format("Heartbeat for region {0}", RegionInfo.RegionName); | 889 | HeartbeatThread.Name = string.Format("Heartbeat for region {0}", RegionInfo.RegionName); |
@@ -912,9 +920,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
912 | /// <param name="e"></param> | 920 | /// <param name="e"></param> |
913 | private void Heartbeat(object sender) | 921 | private void Heartbeat(object sender) |
914 | { | 922 | { |
915 | Update(); | 923 | try |
924 | { | ||
925 | Update(); | ||
916 | 926 | ||
917 | m_lastUpdate = Environment.TickCount; | 927 | m_lastUpdate = Environment.TickCount; |
928 | m_firstHeartbeat = false; | ||
929 | } | ||
930 | catch (ThreadAbortException) | ||
931 | { | ||
932 | } | ||
918 | } | 933 | } |
919 | 934 | ||
920 | /// <summary> | 935 | /// <summary> |
@@ -2307,6 +2322,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2307 | /// <param name="client"></param> | 2322 | /// <param name="client"></param> |
2308 | public override void AddNewClient(IClientAPI client) | 2323 | public override void AddNewClient(IClientAPI client) |
2309 | { | 2324 | { |
2325 | CheckHeartbeat(); | ||
2310 | SubscribeToClientEvents(client); | 2326 | SubscribeToClientEvents(client); |
2311 | ScenePresence presence; | 2327 | ScenePresence presence; |
2312 | 2328 | ||
@@ -2365,14 +2381,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
2365 | EventManager.TriggerOnNewClient(client); | 2381 | EventManager.TriggerOnNewClient(client); |
2366 | } | 2382 | } |
2367 | 2383 | ||
2384 | |||
2385 | |||
2368 | /// <summary> | 2386 | /// <summary> |
2369 | /// Register for events from the client | 2387 | /// Register for events from the client |
2370 | /// </summary> | 2388 | /// </summary> |
2371 | /// <param name="client">The IClientAPI of the connected client</param> | 2389 | /// <param name="client">The IClientAPI of the connected client</param> |
2372 | protected virtual void SubscribeToClientEvents(IClientAPI client) | 2390 | public virtual void SubscribeToClientEvents(IClientAPI client) |
2391 | { | ||
2392 | SubscribeToClientTerrainEvents(client); | ||
2393 | SubscribeToClientPrimEvents(client); | ||
2394 | SubscribeToClientPrimRezEvents(client); | ||
2395 | SubscribeToClientInventoryEvents(client); | ||
2396 | SubscribeToClientAttachmentEvents(client); | ||
2397 | SubscribeToClientTeleportEvents(client); | ||
2398 | SubscribeToClientScriptEvents(client); | ||
2399 | SubscribeToClientParcelEvents(client); | ||
2400 | SubscribeToClientGridEvents(client); | ||
2401 | SubscribeToClientGodEvents(client); | ||
2402 | |||
2403 | SubscribeToClientNetworkEvents(client); | ||
2404 | |||
2405 | |||
2406 | // EventManager.TriggerOnNewClient(client); | ||
2407 | } | ||
2408 | |||
2409 | public virtual void SubscribeToClientTerrainEvents(IClientAPI client) | ||
2373 | { | 2410 | { |
2374 | client.OnRegionHandShakeReply += SendLayerData; | 2411 | client.OnRegionHandShakeReply += SendLayerData; |
2375 | client.OnAddPrim += AddNewPrim; | 2412 | client.OnUnackedTerrain += TerrainUnAcked; |
2413 | } | ||
2414 | |||
2415 | public virtual void SubscribeToClientPrimEvents(IClientAPI client) | ||
2416 | { | ||
2417 | |||
2376 | client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimPosition; | 2418 | client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimPosition; |
2377 | client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; | 2419 | client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; |
2378 | client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimRotation; | 2420 | client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimRotation; |
@@ -2384,8 +2426,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2384 | client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam; | 2426 | client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam; |
2385 | client.OnUpdatePrimShape += m_sceneGraph.UpdatePrimShape; | 2427 | client.OnUpdatePrimShape += m_sceneGraph.UpdatePrimShape; |
2386 | client.OnUpdatePrimTexture += m_sceneGraph.UpdatePrimTexture; | 2428 | client.OnUpdatePrimTexture += m_sceneGraph.UpdatePrimTexture; |
2387 | client.OnTeleportLocationRequest += RequestTeleportLocation; | ||
2388 | client.OnTeleportLandmarkRequest += RequestTeleportLandmark; | ||
2389 | client.OnObjectRequest += RequestPrim; | 2429 | client.OnObjectRequest += RequestPrim; |
2390 | client.OnObjectSelect += SelectPrim; | 2430 | client.OnObjectSelect += SelectPrim; |
2391 | client.OnObjectDeselect += DeselectPrim; | 2431 | client.OnObjectDeselect += DeselectPrim; |
@@ -2393,15 +2433,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2393 | client.OnSpinStart += m_sceneGraph.SpinStart; | 2433 | client.OnSpinStart += m_sceneGraph.SpinStart; |
2394 | client.OnSpinUpdate += m_sceneGraph.SpinObject; | 2434 | client.OnSpinUpdate += m_sceneGraph.SpinObject; |
2395 | client.OnDeRezObject += DeRezObject; | 2435 | client.OnDeRezObject += DeRezObject; |
2396 | client.OnRezObject += RezObject; | 2436 | |
2397 | client.OnRezSingleAttachmentFromInv += RezSingleAttachment; | ||
2398 | client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; | ||
2399 | client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv; | ||
2400 | client.OnObjectAttach += m_sceneGraph.AttachObject; | ||
2401 | client.OnObjectDetach += m_sceneGraph.DetachObject; | ||
2402 | client.OnObjectDrop += m_sceneGraph.DropObject; | ||
2403 | client.OnNameFromUUIDRequest += CommsManager.HandleUUIDNameRequest; | ||
2404 | client.OnObjectDescription += m_sceneGraph.PrimDescription; | ||
2405 | client.OnObjectName += m_sceneGraph.PrimName; | 2437 | client.OnObjectName += m_sceneGraph.PrimName; |
2406 | client.OnObjectClickAction += m_sceneGraph.PrimClickAction; | 2438 | client.OnObjectClickAction += m_sceneGraph.PrimClickAction; |
2407 | client.OnObjectMaterial += m_sceneGraph.PrimMaterial; | 2439 | client.OnObjectMaterial += m_sceneGraph.PrimMaterial; |
@@ -2412,7 +2444,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
2412 | client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags; | 2444 | client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags; |
2413 | client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; | 2445 | client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; |
2414 | client.OnObjectPermissions += HandleObjectPermissionsUpdate; | 2446 | client.OnObjectPermissions += HandleObjectPermissionsUpdate; |
2447 | client.OnGrabObject += ProcessObjectGrab; | ||
2448 | client.OnDeGrabObject += ProcessObjectDeGrab; | ||
2449 | client.OnUndo += m_sceneGraph.HandleUndo; | ||
2450 | client.OnObjectDescription += m_sceneGraph.PrimDescription; | ||
2451 | client.OnObjectDrop += m_sceneGraph.DropObject; | ||
2452 | client.OnObjectSaleInfo += ObjectSaleInfo; | ||
2453 | client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable; | ||
2454 | client.OnObjectOwner += ObjectOwner; | ||
2455 | } | ||
2456 | |||
2457 | public virtual void SubscribeToClientPrimRezEvents(IClientAPI client) | ||
2458 | { | ||
2459 | client.OnAddPrim += AddNewPrim; | ||
2460 | client.OnRezObject += RezObject; | ||
2461 | } | ||
2415 | 2462 | ||
2463 | public virtual void SubscribeToClientInventoryEvents(IClientAPI client) | ||
2464 | { | ||
2416 | client.OnCreateNewInventoryItem += CreateNewInventoryItem; | 2465 | client.OnCreateNewInventoryItem += CreateNewInventoryItem; |
2417 | client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; | 2466 | client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; |
2418 | client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; | 2467 | client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; |
@@ -2430,36 +2479,217 @@ namespace OpenSim.Region.Framework.Scenes | |||
2430 | client.OnRemoveTaskItem += RemoveTaskInventory; | 2479 | client.OnRemoveTaskItem += RemoveTaskInventory; |
2431 | client.OnUpdateTaskInventory += UpdateTaskInventory; | 2480 | client.OnUpdateTaskInventory += UpdateTaskInventory; |
2432 | client.OnMoveTaskItem += ClientMoveTaskInventoryItem; | 2481 | client.OnMoveTaskItem += ClientMoveTaskInventoryItem; |
2482 | } | ||
2433 | 2483 | ||
2434 | client.OnGrabObject += ProcessObjectGrab; | 2484 | public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) |
2435 | client.OnDeGrabObject += ProcessObjectDeGrab; | 2485 | { |
2436 | client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; | 2486 | client.OnRezSingleAttachmentFromInv += RezSingleAttachment; |
2437 | client.OnParcelBuy += ProcessParcelBuy; | 2487 | client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; |
2438 | client.OnAvatarPickerRequest += ProcessAvatarPickerRequest; | 2488 | client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv; |
2439 | client.OnObjectIncludeInSearch += m_sceneGraph.MakeObjectSearchable; | 2489 | client.OnObjectAttach += m_sceneGraph.AttachObject; |
2490 | client.OnObjectDetach += m_sceneGraph.DetachObject; | ||
2491 | } | ||
2492 | |||
2493 | public virtual void SubscribeToClientTeleportEvents(IClientAPI client) | ||
2494 | { | ||
2495 | client.OnTeleportLocationRequest += RequestTeleportLocation; | ||
2496 | client.OnTeleportLandmarkRequest += RequestTeleportLandmark; | ||
2440 | client.OnTeleportHomeRequest += TeleportClientHome; | 2497 | client.OnTeleportHomeRequest += TeleportClientHome; |
2441 | client.OnSetStartLocationRequest += SetHomeRezPoint; | 2498 | } |
2442 | client.OnUndo += m_sceneGraph.HandleUndo; | 2499 | |
2443 | client.OnObjectGroupRequest += m_sceneGraph.HandleObjectGroupUpdate; | 2500 | public virtual void SubscribeToClientScriptEvents(IClientAPI client) |
2444 | client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; | 2501 | { |
2445 | client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; | ||
2446 | client.OnObjectSaleInfo += ObjectSaleInfo; | ||
2447 | client.OnScriptReset += ProcessScriptReset; | 2502 | client.OnScriptReset += ProcessScriptReset; |
2448 | client.OnGetScriptRunning += GetScriptRunning; | 2503 | client.OnGetScriptRunning += GetScriptRunning; |
2449 | client.OnSetScriptRunning += SetScriptRunning; | 2504 | client.OnSetScriptRunning += SetScriptRunning; |
2505 | } | ||
2506 | |||
2507 | public virtual void SubscribeToClientParcelEvents(IClientAPI client) | ||
2508 | { | ||
2509 | client.OnObjectGroupRequest += m_sceneGraph.HandleObjectGroupUpdate; | ||
2510 | client.OnParcelReturnObjectsRequest += LandChannel.ReturnObjectsInParcel; | ||
2511 | client.OnParcelSetOtherCleanTime += LandChannel.SetParcelOtherCleanTime; | ||
2512 | client.OnParcelBuy += ProcessParcelBuy; | ||
2513 | } | ||
2514 | |||
2515 | public virtual void SubscribeToClientGridEvents(IClientAPI client) | ||
2516 | { | ||
2517 | client.OnNameFromUUIDRequest += CommsManager.HandleUUIDNameRequest; | ||
2518 | client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; | ||
2519 | client.OnAvatarPickerRequest += ProcessAvatarPickerRequest; | ||
2520 | client.OnSetStartLocationRequest += SetHomeRezPoint; | ||
2450 | client.OnRegionHandleRequest += RegionHandleRequest; | 2521 | client.OnRegionHandleRequest += RegionHandleRequest; |
2451 | client.OnUnackedTerrain += TerrainUnAcked; | 2522 | } |
2452 | client.OnObjectOwner += ObjectOwner; | ||
2453 | 2523 | ||
2524 | public virtual void SubscribeToClientGodEvents(IClientAPI client) | ||
2525 | { | ||
2454 | IGodsModule godsModule = RequestModuleInterface<IGodsModule>(); | 2526 | IGodsModule godsModule = RequestModuleInterface<IGodsModule>(); |
2455 | client.OnGodKickUser += godsModule.KickUser; | 2527 | client.OnGodKickUser += godsModule.KickUser; |
2456 | client.OnRequestGodlikePowers += godsModule.RequestGodlikePowers; | 2528 | client.OnRequestGodlikePowers += godsModule.RequestGodlikePowers; |
2529 | } | ||
2457 | 2530 | ||
2531 | public virtual void SubscribeToClientNetworkEvents(IClientAPI client) | ||
2532 | { | ||
2458 | client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; | 2533 | client.OnNetworkStatsUpdate += StatsReporter.AddPacketsStats; |
2534 | } | ||
2535 | |||
2536 | protected virtual void UnsubscribeToClientEvents(IClientAPI client) | ||
2537 | { | ||
2538 | |||
2539 | } | ||
2540 | |||
2541 | /// <summary> | ||
2542 | /// Register for events from the client | ||
2543 | /// </summary> | ||
2544 | /// <param name="client">The IClientAPI of the connected client</param> | ||
2545 | public virtual void UnSubscribeToClientEvents(IClientAPI client) | ||
2546 | { | ||
2547 | UnSubscribeToClientTerrainEvents(client); | ||
2548 | UnSubscribeToClientPrimEvents(client); | ||
2549 | UnSubscribeToClientPrimRezEvents(client); | ||
2550 | UnSubscribeToClientInventoryEvents(client); | ||
2551 | UnSubscribeToClientAttachmentEvents(client); | ||
2552 | UnSubscribeToClientTeleportEvents(client); | ||
2553 | UnSubscribeToClientScriptEvents(client); | ||
2554 | UnSubscribeToClientParcelEvents(client); | ||
2555 | UnSubscribeToClientGridEvents(client); | ||
2556 | UnSubscribeToClientGodEvents(client); | ||
2557 | |||
2558 | UnSubscribeToClientNetworkEvents(client); | ||
2559 | |||
2459 | 2560 | ||
2460 | // EventManager.TriggerOnNewClient(client); | 2561 | // EventManager.TriggerOnNewClient(client); |
2461 | } | 2562 | } |
2462 | 2563 | ||
2564 | public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) | ||
2565 | { | ||
2566 | client.OnRegionHandShakeReply -= SendLayerData; | ||
2567 | client.OnUnackedTerrain -= TerrainUnAcked; | ||
2568 | } | ||
2569 | |||
2570 | public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) | ||
2571 | { | ||
2572 | client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimPosition; | ||
2573 | client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; | ||
2574 | client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimRotation; | ||
2575 | client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimRotation; | ||
2576 | client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; | ||
2577 | client.OnUpdatePrimSingleRotationPosition -= m_sceneGraph.UpdatePrimSingleRotationPosition; | ||
2578 | client.OnUpdatePrimScale -= m_sceneGraph.UpdatePrimScale; | ||
2579 | client.OnUpdatePrimGroupScale -= m_sceneGraph.UpdatePrimGroupScale; | ||
2580 | client.OnUpdateExtraParams -= m_sceneGraph.UpdateExtraParam; | ||
2581 | client.OnUpdatePrimShape -= m_sceneGraph.UpdatePrimShape; | ||
2582 | client.OnUpdatePrimTexture -= m_sceneGraph.UpdatePrimTexture; | ||
2583 | client.OnObjectRequest -= RequestPrim; | ||
2584 | client.OnObjectSelect -= SelectPrim; | ||
2585 | client.OnObjectDeselect -= DeselectPrim; | ||
2586 | client.OnGrabUpdate -= m_sceneGraph.MoveObject; | ||
2587 | client.OnSpinStart -= m_sceneGraph.SpinStart; | ||
2588 | client.OnSpinUpdate -= m_sceneGraph.SpinObject; | ||
2589 | client.OnDeRezObject -= DeRezObject; | ||
2590 | client.OnObjectName -= m_sceneGraph.PrimName; | ||
2591 | client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; | ||
2592 | client.OnObjectMaterial -= m_sceneGraph.PrimMaterial; | ||
2593 | client.OnLinkObjects -= m_sceneGraph.LinkObjects; | ||
2594 | client.OnDelinkObjects -= m_sceneGraph.DelinkObjects; | ||
2595 | client.OnObjectDuplicate -= m_sceneGraph.DuplicateObject; | ||
2596 | client.OnObjectDuplicateOnRay -= doObjectDuplicateOnRay; | ||
2597 | client.OnUpdatePrimFlags -= m_sceneGraph.UpdatePrimFlags; | ||
2598 | client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily; | ||
2599 | client.OnObjectPermissions -= HandleObjectPermissionsUpdate; | ||
2600 | client.OnGrabObject -= ProcessObjectGrab; | ||
2601 | client.OnDeGrabObject -= ProcessObjectDeGrab; | ||
2602 | client.OnUndo -= m_sceneGraph.HandleUndo; | ||
2603 | client.OnObjectDescription -= m_sceneGraph.PrimDescription; | ||
2604 | client.OnObjectDrop -= m_sceneGraph.DropObject; | ||
2605 | client.OnObjectSaleInfo -= ObjectSaleInfo; | ||
2606 | client.OnObjectIncludeInSearch -= m_sceneGraph.MakeObjectSearchable; | ||
2607 | client.OnObjectOwner -= ObjectOwner; | ||
2608 | } | ||
2609 | |||
2610 | public virtual void UnSubscribeToClientPrimRezEvents(IClientAPI client) | ||
2611 | { | ||
2612 | client.OnAddPrim -= AddNewPrim; | ||
2613 | client.OnRezObject -= RezObject; | ||
2614 | } | ||
2615 | |||
2616 | |||
2617 | public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client) | ||
2618 | { | ||
2619 | client.OnCreateNewInventoryItem -= CreateNewInventoryItem; | ||
2620 | client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; | ||
2621 | client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; | ||
2622 | client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! | ||
2623 | client.OnFetchInventoryDescendents -= HandleFetchInventoryDescendents; | ||
2624 | client.OnPurgeInventoryDescendents -= HandlePurgeInventoryDescendents; // 2; //!! | ||
2625 | client.OnFetchInventory -= HandleFetchInventory; | ||
2626 | client.OnUpdateInventoryItem -= UpdateInventoryItemAsset; | ||
2627 | client.OnCopyInventoryItem -= CopyInventoryItem; | ||
2628 | client.OnMoveInventoryItem -= MoveInventoryItem; | ||
2629 | client.OnRemoveInventoryItem -= RemoveInventoryItem; | ||
2630 | client.OnRemoveInventoryFolder -= RemoveInventoryFolder; | ||
2631 | client.OnRezScript -= RezScript; | ||
2632 | client.OnRequestTaskInventory -= RequestTaskInventory; | ||
2633 | client.OnRemoveTaskItem -= RemoveTaskInventory; | ||
2634 | client.OnUpdateTaskInventory -= UpdateTaskInventory; | ||
2635 | client.OnMoveTaskItem -= ClientMoveTaskInventoryItem; | ||
2636 | } | ||
2637 | |||
2638 | public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) | ||
2639 | { | ||
2640 | client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; | ||
2641 | client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; | ||
2642 | client.OnDetachAttachmentIntoInv -= DetachSingleAttachmentToInv; | ||
2643 | client.OnObjectAttach -= m_sceneGraph.AttachObject; | ||
2644 | client.OnObjectDetach -= m_sceneGraph.DetachObject; | ||
2645 | } | ||
2646 | |||
2647 | public virtual void UnSubscribeToClientTeleportEvents(IClientAPI client) | ||
2648 | { | ||
2649 | client.OnTeleportLocationRequest -= RequestTeleportLocation; | ||
2650 | client.OnTeleportLandmarkRequest -= RequestTeleportLandmark; | ||
2651 | client.OnTeleportHomeRequest -= TeleportClientHome; | ||
2652 | } | ||
2653 | |||
2654 | public virtual void UnSubscribeToClientScriptEvents(IClientAPI client) | ||
2655 | { | ||
2656 | client.OnScriptReset -= ProcessScriptReset; | ||
2657 | client.OnGetScriptRunning -= GetScriptRunning; | ||
2658 | client.OnSetScriptRunning -= SetScriptRunning; | ||
2659 | } | ||
2660 | |||
2661 | public virtual void UnSubscribeToClientParcelEvents(IClientAPI client) | ||
2662 | { | ||
2663 | client.OnObjectGroupRequest -= m_sceneGraph.HandleObjectGroupUpdate; | ||
2664 | client.OnParcelReturnObjectsRequest -= LandChannel.ReturnObjectsInParcel; | ||
2665 | client.OnParcelSetOtherCleanTime -= LandChannel.SetParcelOtherCleanTime; | ||
2666 | client.OnParcelBuy -= ProcessParcelBuy; | ||
2667 | } | ||
2668 | |||
2669 | public virtual void UnSubscribeToClientGridEvents(IClientAPI client) | ||
2670 | { | ||
2671 | client.OnNameFromUUIDRequest -= CommsManager.HandleUUIDNameRequest; | ||
2672 | client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; | ||
2673 | client.OnAvatarPickerRequest -= ProcessAvatarPickerRequest; | ||
2674 | client.OnSetStartLocationRequest -= SetHomeRezPoint; | ||
2675 | client.OnRegionHandleRequest -= RegionHandleRequest; | ||
2676 | } | ||
2677 | |||
2678 | public virtual void UnSubscribeToClientGodEvents(IClientAPI client) | ||
2679 | { | ||
2680 | IGodsModule godsModule = RequestModuleInterface<IGodsModule>(); | ||
2681 | client.OnGodKickUser -= godsModule.KickUser; | ||
2682 | client.OnRequestGodlikePowers -= godsModule.RequestGodlikePowers; | ||
2683 | } | ||
2684 | |||
2685 | public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) | ||
2686 | { | ||
2687 | client.OnNetworkStatsUpdate -= StatsReporter.AddPacketsStats; | ||
2688 | } | ||
2689 | |||
2690 | |||
2691 | |||
2692 | |||
2463 | /// <summary> | 2693 | /// <summary> |
2464 | /// Teleport an avatar to their home region | 2694 | /// Teleport an avatar to their home region |
2465 | /// </summary> | 2695 | /// </summary> |
@@ -2617,6 +2847,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2617 | /// <returns></returns> | 2847 | /// <returns></returns> |
2618 | protected virtual ScenePresence CreateAndAddScenePresence(IClientAPI client) | 2848 | protected virtual ScenePresence CreateAndAddScenePresence(IClientAPI client) |
2619 | { | 2849 | { |
2850 | CheckHeartbeat(); | ||
2620 | AvatarAppearance appearance = null; | 2851 | AvatarAppearance appearance = null; |
2621 | GetAvatarAppearance(client, out appearance); | 2852 | GetAvatarAppearance(client, out appearance); |
2622 | 2853 | ||
@@ -2659,6 +2890,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2659 | /// <param name="agentID"></param> | 2890 | /// <param name="agentID"></param> |
2660 | public override void RemoveClient(UUID agentID) | 2891 | public override void RemoveClient(UUID agentID) |
2661 | { | 2892 | { |
2893 | CheckHeartbeat(); | ||
2662 | bool childagentYN = false; | 2894 | bool childagentYN = false; |
2663 | ScenePresence avatar = GetScenePresence(agentID); | 2895 | ScenePresence avatar = GetScenePresence(agentID); |
2664 | if (avatar != null) | 2896 | if (avatar != null) |
@@ -2926,11 +3158,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2926 | 3158 | ||
2927 | if (!agent.child) | 3159 | if (!agent.child) |
2928 | { | 3160 | { |
2929 | if (agent.startpos.X > (int)Constants.RegionSize - 1) | 3161 | if (TestBorderCross(agent.startpos,Cardinals.E)) |
2930 | agent.startpos.X = (int)Constants.RegionSize - 1; | 3162 | { |
3163 | Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); | ||
3164 | agent.startpos.X = crossedBorder.BorderLine.Z - 1; | ||
3165 | } | ||
2931 | 3166 | ||
2932 | if (agent.startpos.Y > (int)Constants.RegionSize - 1) | 3167 | if (TestBorderCross(agent.startpos, Cardinals.N)) |
2933 | agent.startpos.Y = (int)Constants.RegionSize - 1; | 3168 | { |
3169 | Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); | ||
3170 | agent.startpos.Y = crossedBorder.BorderLine.Z - 1; | ||
3171 | } | ||
2934 | 3172 | ||
2935 | // Honor parcel landing type and position. | 3173 | // Honor parcel landing type and position. |
2936 | ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); | 3174 | ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); |
@@ -4160,6 +4398,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
4160 | else | 4398 | else |
4161 | return health; | 4399 | return health; |
4162 | 4400 | ||
4401 | CheckHeartbeat(); | ||
4402 | |||
4163 | return health; | 4403 | return health; |
4164 | } | 4404 | } |
4165 | 4405 | ||
@@ -4345,5 +4585,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
4345 | 4585 | ||
4346 | return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; | 4586 | return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; |
4347 | } | 4587 | } |
4588 | |||
4589 | private void CheckHeartbeat() | ||
4590 | { | ||
4591 | if (m_firstHeartbeat) | ||
4592 | return; | ||
4593 | |||
4594 | if (System.Environment.TickCount - m_lastUpdate > 2000) | ||
4595 | StartTimer(); | ||
4596 | } | ||
4348 | } | 4597 | } |
4349 | } | 4598 | } |
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index c6b3f30..0827672 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs | |||
@@ -367,6 +367,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
367 | string reason = String.Empty; | 367 | string reason = String.Empty; |
368 | 368 | ||
369 | //bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a); | 369 | //bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a); |
370 | |||
370 | bool regionAccepted = m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a, out reason); | 371 | bool regionAccepted = m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a, out reason); |
371 | 372 | ||
372 | if (regionAccepted && newAgent) | 373 | if (regionAccepted && newAgent) |
@@ -384,7 +385,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
384 | 385 | ||
385 | eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID); | 386 | eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID); |
386 | eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath); | 387 | eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath); |
387 | m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}", | 388 | m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}", |
388 | capsPath, avatar.UUID, avatar.Scene.RegionInfo.RegionName); | 389 | capsPath, avatar.UUID, avatar.Scene.RegionInfo.RegionName); |
389 | } | 390 | } |
390 | else | 391 | else |
@@ -394,7 +395,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
394 | } | 395 | } |
395 | 396 | ||
396 | m_log.Info("[INTERGRID]: Completed inform client about neighbour " + endPoint.ToString()); | 397 | m_log.Info("[INTERGRID]: Completed inform client about neighbour " + endPoint.ToString()); |
398 | |||
397 | } | 399 | } |
400 | |||
398 | } | 401 | } |
399 | 402 | ||
400 | public void RequestNeighbors(RegionInfo region) | 403 | public void RequestNeighbors(RegionInfo region) |
@@ -407,6 +410,65 @@ namespace OpenSim.Region.Framework.Scenes | |||
407 | //blah.Port = region.RemotingPort; | 410 | //blah.Port = region.RemotingPort; |
408 | } | 411 | } |
409 | 412 | ||
413 | public List<SimpleRegionInfo> RequestNeighbors(Scene pScene, uint pRegionLocX, uint pRegionLocY) | ||
414 | { | ||
415 | Border[] northBorders = pScene.NorthBorders.ToArray(); | ||
416 | Border[] southBorders = pScene.SouthBorders.ToArray(); | ||
417 | Border[] eastBorders = pScene.EastBorders.ToArray(); | ||
418 | Border[] westBorders = pScene.WestBorders.ToArray(); | ||
419 | |||
420 | // Legacy one region. Provided for simplicity while testing the all inclusive method in the else statement. | ||
421 | if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1) | ||
422 | { | ||
423 | return m_commsProvider.GridService.RequestNeighbours(pRegionLocX, pRegionLocY); | ||
424 | } | ||
425 | else | ||
426 | { | ||
427 | Vector2 extent = Vector2.Zero; | ||
428 | for (int i=0;i<eastBorders.Length;i++) | ||
429 | { | ||
430 | extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X; | ||
431 | } | ||
432 | for (int i=0;i<northBorders.Length;i++) | ||
433 | { | ||
434 | extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y; | ||
435 | } | ||
436 | |||
437 | List<SimpleRegionInfo> neighbourList = new List<SimpleRegionInfo>(); | ||
438 | |||
439 | // Loss of fraction on purpose | ||
440 | extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1; | ||
441 | extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1; | ||
442 | |||
443 | int startX = (int) pRegionLocX - 1; | ||
444 | int startY = (int) pRegionLocY - 1; | ||
445 | |||
446 | int endX = (int) pRegionLocX + (int)extent.X + 1; | ||
447 | int endY = (int) pRegionLocY + (int)extent.Y + 1; | ||
448 | |||
449 | for (int i=startX;i<endX;i++) | ||
450 | { | ||
451 | for (int j=startY;j<endY;j++) | ||
452 | { | ||
453 | // Skip CurrentRegion | ||
454 | if (i == (int)pRegionLocX && j == (int)pRegionLocY) | ||
455 | continue; | ||
456 | |||
457 | ulong regionHandle = Util.UIntsToLong((uint)(i * Constants.RegionSize), | ||
458 | (uint)(j * Constants.RegionSize)); | ||
459 | RegionInfo neighborreg = m_commsProvider.GridService.RequestNeighbourInfo(regionHandle); | ||
460 | if (neighborreg != null) | ||
461 | { | ||
462 | neighbourList.Add(neighborreg); | ||
463 | } | ||
464 | } | ||
465 | } | ||
466 | return neighbourList; | ||
467 | //SimpleRegionInfo regionData = m_commsProvider.GridService.RequestNeighbourInfo() | ||
468 | //return m_commsProvider.GridService.RequestNeighbours(pRegionLocX, pRegionLocY); | ||
469 | } | ||
470 | } | ||
471 | |||
410 | /// <summary> | 472 | /// <summary> |
411 | /// This informs all neighboring regions about agent "avatar". | 473 | /// This informs all neighboring regions about agent "avatar". |
412 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. | 474 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. |
@@ -429,7 +491,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
429 | if (m_regionInfo != null) | 491 | if (m_regionInfo != null) |
430 | { | 492 | { |
431 | neighbours = | 493 | neighbours = |
432 | m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); | 494 | RequestNeighbors(avatar.Scene,m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); |
433 | } | 495 | } |
434 | else | 496 | else |
435 | { | 497 | { |
@@ -536,6 +598,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
536 | InformClientOfNeighbourCompleted, | 598 | InformClientOfNeighbourCompleted, |
537 | d); | 599 | d); |
538 | } | 600 | } |
601 | |||
602 | catch (ArgumentOutOfRangeException) | ||
603 | { | ||
604 | m_log.ErrorFormat( | ||
605 | "[REGIONINFO]: Neighbour Regions response included the current region in the neighbor list. The following region will not display to the client: {0} for region {1} ({2}, {3}).", | ||
606 | neighbour.ExternalHostName, | ||
607 | neighbour.RegionHandle, | ||
608 | neighbour.RegionLocX, | ||
609 | neighbour.RegionLocY); | ||
610 | } | ||
539 | catch (Exception e) | 611 | catch (Exception e) |
540 | { | 612 | { |
541 | m_log.ErrorFormat( | 613 | m_log.ErrorFormat( |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 857dc11..1024857 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -62,6 +62,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
62 | public ScriptControlled eventControls; | 62 | public ScriptControlled eventControls; |
63 | } | 63 | } |
64 | 64 | ||
65 | public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence); | ||
66 | |||
65 | public class ScenePresence : EntityBase | 67 | public class ScenePresence : EntityBase |
66 | { | 68 | { |
67 | // ~ScenePresence() | 69 | // ~ScenePresence() |
@@ -87,12 +89,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
87 | public Vector3 lastKnownAllowedPosition; | 89 | public Vector3 lastKnownAllowedPosition; |
88 | public bool sentMessageAboutRestrictedParcelFlyingDown; | 90 | public bool sentMessageAboutRestrictedParcelFlyingDown; |
89 | 91 | ||
92 | |||
93 | |||
90 | private bool m_updateflag; | 94 | private bool m_updateflag; |
91 | private byte m_movementflag; | 95 | private byte m_movementflag; |
92 | private readonly List<NewForce> m_forcesList = new List<NewForce>(); | 96 | private readonly List<NewForce> m_forcesList = new List<NewForce>(); |
93 | private short m_updateCount; | 97 | private short m_updateCount; |
94 | private uint m_requestedSitTargetID; | 98 | private uint m_requestedSitTargetID; |
95 | private UUID m_requestedSitTargetUUID = UUID.Zero; | 99 | private UUID m_requestedSitTargetUUID = UUID.Zero; |
100 | private SendCourseLocationsMethod m_sendCourseLocationsMethod; | ||
96 | 101 | ||
97 | private bool m_startAnimationSet; | 102 | private bool m_startAnimationSet; |
98 | 103 | ||
@@ -616,6 +621,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
616 | 621 | ||
617 | private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) | 622 | private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) |
618 | { | 623 | { |
624 | m_sendCourseLocationsMethod = SendCoarseLocationsDefault; | ||
619 | CreateSceneViewer(); | 625 | CreateSceneViewer(); |
620 | m_regionHandle = reginfo.RegionHandle; | 626 | m_regionHandle = reginfo.RegionHandle; |
621 | m_controllingClient = client; | 627 | m_controllingClient = client; |
@@ -2458,6 +2464,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
2458 | 2464 | ||
2459 | public void SendCoarseLocations() | 2465 | public void SendCoarseLocations() |
2460 | { | 2466 | { |
2467 | SendCourseLocationsMethod d = m_sendCourseLocationsMethod; | ||
2468 | if (d != null) | ||
2469 | { | ||
2470 | d.Invoke(m_scene.RegionInfo.originRegionID, this); | ||
2471 | } | ||
2472 | } | ||
2473 | |||
2474 | public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) | ||
2475 | { | ||
2476 | if (d != null) | ||
2477 | m_sendCourseLocationsMethod = d; | ||
2478 | } | ||
2479 | |||
2480 | public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p) | ||
2481 | { | ||
2461 | m_perfMonMS = Environment.TickCount; | 2482 | m_perfMonMS = Environment.TickCount; |
2462 | 2483 | ||
2463 | List<Vector3> CoarseLocations = new List<Vector3>(); | 2484 | List<Vector3> CoarseLocations = new List<Vector3>(); |
@@ -3302,6 +3323,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3302 | { | 3323 | { |
3303 | Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); | 3324 | Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); |
3304 | DefaultTexture = textu.GetBytes(); | 3325 | DefaultTexture = textu.GetBytes(); |
3326 | |||
3305 | } | 3327 | } |
3306 | 3328 | ||
3307 | public class NewForce | 3329 | public class NewForce |
@@ -3431,6 +3453,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3431 | Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); | 3453 | Primitive.TextureEntry textu = AvatarAppearance.GetDefaultTexture(); |
3432 | DefaultTexture = textu.GetBytes(); | 3454 | DefaultTexture = textu.GetBytes(); |
3433 | } | 3455 | } |
3456 | m_sendCourseLocationsMethod = SendCoarseLocationsDefault; | ||
3434 | CreateSceneViewer(); | 3457 | CreateSceneViewer(); |
3435 | } | 3458 | } |
3436 | 3459 | ||