aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorunknown2010-05-20 12:28:13 -0700
committerunknown2010-05-20 12:28:13 -0700
commitbeed74096cbe7df35b2a8036a89af398f908544d (patch)
tree78cec5ca1f73b35f0b5c30a88d8cd97538bb27e8
parentRevert one of the previous patches' hunks. The new code looked better, but (diff)
parent* Don't send texture data for prims in ImprovedTerseObjectUpdate packets unle... (diff)
downloadopensim-SC-beed74096cbe7df35b2a8036a89af398f908544d.zip
opensim-SC-beed74096cbe7df35b2a8036a89af398f908544d.tar.gz
opensim-SC-beed74096cbe7df35b2a8036a89af398f908544d.tar.bz2
opensim-SC-beed74096cbe7df35b2a8036a89af398f908544d.tar.xz
Merging slimupdates2
-rw-r--r--OpenSim/Client/MXP/ClientStack/MXPClientView.cs47
-rw-r--r--OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs20
-rw-r--r--OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs16
-rw-r--r--OpenSim/Framework/IClientAPI.cs258
-rw-r--r--OpenSim/Framework/ISceneEntity.cs37
-rw-r--r--OpenSim/Framework/Lazy.cs236
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs630
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs18
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs16
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs10
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs14
-rw-r--r--OpenSim/Region/Framework/Interfaces/ILandChannel.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs114
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs29
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs34
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs14
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs82
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs15
-rw-r--r--OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs3
-rw-r--r--OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs113
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs187
-rw-r--r--OpenSim/Services/Interfaces/IGridUserService.cs2
-rw-r--r--OpenSim/Services/UserAccountService/GridUserService.cs2
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs14
-rw-r--r--OpenSim/Tests/Common/Mock/TestLandChannel.cs4
32 files changed, 1093 insertions, 889 deletions
diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
index 1d6d4c1..a62d897 100644
--- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
+++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
@@ -1026,23 +1026,6 @@ namespace OpenSim.Client.MXP.ClientStack
1026 // Need to translate to MXP somehow 1026 // Need to translate to MXP somehow
1027 } 1027 }
1028 1028
1029 public void SendAvatarData(SendAvatarData data)
1030 {
1031 //ScenePresence presence=((Scene)this.Scene).GetScenePresence(avatarID);
1032 UUID ownerID = data.AvatarID;
1033 MXPSendAvatarData(data.FirstName + " " + data.LastName, ownerID, UUID.Zero, data.AvatarID, data.AvatarLocalID, data.Position, data.Rotation);
1034 }
1035
1036 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
1037 {
1038 MovementEventMessage me = new MovementEventMessage();
1039 me.ObjectIndex = data.LocalID;
1040 me.Location = ToOmVector(data.Position);
1041 me.Orientation = ToOmQuaternion(data.Rotation);
1042
1043 Session.Send(me);
1044 }
1045
1046 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 1029 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
1047 { 1030 {
1048 // Minimap function, not used. 1031 // Minimap function, not used.
@@ -1058,23 +1041,31 @@ namespace OpenSim.Client.MXP.ClientStack
1058 // Need to translate to MXP somehow 1041 // Need to translate to MXP somehow
1059 } 1042 }
1060 1043
1061 public void SendPrimitiveToClient(SendPrimitiveData data) 1044 public void SendAvatarDataImmediate(ISceneEntity avatar)
1062 { 1045 {
1063 MXPSendPrimitive(data.localID, data.ownerID, data.acc, data.rvel, data.primShape, data.pos, data.objectID, data.vel, 1046 //ScenePresence presence=((Scene)this.Scene).GetScenePresence(avatarID);
1064 data.rotation, (uint)data.flags, data.text, data.color, data.parentID, data.particleSystem, data.clickAction, 1047 ScenePresence presence = (ScenePresence)avatar;
1065 data.material, data.textureanim); 1048 UUID ownerID = presence.UUID;
1049 MXPSendAvatarData(presence.Firstname + " " + presence.Lastname, ownerID, UUID.Zero, presence.UUID, presence.LocalId, presence.AbsolutePosition, presence.Rotation);
1066 } 1050 }
1067 1051
1068 public void SendPrimTerseUpdate(SendPrimitiveTerseData data) 1052 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
1069 { 1053 {
1070 MovementEventMessage me = new MovementEventMessage(); 1054 //MovementEventMessage me = new MovementEventMessage();
1071 me.ObjectIndex = data.LocalID; 1055 //me.ObjectIndex = data.LocalID;
1072 me.Location = ToOmVector(data.Position); 1056 //me.Location = ToOmVector(data.Position);
1073 me.Orientation = ToOmQuaternion(data.Rotation); 1057 //me.Orientation = ToOmQuaternion(data.Rotation);
1074 Session.Send(me); 1058
1059 //MXPSendPrimitive(data.localID, data.ownerID, data.acc, data.rvel, data.primShape, data.pos, data.objectID, data.vel,
1060 // data.rotation, (uint)data.flags, data.text, data.color, data.parentID, data.particleSystem, data.clickAction,
1061 // data.material, data.textureanim);
1062
1063 //Session.Send(me);
1064
1065 throw new System.NotImplementedException();
1075 } 1066 }
1076 1067
1077 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 1068 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
1078 { 1069 {
1079 } 1070 }
1080 1071
diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs
index 43c64e9..d1f0988 100644
--- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs
+++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs
@@ -584,16 +584,6 @@ namespace OpenSim.Client.Sirikata.ClientStack
584 throw new System.NotImplementedException(); 584 throw new System.NotImplementedException();
585 } 585 }
586 586
587 public void SendAvatarData(SendAvatarData data)
588 {
589 throw new System.NotImplementedException();
590 }
591
592 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
593 {
594 throw new System.NotImplementedException();
595 }
596
597 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 587 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
598 { 588 {
599 throw new System.NotImplementedException(); 589 throw new System.NotImplementedException();
@@ -609,27 +599,27 @@ namespace OpenSim.Client.Sirikata.ClientStack
609 throw new System.NotImplementedException(); 599 throw new System.NotImplementedException();
610 } 600 }
611 601
612 public void SendPrimitiveToClient(SendPrimitiveData data) 602 public void SendAvatarDataImmediate(ISceneEntity avatar)
613 { 603 {
614 throw new System.NotImplementedException(); 604 throw new System.NotImplementedException();
615 } 605 }
616 606
617 public void SendPrimTerseUpdate(SendPrimitiveTerseData data) 607 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
618 { 608 {
619 throw new System.NotImplementedException(); 609 throw new System.NotImplementedException();
620 } 610 }
621 611
622 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 612 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
623 { 613 {
624 throw new System.NotImplementedException(); 614 throw new System.NotImplementedException();
625 } 615 }
626 616
627 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems) 617 public void FlushPrimUpdates()
628 { 618 {
629 throw new System.NotImplementedException(); 619 throw new System.NotImplementedException();
630 } 620 }
631 621
632 public void FlushPrimUpdates() 622 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems)
633 { 623 {
634 throw new System.NotImplementedException(); 624 throw new System.NotImplementedException();
635 } 625 }
diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
index 864b4f1..c0da326 100644
--- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
+++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
@@ -590,16 +590,6 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
590 throw new System.NotImplementedException(); 590 throw new System.NotImplementedException();
591 } 591 }
592 592
593 public void SendAvatarData(SendAvatarData data)
594 {
595 throw new System.NotImplementedException();
596 }
597
598 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
599 {
600 throw new System.NotImplementedException();
601 }
602
603 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 593 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
604 { 594 {
605 throw new System.NotImplementedException(); 595 throw new System.NotImplementedException();
@@ -615,17 +605,17 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
615 throw new System.NotImplementedException(); 605 throw new System.NotImplementedException();
616 } 606 }
617 607
618 public void SendPrimitiveToClient(SendPrimitiveData data) 608 public void SendAvatarDataImmediate(ISceneEntity avatar)
619 { 609 {
620 throw new System.NotImplementedException(); 610 throw new System.NotImplementedException();
621 } 611 }
622 612
623 public void SendPrimTerseUpdate(SendPrimitiveTerseData data) 613 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
624 { 614 {
625 throw new System.NotImplementedException(); 615 throw new System.NotImplementedException();
626 } 616 }
627 617
628 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 618 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
629 { 619 {
630 throw new System.NotImplementedException(); 620 throw new System.NotImplementedException();
631 } 621 }
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 01daeb1..00681cf 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -571,207 +571,6 @@ namespace OpenSim.Framework
571 public float dwell; 571 public float dwell;
572 } 572 }
573 573
574 public struct SendAvatarData
575 {
576 public readonly ulong RegionHandle;
577 public readonly string FirstName;
578 public readonly string LastName;
579 public readonly string GroupTitle;
580 public readonly UUID AvatarID;
581 public readonly uint AvatarLocalID;
582 public readonly Vector3 Position;
583 public readonly byte[] TextureEntry;
584 public readonly uint ParentID;
585 public readonly Quaternion Rotation;
586
587 public SendAvatarData(ulong regionHandle, string firstName, string lastName, string groupTitle, UUID avatarID,
588 uint avatarLocalID, Vector3 position, byte[] textureEntry, uint parentID, Quaternion rotation)
589 {
590 RegionHandle = regionHandle;
591 FirstName = firstName;
592 LastName = lastName;
593 GroupTitle = groupTitle;
594 AvatarID = avatarID;
595 AvatarLocalID = avatarLocalID;
596 Position = position;
597 TextureEntry = textureEntry;
598 ParentID = parentID;
599 Rotation = rotation;
600 }
601 }
602
603 public struct SendAvatarTerseData
604 {
605 public readonly ulong RegionHandle;
606 public readonly ushort TimeDilation;
607 public readonly uint LocalID;
608 public readonly Vector3 Position;
609 public readonly Vector3 Velocity;
610 public readonly Vector3 Acceleration;
611 public readonly Quaternion Rotation;
612 public readonly Vector4 CollisionPlane;
613 public readonly UUID AgentID;
614 public readonly byte[] TextureEntry;
615 public readonly double Priority;
616
617 public SendAvatarTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity,
618 Vector3 acceleration, Quaternion rotation, Vector4 collisionPlane, UUID agentid, byte[] textureEntry, double priority)
619 {
620 RegionHandle = regionHandle;
621 TimeDilation = timeDilation;
622 LocalID = localID;
623 Position = position;
624 Velocity = velocity;
625 Acceleration = acceleration;
626 Rotation = rotation;
627 CollisionPlane = collisionPlane;
628 AgentID = agentid;
629 TextureEntry = textureEntry;
630 Priority = priority;
631 }
632 }
633
634 public struct SendPrimitiveTerseData
635 {
636 public readonly ulong RegionHandle;
637 public readonly ushort TimeDilation;
638 public readonly uint LocalID;
639 public readonly Vector3 Position;
640 public readonly Quaternion Rotation;
641 public readonly Vector3 Velocity;
642 public readonly Vector3 Acceleration;
643 public readonly Vector3 AngularVelocity;
644 public readonly UUID AssetID;
645 public readonly UUID OwnerID;
646 public readonly int AttachPoint;
647 public readonly byte[] TextureEntry;
648 public readonly double Priority;
649
650 public SendPrimitiveTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
651 Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 rotationalvelocity,
652 UUID assetID, UUID ownerID, int attachPoint, byte[] textureEntry, double priority)
653 {
654 RegionHandle = regionHandle;
655 TimeDilation = timeDilation;
656 LocalID = localID;
657 Position = position;
658 Rotation = rotation;
659 Velocity = velocity;
660 Acceleration = acceleration;
661 AngularVelocity = rotationalvelocity;
662 AssetID = assetID;
663 OwnerID = ownerID;
664 AttachPoint = attachPoint;
665 TextureEntry = textureEntry;
666 Priority = priority;
667 }
668 }
669
670 public struct SendPrimitiveData
671 {
672 private ulong m_regionHandle;
673 private ushort m_timeDilation;
674 private uint m_localID;
675 private PrimitiveBaseShape m_primShape;
676 private Vector3 m_pos;
677 private Vector3 m_vel;
678 private Vector3 m_acc;
679 private Quaternion m_rotation;
680 private Vector3 m_rvel;
681 private PrimFlags m_flags;
682 private UUID m_objectID;
683 private UUID m_ownerID;
684 private string m_text;
685 private byte[] m_color;
686 private uint m_parentID;
687 private byte[] m_particleSystem;
688 private byte m_clickAction;
689 private byte m_material;
690 private byte[] m_textureanim;
691 private bool m_attachment;
692 private uint m_AttachPoint;
693 private UUID m_AssetId;
694 private UUID m_SoundId;
695 private double m_SoundVolume;
696 private byte m_SoundFlags;
697 private double m_SoundRadius;
698 private double m_priority;
699
700 public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
701 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
702 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
703 uint parentID, byte[] particleSystem, byte clickAction, byte material, double priority) :
704 this(regionHandle, timeDilation, localID, primShape, pos, vel, acc, rotation, rvel, flags, objectID,
705 ownerID, text, color, parentID, particleSystem, clickAction, material, new byte[0], false, 0, UUID.Zero,
706 UUID.Zero, 0, 0, 0, priority) { }
707
708 public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
709 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
710 uint flags,
711 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID,
712 byte[] particleSystem,
713 byte clickAction, byte material, byte[] textureanim, bool attachment,
714 uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags,
715 double SoundRadius, double priority)
716 {
717 this.m_regionHandle = regionHandle;
718 this.m_timeDilation = timeDilation;
719 this.m_localID = localID;
720 this.m_primShape = primShape;
721 this.m_pos = pos;
722 this.m_vel = vel;
723 this.m_acc = acc;
724 this.m_rotation = rotation;
725 this.m_rvel = rvel;
726 this.m_flags = (PrimFlags)flags;
727 this.m_objectID = objectID;
728 this.m_ownerID = ownerID;
729 this.m_text = text;
730 this.m_color = color;
731 this.m_parentID = parentID;
732 this.m_particleSystem = particleSystem;
733 this.m_clickAction = clickAction;
734 this.m_material = material;
735 this.m_textureanim = textureanim;
736 this.m_attachment = attachment;
737 this.m_AttachPoint = AttachPoint;
738 this.m_AssetId = AssetId;
739 this.m_SoundId = SoundId;
740 this.m_SoundVolume = SoundVolume;
741 this.m_SoundFlags = SoundFlags;
742 this.m_SoundRadius = SoundRadius;
743 this.m_priority = priority;
744 }
745
746 public ulong regionHandle { get { return this.m_regionHandle; } }
747 public ushort timeDilation { get { return this.m_timeDilation; } }
748 public uint localID { get { return this.m_localID; } }
749 public PrimitiveBaseShape primShape { get { return this.m_primShape; } }
750 public Vector3 pos { get { return this.m_pos; } }
751 public Vector3 vel { get { return this.m_vel; } }
752 public Vector3 acc { get { return this.m_acc; } }
753 public Quaternion rotation { get { return this.m_rotation; } }
754 public Vector3 rvel { get { return this.m_rvel; } }
755 public PrimFlags flags { get { return this.m_flags; } }
756 public UUID objectID { get { return this.m_objectID; } }
757 public UUID ownerID { get { return this.m_ownerID; } }
758 public string text { get { return this.m_text; } }
759 public byte[] color { get { return this.m_color; } }
760 public uint parentID { get { return this.m_parentID; } }
761 public byte[] particleSystem { get { return this.m_particleSystem; } }
762 public byte clickAction { get { return this.m_clickAction; } }
763 public byte material { get { return this.m_material; } }
764 public byte[] textureanim { get { return this.m_textureanim; } }
765 public bool attachment { get { return this.m_attachment; } }
766 public uint AttachPoint { get { return this.m_AttachPoint; } }
767 public UUID AssetId { get { return this.m_AssetId; } }
768 public UUID SoundId { get { return this.m_SoundId; } }
769 public double SoundVolume { get { return this.m_SoundVolume; } }
770 public byte SoundFlags { get { return this.m_SoundFlags; } }
771 public double SoundRadius { get { return this.m_SoundRadius; } }
772 public double priority { get { return this.m_priority; } }
773 }
774
775 public struct UpdatePriorityData { 574 public struct UpdatePriorityData {
776 private double m_priority; 575 private double m_priority;
777 private uint m_localID; 576 private uint m_localID;
@@ -785,14 +584,46 @@ namespace OpenSim.Framework
785 public uint localID { get { return this.m_localID; } } 584 public uint localID { get { return this.m_localID; } }
786 } 585 }
787 586
587 /// <summary>
588 /// Specifies the fields that have been changed when sending a prim or
589 /// avatar update
590 /// </summary>
788 [Flags] 591 [Flags]
789 public enum StateUpdateTypes 592 public enum PrimUpdateFlags : uint
790 { 593 {
791 None = 0, 594 None = 0,
792 AvatarTerse = 1, 595 AttachmentPoint = 1 << 0,
793 PrimitiveTerse = AvatarTerse << 1, 596 Material = 1 << 1,
794 PrimitiveFull = PrimitiveTerse << 1, 597 ClickAction = 1 << 2,
795 All = AvatarTerse | PrimitiveTerse | PrimitiveFull, 598 Scale = 1 << 3,
599 ParentID = 1 << 4,
600 PrimFlags = 1 << 5,
601 PrimData = 1 << 6,
602 MediaURL = 1 << 7,
603 ScratchPad = 1 << 8,
604 Textures = 1 << 9,
605 TextureAnim = 1 << 10,
606 NameValue = 1 << 11,
607 Position = 1 << 12,
608 Rotation = 1 << 13,
609 Velocity = 1 << 14,
610 Acceleration = 1 << 15,
611 AngularVelocity = 1 << 16,
612 CollisionPlane = 1 << 17,
613 Text = 1 << 18,
614 Particles = 1 << 19,
615 ExtraData = 1 << 20,
616 Sound = 1 << 21,
617 Joint = 1 << 22,
618 FullUpdate = UInt32.MaxValue
619 }
620
621 public static class PrimUpdateFlagsExtensions
622 {
623 public static bool HasFlag(this PrimUpdateFlags updateFlags, PrimUpdateFlags flag)
624 {
625 return (updateFlags & flag) == flag;
626 }
796 } 627 }
797 628
798 public interface IClientAPI 629 public interface IClientAPI
@@ -1186,27 +1017,20 @@ namespace OpenSim.Framework
1186 void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance); 1017 void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance);
1187 void SendPayPrice(UUID objectID, int[] payPrice); 1018 void SendPayPrice(UUID objectID, int[] payPrice);
1188 1019
1189 void SendAvatarData(SendAvatarData data);
1190
1191 void SendAvatarTerseUpdate(SendAvatarTerseData data);
1192
1193 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); 1020 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
1194 1021
1195 void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID); 1022 void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID);
1196 void SetChildAgentThrottle(byte[] throttle); 1023 void SetChildAgentThrottle(byte[] throttle);
1197 1024
1198 void SendPrimitiveToClient(SendPrimitiveData data); 1025 void SendAvatarDataImmediate(ISceneEntity avatar);
1199 1026 void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags);
1200 void SendPrimTerseUpdate(SendPrimitiveTerseData data); 1027 void ReprioritizeUpdates(UpdatePriorityHandler handler);
1201 1028 void FlushPrimUpdates();
1202 void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler);
1203 1029
1204 void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, 1030 void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
1205 List<InventoryFolderBase> folders, int version, bool fetchFolders, 1031 List<InventoryFolderBase> folders, int version, bool fetchFolders,
1206 bool fetchItems); 1032 bool fetchItems);
1207 1033
1208 void FlushPrimUpdates();
1209
1210 void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item); 1034 void SendInventoryItemDetails(UUID ownerID, InventoryItemBase item);
1211 1035
1212 /// <summary> 1036 /// <summary>
diff --git a/OpenSim/Framework/ISceneEntity.cs b/OpenSim/Framework/ISceneEntity.cs
new file mode 100644
index 0000000..fa3c514
--- /dev/null
+++ b/OpenSim/Framework/ISceneEntity.cs
@@ -0,0 +1,37 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenMetaverse;
29
30namespace OpenSim.Framework
31{
32 public interface ISceneEntity
33 {
34 UUID UUID { get; }
35 uint LocalId { get; }
36 }
37}
diff --git a/OpenSim/Framework/Lazy.cs b/OpenSim/Framework/Lazy.cs
new file mode 100644
index 0000000..8a417ac
--- /dev/null
+++ b/OpenSim/Framework/Lazy.cs
@@ -0,0 +1,236 @@
1//
2// Lazy.cs
3//
4// Authors:
5// Zoltan Varga (vargaz@gmail.com)
6// Marek Safar (marek.safar@gmail.com)
7//
8// Copyright (C) 2009 Novell
9//
10// Permission is hereby granted, free of charge, to any person obtaining
11// a copy of this software and associated documentation files (the
12// "Software"), to deal in the Software without restriction, including
13// without limitation the rights to use, copy, modify, merge, publish,
14// distribute, sublicense, and/or sell copies of the Software, and to
15// permit persons to whom the Software is furnished to do so, subject to
16// the following conditions:
17//
18// The above copyright notice and this permission notice shall be
19// included in all copies or substantial portions of the Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28//
29
30using System;
31using System.Runtime.Serialization;
32using System.Runtime.InteropServices;
33using System.Security.Permissions;
34using System.Threading;
35using System.Diagnostics;
36
37namespace OpenSim.Framework
38{
39 public enum LazyThreadSafetyMode
40 {
41 None,
42 PublicationOnly,
43 ExecutionAndPublication
44 }
45
46 [SerializableAttribute]
47 [ComVisibleAttribute(false)]
48 [HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
49 public class Lazy<T>
50 {
51 T value;
52 bool inited;
53 LazyThreadSafetyMode mode;
54 Func<T> factory;
55 object monitor;
56 Exception exception;
57
58 public Lazy()
59 : this(LazyThreadSafetyMode.ExecutionAndPublication)
60 {
61 }
62
63 public Lazy(Func<T> valueFactory)
64 : this(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication)
65 {
66 }
67
68 public Lazy(bool isThreadSafe)
69 : this(() => Activator.CreateInstance<T>(), isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
70 {
71 }
72
73 public Lazy(Func<T> valueFactory, bool isThreadSafe)
74 : this(valueFactory, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
75 {
76 }
77
78 public Lazy(LazyThreadSafetyMode mode)
79 : this(() => Activator.CreateInstance<T>(), mode)
80 {
81 }
82
83 public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode)
84 {
85 if (valueFactory == null)
86 throw new ArgumentNullException("valueFactory");
87 this.factory = valueFactory;
88 if (mode != LazyThreadSafetyMode.None)
89 monitor = new object();
90 this.mode = mode;
91 }
92
93 // Don't trigger expensive initialization
94 [DebuggerBrowsable(DebuggerBrowsableState.Never)]
95 public T Value
96 {
97 get
98 {
99 if (inited)
100 return value;
101 if (exception != null)
102 throw exception;
103
104 return InitValue();
105 }
106 }
107
108 T InitValue()
109 {
110 switch (mode)
111 {
112 case LazyThreadSafetyMode.None:
113 {
114 var init_factory = factory;
115 if (init_factory == null)
116 throw exception = new InvalidOperationException("The initialization function tries to access Value on this instance");
117 try
118 {
119 factory = null;
120 T v = init_factory();
121 value = v;
122 Thread.MemoryBarrier();
123 inited = true;
124 }
125 catch (Exception ex)
126 {
127 exception = ex;
128 throw;
129 }
130 break;
131 }
132 case LazyThreadSafetyMode.PublicationOnly:
133 {
134 var init_factory = factory;
135 T v;
136
137 //exceptions are ignored
138 if (init_factory != null)
139 v = init_factory();
140 else
141 v = default(T);
142
143 lock (monitor)
144 {
145 if (inited)
146 return value;
147 value = v;
148 Thread.MemoryBarrier();
149 inited = true;
150 factory = null;
151 }
152 break;
153 }
154 case LazyThreadSafetyMode.ExecutionAndPublication:
155 {
156 lock (monitor)
157 {
158 if (inited)
159 return value;
160
161 if (factory == null)
162 throw exception = new InvalidOperationException("The initialization function tries to access Value on this instance");
163
164 var init_factory = factory;
165 try
166 {
167 factory = null;
168 T v = init_factory();
169 value = v;
170 Thread.MemoryBarrier();
171 inited = true;
172 }
173 catch (Exception ex)
174 {
175 exception = ex;
176 throw;
177 }
178 }
179 break;
180 }
181 default:
182 throw new InvalidOperationException("Invalid LazyThreadSafetyMode " + mode);
183 }
184
185 if (monitor == null)
186 {
187 value = factory();
188 inited = true;
189 }
190 else
191 {
192 lock (monitor)
193 {
194 if (inited)
195 return value;
196
197 if (factory == null)
198 throw new InvalidOperationException("The initialization function tries to access Value on this instance");
199
200 var init_factory = factory;
201 try
202 {
203 factory = null;
204 T v = init_factory();
205 value = v;
206 Thread.MemoryBarrier();
207 inited = true;
208 }
209 catch
210 {
211 factory = init_factory;
212 throw;
213 }
214 }
215 }
216
217 return value;
218 }
219
220 public bool IsValueCreated
221 {
222 get
223 {
224 return inited;
225 }
226 }
227
228 public override string ToString()
229 {
230 if (inited)
231 return value.ToString();
232 else
233 return "Value is not created";
234 }
235 }
236}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 1f3582c..07c3a6a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -50,43 +50,17 @@ using Nini.Config;
50 50
51namespace OpenSim.Region.ClientStack.LindenUDP 51namespace OpenSim.Region.ClientStack.LindenUDP
52{ 52{
53 #region Enums 53 public class EntityUpdate
54
55 /// <summary>
56 /// Specifies the fields that have been changed when sending a prim or
57 /// avatar update
58 /// </summary>
59 [Flags]
60 public enum PrimUpdateFlags : uint
61 { 54 {
62 None = 0, 55 public ISceneEntity Entity;
63 AttachmentPoint = 1 << 0, 56 public PrimUpdateFlags Flags;
64 Material = 1 << 1,
65 ClickAction = 1 << 2,
66 Scale = 1 << 3,
67 ParentID = 1 << 4,
68 PrimFlags = 1 << 5,
69 PrimData = 1 << 6,
70 MediaURL = 1 << 7,
71 ScratchPad = 1 << 8,
72 Textures = 1 << 9,
73 TextureAnim = 1 << 10,
74 NameValue = 1 << 11,
75 Position = 1 << 12,
76 Rotation = 1 << 13,
77 Velocity = 1 << 14,
78 Acceleration = 1 << 15,
79 AngularVelocity = 1 << 16,
80 CollisionPlane = 1 << 17,
81 Text = 1 << 18,
82 Particles = 1 << 19,
83 ExtraData = 1 << 20,
84 Sound = 1 << 21,
85 Joint = 1 << 22,
86 FullUpdate = UInt32.MaxValue
87 }
88 57
89 #endregion Enums 58 public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags)
59 {
60 Entity = entity;
61 Flags = flags;
62 }
63 }
90 64
91 public delegate bool PacketMethod(IClientAPI simClient, Packet packet); 65 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
92 66
@@ -350,9 +324,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
350 private readonly IGroupsModule m_GroupsModule; 324 private readonly IGroupsModule m_GroupsModule;
351 325
352 private int m_cachedTextureSerial; 326 private int m_cachedTextureSerial;
353 protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates; 327 private PriorityQueue<double, EntityUpdate> m_entityUpdates;
354 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
355 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
356 328
357 /// <value> 329 /// <value>
358 /// List used in construction of data blocks for an object update packet. This is to stop us having to 330 /// List used in construction of data blocks for an object update packet. This is to stop us having to
@@ -463,9 +435,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
463 435
464 m_scene = scene; 436 m_scene = scene;
465 437
466 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 438 m_entityUpdates = new PriorityQueue<double, EntityUpdate>(m_scene.Entities.Count);
467 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
468 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
469 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 439 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
470 m_killRecord = new HashSet<uint>(); 440 m_killRecord = new HashSet<uint>();
471 441
@@ -1519,7 +1489,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1519 kill.Header.Reliable = true; 1489 kill.Header.Reliable = true;
1520 kill.Header.Zerocoded = true; 1490 kill.Header.Zerocoded = true;
1521 1491
1522 lock (m_primFullUpdates.SyncRoot) 1492 lock (m_entityUpdates.SyncRoot)
1523 { 1493 {
1524 m_killRecord.Add(localID); 1494 m_killRecord.Add(localID);
1525 OutPacket(kill, ThrottleOutPacketType.State); 1495 OutPacket(kill, ThrottleOutPacketType.State);
@@ -3419,71 +3389,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3419 /// <summary> 3389 /// <summary>
3420 /// Send an ObjectUpdate packet with information about an avatar 3390 /// Send an ObjectUpdate packet with information about an avatar
3421 /// </summary> 3391 /// </summary>
3422 public void SendAvatarData(SendAvatarData data) 3392 public void SendAvatarDataImmediate(ISceneEntity avatar)
3423 { 3393 {
3394 ScenePresence presence = avatar as ScenePresence;
3395 if (presence == null)
3396 return;
3397
3424 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3398 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3425 objupdate.Header.Zerocoded = true; 3399 objupdate.Header.Zerocoded = true;
3426 3400
3427 objupdate.RegionData.RegionHandle = data.RegionHandle; 3401 objupdate.RegionData.RegionHandle = presence.RegionHandle;
3428 objupdate.RegionData.TimeDilation = ushort.MaxValue; 3402 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3429 3403
3430 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 3404 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3431 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data); 3405 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
3432 3406
3433 OutPacket(objupdate, ThrottleOutPacketType.Task); 3407 OutPacket(objupdate, ThrottleOutPacketType.Task);
3434 } 3408 }
3435 3409
3436 /// <summary>
3437 /// Send a terse positional/rotation/velocity update about an avatar
3438 /// to the client. This avatar can be that of the client itself.
3439 /// </summary>
3440 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
3441 {
3442 if (data.Priority == double.NaN)
3443 {
3444 m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update");
3445 return;
3446 }
3447
3448 Quaternion rotation = data.Rotation;
3449 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3450 rotation = Quaternion.Identity;
3451
3452 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data);
3453
3454 lock (m_avatarTerseUpdates.SyncRoot)
3455 m_avatarTerseUpdates.Enqueue(data.Priority, terseBlock, data.LocalID);
3456
3457 // If we received an update about our own avatar, process the avatar update priority queue immediately
3458 if (data.AgentID == m_agentId)
3459 ProcessAvatarTerseUpdates();
3460 }
3461
3462 protected void ProcessAvatarTerseUpdates()
3463 {
3464 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3465 terse.Header.Reliable = false;
3466 terse.Header.Zerocoded = true;
3467
3468 //terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock();
3469 terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3470 terse.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3471
3472 lock (m_avatarTerseUpdates.SyncRoot)
3473 {
3474 int count = Math.Min(m_avatarTerseUpdates.Count, m_udpServer.AvatarTerseUpdatesPerPacket);
3475 if (count == 0)
3476 return;
3477
3478 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3479 for (int i = 0; i < count; i++)
3480 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
3481 }
3482
3483 // HACK: Using the task category until the tiered reprioritization code is in
3484 OutPacket(terse, ThrottleOutPacketType.Task);
3485 }
3486
3487 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 3410 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
3488 { 3411 {
3489 if (!IsActive) return; // We don't need to update inactive clients. 3412 if (!IsActive) return; // We don't need to update inactive clients.
@@ -3528,172 +3451,187 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3528 3451
3529 #region Primitive Packet/Data Sending Methods 3452 #region Primitive Packet/Data Sending Methods
3530 3453
3531 public void SendPrimitiveToClient(SendPrimitiveData data) 3454 /// <summary>
3455 /// Generate one of the object update packets based on PrimUpdateFlags
3456 /// and broadcast the packet to clients
3457 /// </summary>
3458 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3532 { 3459 {
3533// string text = data.text; 3460 double priority;
3534// if (text.IndexOf("\n") >= 0)
3535// text = text.Remove(text.IndexOf("\n"));
3536// m_log.DebugFormat(
3537// "[CLIENT]: Placing request to send full info about prim {0} text {1} to client {2}",
3538// data.localID, text, Name);
3539
3540 if (data.priority == double.NaN)
3541 {
3542 m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
3543 return;
3544 }
3545
3546 Quaternion rotation = data.rotation;
3547 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3548 rotation = Quaternion.Identity;
3549
3550 if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
3551 return;
3552 if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9)
3553 return;
3554 3461
3555 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data); 3462 if (entity is SceneObjectPart)
3463 priority = ((SceneObjectPart)entity).ParentGroup.GetUpdatePriority(this);
3464 else if (entity is ScenePresence)
3465 priority = ((ScenePresence)entity).GetUpdatePriority(this);
3466 else
3467 priority = 0.0d;
3556 3468
3557 lock (m_primFullUpdates.SyncRoot) 3469 lock (m_entityUpdates.SyncRoot)
3558 m_primFullUpdates.Enqueue(data.priority, objectData, data.localID); 3470 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags), entity.LocalId);
3559 } 3471 }
3560 3472
3561 void ProcessPrimFullUpdates() 3473 private void ProcessEntityUpdates(int maxUpdates)
3562 { 3474 {
3563 ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3475 Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3564 outPacket.Header.Zerocoded = true; 3476 Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3477 Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3565 3478
3566 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; 3479 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue;
3567 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); 3480 int updatesThisCall = 0;
3568 3481
3569 lock (m_primFullUpdates.SyncRoot) 3482 lock (m_entityUpdates.SyncRoot)
3570 { 3483 {
3571 int count = Math.Min(m_primFullUpdates.Count, m_udpServer.PrimFullUpdatesPerPacket); 3484 EntityUpdate update;
3572 if (count == 0) 3485 while (updatesThisCall < maxUpdates && m_entityUpdates.TryDequeue(out update))
3573 return;
3574
3575 m_fullUpdateDataBlocksBuilder.Clear();
3576
3577 for (int i = 0; i < count; i++)
3578 { 3486 {
3579 ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue(); 3487 ++updatesThisCall;
3488
3489 #region UpdateFlags to packet type conversion
3580 3490
3581 if (!m_killRecord.Contains(block.ID)) 3491 PrimUpdateFlags updateFlags = update.Flags;
3492
3493 bool canUseCompressed = true;
3494 bool canUseImproved = true;
3495
3496 // Compressed object updates only make sense for LL primitives
3497 if (!(update.Entity is SceneObjectPart))
3498 canUseCompressed = false;
3499
3500 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3582 { 3501 {
3583 m_fullUpdateDataBlocksBuilder.Add(block); 3502 canUseCompressed = false;
3584 3503 canUseImproved = false;
3585// string text = Util.FieldToString(outPacket.ObjectData[i].Text); 3504 }
3586// if (text.IndexOf("\n") >= 0) 3505 else
3587// text = text.Remove(text.IndexOf("\n")); 3506 {
3588// m_log.DebugFormat( 3507 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3589// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}", 3508 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3590// outPacket.ObjectData[i].ID, text, Name); 3509 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3510 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3511 {
3512 canUseCompressed = false;
3513 }
3514
3515 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3516 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3517 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3518 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3519 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3520 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3521 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3522 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3523 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3524 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3525 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3526 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3527 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3528 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3529 {
3530 canUseImproved = false;
3531 }
3532 }
3533
3534 #endregion UpdateFlags to packet type conversion
3535
3536 #region Block Construction
3537
3538 // TODO: Remove this once we can build compressed updates
3539 canUseCompressed = false;
3540
3541 if (!canUseImproved && !canUseCompressed)
3542 {
3543 if (update.Entity is ScenePresence)
3544 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3545 else
3546 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3547 }
3548 else if (!canUseImproved)
3549 {
3550 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3591 } 3551 }
3592// else 3552 else
3593// { 3553 {
3594// m_log.WarnFormat( 3554 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3595// "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name); 3555 }
3596// } 3556
3557 #endregion Block Construction
3597 } 3558 }
3559 }
3598 3560
3599 outPacket.ObjectData = m_fullUpdateDataBlocksBuilder.ToArray(); 3561 #region Packet Sending
3600
3601 OutPacket(outPacket, ThrottleOutPacketType.State);
3602 }
3603 }
3604 3562
3605 public void SendPrimTerseUpdate(SendPrimitiveTerseData data) 3563 const float TIME_DILATION = 1.0f;
3606 { 3564 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
3607 if (data.Priority == double.NaN) 3565
3566 if (objectUpdateBlocks.IsValueCreated)
3608 { 3567 {
3609 m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update"); 3568 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3610 return;
3611 }
3612 3569
3613 Quaternion rotation = data.Rotation; 3570 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3614 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f) 3571 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3615 rotation = Quaternion.Identity; 3572 packet.RegionData.TimeDilation = timeDilation;
3573 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3616 3574
3617 if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD 3575 for (int i = 0; i < blocks.Count; i++)
3618 return; 3576 packet.ObjectData[i] = blocks[i];
3619 3577
3620 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data); 3578 OutPacket(packet, ThrottleOutPacketType.Task, true);
3579 }
3621 3580
3622 lock (m_primTerseUpdates.SyncRoot) 3581 if (compressedUpdateBlocks.IsValueCreated)
3623 m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID); 3582 {
3624 } 3583 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3625 3584
3626 void ProcessPrimTerseUpdates() 3585 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3627 { 3586 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3628 ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 3587 packet.RegionData.TimeDilation = timeDilation;
3629 outPacket.Header.Reliable = false; 3588 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3630 outPacket.Header.Zerocoded = true;
3631 3589
3632 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; 3590 for (int i = 0; i < blocks.Count; i++)
3633 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); 3591 packet.ObjectData[i] = blocks[i];
3634 3592
3635 lock (m_primTerseUpdates.SyncRoot) 3593 OutPacket(packet, ThrottleOutPacketType.Task, true);
3594 }
3595
3596 if (terseUpdateBlocks.IsValueCreated)
3636 { 3597 {
3637 int count = Math.Min(m_primTerseUpdates.Count, m_udpServer.PrimTerseUpdatesPerPacket); 3598 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3638 if (count == 0)
3639 return;
3640 3599
3641 outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; 3600 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3642 for (int i = 0; i < count; i++) 3601 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3643 outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue(); 3602 packet.RegionData.TimeDilation = timeDilation;
3603 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3604
3605 for (int i = 0; i < blocks.Count; i++)
3606 packet.ObjectData[i] = blocks[i];
3607
3608 OutPacket(packet, ThrottleOutPacketType.Task, true);
3644 } 3609 }
3645 3610
3646 OutPacket(outPacket, ThrottleOutPacketType.State); 3611 #endregion Packet Sending
3647 } 3612 }
3648 3613
3649 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 3614 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
3650 { 3615 {
3651 PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler terse_update_priority_handler = 3616 //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
3652 delegate(ref double priority, uint local_id) 3617
3653 { 3618 PriorityQueue<double, EntityUpdate>.UpdatePriorityHandler update_priority_handler =
3654 priority = handler(new UpdatePriorityData(priority, local_id));
3655 return priority != double.NaN;
3656 };
3657 PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler =
3658 delegate(ref double priority, uint local_id) 3619 delegate(ref double priority, uint local_id)
3659 { 3620 {
3660 priority = handler(new UpdatePriorityData(priority, local_id)); 3621 priority = handler(new UpdatePriorityData(priority, local_id));
3661 return priority != double.NaN; 3622 return priority != double.NaN;
3662 }; 3623 };
3663 3624
3664 if ((type & StateUpdateTypes.AvatarTerse) != 0) 3625 lock (m_entityUpdates.SyncRoot)
3665 { 3626 m_entityUpdates.Reprioritize(update_priority_handler);
3666 lock (m_avatarTerseUpdates.SyncRoot)
3667 m_avatarTerseUpdates.Reprioritize(terse_update_priority_handler);
3668 }
3669
3670 if ((type & StateUpdateTypes.PrimitiveFull) != 0)
3671 {
3672 lock (m_primFullUpdates.SyncRoot)
3673 m_primFullUpdates.Reprioritize(update_priority_handler);
3674 }
3675
3676 if ((type & StateUpdateTypes.PrimitiveTerse) != 0)
3677 {
3678 lock (m_primTerseUpdates.SyncRoot)
3679 m_primTerseUpdates.Reprioritize(terse_update_priority_handler);
3680 }
3681 } 3627 }
3682 3628
3683 public void FlushPrimUpdates() 3629 public void FlushPrimUpdates()
3684 { 3630 {
3685 while (m_primFullUpdates.Count > 0) 3631 m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
3686 { 3632
3687 ProcessPrimFullUpdates(); 3633 while (m_entityUpdates.Count > 0)
3688 } 3634 ProcessEntityUpdates(-1);
3689 while (m_primTerseUpdates.Count > 0)
3690 {
3691 ProcessPrimTerseUpdates();
3692 }
3693 while (m_avatarTerseUpdates.Count > 0)
3694 {
3695 ProcessAvatarTerseUpdates();
3696 }
3697 } 3635 }
3698 3636
3699 #endregion Primitive Packet/Data Sending Methods 3637 #endregion Primitive Packet/Data Sending Methods
@@ -3726,26 +3664,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3726 { 3664 {
3727 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) 3665 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
3728 { 3666 {
3729 lock (m_avatarTerseUpdates.SyncRoot) 3667 if (m_entityUpdates.Count > 0)
3730 { 3668 ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback);
3731 if (m_avatarTerseUpdates.Count > 0)
3732 ProcessAvatarTerseUpdates();
3733 }
3734 }
3735
3736 if ((categories & ThrottleOutPacketTypeFlags.State) != 0)
3737 {
3738 lock (m_primFullUpdates.SyncRoot)
3739 {
3740 if (m_primFullUpdates.Count > 0)
3741 ProcessPrimFullUpdates();
3742 }
3743
3744 lock (m_primTerseUpdates.SyncRoot)
3745 {
3746 if (m_primTerseUpdates.Count > 0)
3747 ProcessPrimTerseUpdates();
3748 }
3749 } 3669 }
3750 3670
3751 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) 3671 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
@@ -4403,22 +4323,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4403 4323
4404 #region Helper Methods 4324 #region Helper Methods
4405 4325
4406 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendAvatarTerseData data) 4326 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture)
4407 { 4327 {
4408 return CreateImprovedTerseBlock(true, data.LocalID, 0, data.CollisionPlane, data.Position, data.Velocity, 4328 #region ScenePresence/SOP Handling
4409 data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry);
4410 }
4411 4329
4412 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data) 4330 bool avatar = (entity is ScenePresence);
4413 { 4331 uint localID = entity.LocalId;
4414 return CreateImprovedTerseBlock(false, data.LocalID, data.AttachPoint, Vector4.Zero, data.Position, data.Velocity, 4332 uint attachPoint;
4415 data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry); 4333 Vector4 collisionPlane;
4416 } 4334 Vector3 position, velocity, acceleration, angularVelocity;
4335 Quaternion rotation;
4336 byte[] textureEntry;
4337
4338 if (entity is ScenePresence)
4339 {
4340 ScenePresence presence = (ScenePresence)entity;
4341
4342 attachPoint = 0;
4343 collisionPlane = presence.CollisionPlane;
4344 position = presence.OffsetPosition;
4345 velocity = presence.Velocity;
4346 acceleration = Vector3.Zero;
4347 angularVelocity = Vector3.Zero;
4348 rotation = presence.Rotation;
4349
4350 if (sendTexture)
4351 textureEntry = presence.Appearance.Texture.GetBytes();
4352 else
4353 textureEntry = null;
4354 }
4355 else
4356 {
4357 SceneObjectPart part = (SceneObjectPart)entity;
4358
4359 attachPoint = part.AttachmentPoint;
4360 collisionPlane = Vector4.Zero;
4361 position = part.RelativePosition;
4362 velocity = part.Velocity;
4363 acceleration = part.Acceleration;
4364 angularVelocity = part.AngularVelocity;
4365 rotation = part.RotationOffset;
4366
4367 if (sendTexture)
4368 textureEntry = part.Shape.TextureEntry;
4369 else
4370 textureEntry = null;
4371 }
4372
4373 #endregion ScenePresence/SOP Handling
4417 4374
4418 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, int attachPoint,
4419 Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation,
4420 Vector3 angularVelocity, byte[] textureEntry)
4421 {
4422 int pos = 0; 4375 int pos = 0;
4423 byte[] data = new byte[(avatar ? 60 : 44)]; 4376 byte[] data = new byte[(avatar ? 60 : 44)];
4424 4377
@@ -4490,12 +4443,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4490 return block; 4443 return block;
4491 } 4444 }
4492 4445
4493 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data) 4446 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
4494 { 4447 {
4495 byte[] objectData = new byte[76]; 4448 byte[] objectData = new byte[76];
4496 4449
4497 Vector4.UnitW.ToBytes(objectData, 0); // TODO: Collision plane support 4450 data.CollisionPlane.ToBytes(objectData, 0);
4498 data.Position.ToBytes(objectData, 16); 4451 data.OffsetPosition.ToBytes(objectData, 16);
4499 //data.Velocity.ToBytes(objectData, 28); 4452 //data.Velocity.ToBytes(objectData, 28);
4500 //data.Acceleration.ToBytes(objectData, 40); 4453 //data.Acceleration.ToBytes(objectData, 40);
4501 data.Rotation.ToBytes(objectData, 52); 4454 data.Rotation.ToBytes(objectData, 52);
@@ -4505,12 +4458,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4505 4458
4506 update.Data = Utils.EmptyBytes; 4459 update.Data = Utils.EmptyBytes;
4507 update.ExtraParams = new byte[1]; 4460 update.ExtraParams = new byte[1];
4508 update.FullID = data.AvatarID; 4461 update.FullID = data.UUID;
4509 update.ID = data.AvatarLocalID; 4462 update.ID = data.LocalId;
4510 update.Material = (byte)Material.Flesh; 4463 update.Material = (byte)Material.Flesh;
4511 update.MediaURL = Utils.EmptyBytes; 4464 update.MediaURL = Utils.EmptyBytes;
4512 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " + 4465 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
4513 data.LastName + "\nTitle STRING RW SV " + data.GroupTitle); 4466 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
4514 update.ObjectData = objectData; 4467 update.ObjectData = objectData;
4515 update.ParentID = data.ParentID; 4468 update.ParentID = data.ParentID;
4516 update.PathCurve = 16; 4469 update.PathCurve = 16;
@@ -4519,102 +4472,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4519 update.PCode = (byte)PCode.Avatar; 4472 update.PCode = (byte)PCode.Avatar;
4520 update.ProfileCurve = 1; 4473 update.ProfileCurve = 1;
4521 update.PSBlock = Utils.EmptyBytes; 4474 update.PSBlock = Utils.EmptyBytes;
4522 update.Scale = new Vector3(0.45f,0.6f,1.9f); 4475 update.Scale = new Vector3(0.45f, 0.6f, 1.9f);
4523 update.Text = Utils.EmptyBytes; 4476 update.Text = Utils.EmptyBytes;
4524 update.TextColor = new byte[4]; 4477 update.TextColor = new byte[4];
4525 update.TextureAnim = Utils.EmptyBytes; 4478 update.TextureAnim = Utils.EmptyBytes;
4526 update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes; 4479 update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
4527 update.UpdateFlags = (uint)(PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | PrimFlags.ObjectOwnerModify);//61 + (9 << 8) + (130 << 16) + (16 << 24); // TODO: Replace these numbers with PrimFlags 4480 update.UpdateFlags = (uint)(
4481 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
4482 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
4483 PrimFlags.ObjectOwnerModify);
4528 4484
4529 return update; 4485 return update;
4530 } 4486 }
4531 4487
4532 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data) 4488 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
4533 { 4489 {
4534 byte[] objectData = new byte[60]; 4490 byte[] objectData = new byte[60];
4535 data.pos.ToBytes(objectData, 0); 4491 data.RelativePosition.ToBytes(objectData, 0);
4536 data.vel.ToBytes(objectData, 12); 4492 data.Velocity.ToBytes(objectData, 12);
4537 data.acc.ToBytes(objectData, 24); 4493 data.Acceleration.ToBytes(objectData, 24);
4538 data.rotation.ToBytes(objectData, 36); 4494 data.RotationOffset.ToBytes(objectData, 36);
4539 data.rvel.ToBytes(objectData, 48); 4495 data.AngularVelocity.ToBytes(objectData, 48);
4540 4496
4541 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 4497 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4542 update.ClickAction = (byte)data.clickAction; 4498 update.ClickAction = (byte)data.ClickAction;
4543 update.CRC = 0; 4499 update.CRC = 0;
4544 update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes; 4500 update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes;
4545 update.FullID = data.objectID; 4501 update.FullID = data.UUID;
4546 update.ID = data.localID; 4502 update.ID = data.LocalId;
4547 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated 4503 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
4548 //update.JointPivot = Vector3.Zero; 4504 //update.JointPivot = Vector3.Zero;
4549 //update.JointType = 0; 4505 //update.JointType = 0;
4550 update.Material = data.material; 4506 update.Material = data.Material;
4551 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim 4507 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
4552 if (data.attachment) 4508 if (data.IsAttachment)
4553 { 4509 {
4554 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.AssetId); 4510 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID);
4555 update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16)); 4511 update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16));
4556 } 4512 }
4557 else 4513 else
4558 { 4514 {
4559 update.NameValue = Utils.EmptyBytes; 4515 update.NameValue = Utils.EmptyBytes;
4560 update.State = data.primShape.State; 4516 update.State = data.Shape.State;
4561 } 4517 }
4518
4562 update.ObjectData = objectData; 4519 update.ObjectData = objectData;
4563 update.ParentID = data.parentID; 4520 update.ParentID = data.ParentID;
4564 update.PathBegin = data.primShape.PathBegin; 4521 update.PathBegin = data.Shape.PathBegin;
4565 update.PathCurve = data.primShape.PathCurve; 4522 update.PathCurve = data.Shape.PathCurve;
4566 update.PathEnd = data.primShape.PathEnd; 4523 update.PathEnd = data.Shape.PathEnd;
4567 update.PathRadiusOffset = data.primShape.PathRadiusOffset; 4524 update.PathRadiusOffset = data.Shape.PathRadiusOffset;
4568 update.PathRevolutions = data.primShape.PathRevolutions; 4525 update.PathRevolutions = data.Shape.PathRevolutions;
4569 update.PathScaleX = data.primShape.PathScaleX; 4526 update.PathScaleX = data.Shape.PathScaleX;
4570 update.PathScaleY = data.primShape.PathScaleY; 4527 update.PathScaleY = data.Shape.PathScaleY;
4571 update.PathShearX = data.primShape.PathShearX; 4528 update.PathShearX = data.Shape.PathShearX;
4572 update.PathShearY = data.primShape.PathShearY; 4529 update.PathShearY = data.Shape.PathShearY;
4573 update.PathSkew = data.primShape.PathSkew; 4530 update.PathSkew = data.Shape.PathSkew;
4574 update.PathTaperX = data.primShape.PathTaperX; 4531 update.PathTaperX = data.Shape.PathTaperX;
4575 update.PathTaperY = data.primShape.PathTaperY; 4532 update.PathTaperY = data.Shape.PathTaperY;
4576 update.PathTwist = data.primShape.PathTwist; 4533 update.PathTwist = data.Shape.PathTwist;
4577 update.PathTwistBegin = data.primShape.PathTwistBegin; 4534 update.PathTwistBegin = data.Shape.PathTwistBegin;
4578 update.PCode = data.primShape.PCode; 4535 update.PCode = data.Shape.PCode;
4579 update.ProfileBegin = data.primShape.ProfileBegin; 4536 update.ProfileBegin = data.Shape.ProfileBegin;
4580 update.ProfileCurve = data.primShape.ProfileCurve; 4537 update.ProfileCurve = data.Shape.ProfileCurve;
4581 update.ProfileEnd = data.primShape.ProfileEnd; 4538 update.ProfileEnd = data.Shape.ProfileEnd;
4582 update.ProfileHollow = data.primShape.ProfileHollow; 4539 update.ProfileHollow = data.Shape.ProfileHollow;
4583 update.PSBlock = data.particleSystem ?? Utils.EmptyBytes; 4540 update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes;
4584 update.TextColor = data.color ?? Color4.Black.GetBytes(true); 4541 update.TextColor = data.GetTextColor().GetBytes(false);
4585 update.TextureAnim = data.textureanim ?? Utils.EmptyBytes; 4542 update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes;
4586 update.TextureEntry = data.primShape.TextureEntry ?? Utils.EmptyBytes; 4543 update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
4587 update.Scale = data.primShape.Scale; 4544 update.Scale = data.Shape.Scale;
4588 update.Text = Util.StringToBytes256(data.text); 4545 update.Text = Util.StringToBytes256(data.Text);
4589 update.UpdateFlags = (uint)data.flags; 4546
4590 4547 #region PrimFlags
4591 if (data.SoundId != UUID.Zero) 4548
4592 { 4549 PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID);
4593 update.Sound = data.SoundId; 4550
4594 update.OwnerID = data.ownerID; 4551 // Don't send the CreateSelected flag to everyone
4595 update.Gain = (float)data.SoundVolume; 4552 flags &= ~PrimFlags.CreateSelected;
4553
4554 if (recipientID == data.OwnerID)
4555 {
4556 if ((data.Flags & PrimFlags.CreateSelected) != 0)
4557 {
4558 // Only send this flag once, then unset it
4559 flags |= PrimFlags.CreateSelected;
4560 data.Flags &= ~PrimFlags.CreateSelected;
4561 }
4562 }
4563
4564 update.UpdateFlags = (uint)flags;
4565
4566 #endregion PrimFlags
4567
4568 if (data.Sound != UUID.Zero)
4569 {
4570 update.Sound = data.Sound;
4571 update.OwnerID = data.OwnerID;
4572 update.Gain = (float)data.SoundGain;
4596 update.Radius = (float)data.SoundRadius; 4573 update.Radius = (float)data.SoundRadius;
4597 update.Flags = data.SoundFlags; 4574 update.Flags = data.SoundFlags;
4598 } 4575 }
4599 4576
4600 switch ((PCode)data.primShape.PCode) 4577 switch ((PCode)data.Shape.PCode)
4601 { 4578 {
4602 case PCode.Grass: 4579 case PCode.Grass:
4603 case PCode.Tree: 4580 case PCode.Tree:
4604 case PCode.NewTree: 4581 case PCode.NewTree:
4605 update.Data = new byte[] { data.primShape.State }; 4582 update.Data = new byte[] { data.Shape.State };
4606 break; 4583 break;
4607 default: 4584 default:
4608 // TODO: Support ScratchPad
4609 //if (prim.ScratchPad != null)
4610 //{
4611 // update.Data = new byte[prim.ScratchPad.Length];
4612 // Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length);
4613 //}
4614 //else
4615 //{
4616 // update.Data = Utils.EmptyBytes;
4617 //}
4618 update.Data = Utils.EmptyBytes; 4585 update.Data = Utils.EmptyBytes;
4619 break; 4586 break;
4620 } 4587 }
@@ -4622,6 +4589,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4622 return update; 4589 return update;
4623 } 4590 }
4624 4591
4592 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
4593 {
4594 // TODO: Implement this
4595 return null;
4596 }
4597
4625 public void SendNameReply(UUID profileId, string firstname, string lastname) 4598 public void SendNameReply(UUID profileId, string firstname, string lastname)
4626 { 4599 {
4627 UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); 4600 UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
@@ -11644,7 +11617,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11644 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); 11617 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
11645 } 11618 }
11646 11619
11647 internal TValue Dequeue() 11620 internal bool TryDequeue(out TValue value)
11648 { 11621 {
11649 for (int i = 0; i < m_heaps.Length; ++i) 11622 for (int i = 0; i < m_heaps.Length; ++i)
11650 { 11623 {
@@ -11652,10 +11625,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11652 { 11625 {
11653 MinHeapItem item = m_heaps[i].RemoveMin(); 11626 MinHeapItem item = m_heaps[i].RemoveMin();
11654 m_lookupTable.Remove(item.LocalID); 11627 m_lookupTable.Remove(item.LocalID);
11655 return item.Value; 11628 value = item.Value;
11629 return true;
11656 } 11630 }
11657 } 11631 }
11658 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); 11632
11633 value = default(TValue);
11634 return false;
11659 } 11635 }
11660 11636
11661 internal void Reprioritize(UpdatePriorityHandler handler) 11637 internal void Reprioritize(UpdatePriorityHandler handler)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 41e41e4..1b81105 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -99,15 +99,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
99 99
100 /// <summary>The measured resolution of Environment.TickCount</summary> 100 /// <summary>The measured resolution of Environment.TickCount</summary>
101 public readonly float TickCountResolution; 101 public readonly float TickCountResolution;
102 /// <summary>Number of terse prim updates to put on the queue each time the 102 /// <summary>Number of prim updates to put on the queue each time the
103 /// OnQueueEmpty event is triggered for updates</summary> 103 /// OnQueueEmpty event is triggered for updates</summary>
104 public readonly int PrimTerseUpdatesPerPacket; 104 public readonly int PrimUpdatesPerCallback;
105 /// <summary>Number of terse avatar updates to put on the queue each time the
106 /// OnQueueEmpty event is triggered for updates</summary>
107 public readonly int AvatarTerseUpdatesPerPacket;
108 /// <summary>Number of full prim updates to put on the queue each time the
109 /// OnQueueEmpty event is triggered for updates</summary>
110 public readonly int PrimFullUpdatesPerPacket;
111 /// <summary>Number of texture packets to put on the queue each time the 105 /// <summary>Number of texture packets to put on the queue each time the
112 /// OnQueueEmpty event is triggered for textures</summary> 106 /// OnQueueEmpty event is triggered for textures</summary>
113 public readonly int TextureSendLimit; 107 public readonly int TextureSendLimit;
@@ -191,9 +185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
191 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); 185 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
192 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); 186 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
193 187
194 PrimTerseUpdatesPerPacket = config.GetInt("PrimTerseUpdatesPerPacket", 25); 188 PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
195 AvatarTerseUpdatesPerPacket = config.GetInt("AvatarTerseUpdatesPerPacket", 10);
196 PrimFullUpdatesPerPacket = config.GetInt("PrimFullUpdatesPerPacket", 100);
197 TextureSendLimit = config.GetInt("TextureSendLimit", 20); 189 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
198 190
199 m_defaultRTO = config.GetInt("DefaultRTO", 0); 191 m_defaultRTO = config.GetInt("DefaultRTO", 0);
@@ -201,9 +193,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
201 } 193 }
202 else 194 else
203 { 195 {
204 PrimTerseUpdatesPerPacket = 25; 196 PrimUpdatesPerCallback = 100;
205 AvatarTerseUpdatesPerPacket = 10;
206 PrimFullUpdatesPerPacket = 100;
207 TextureSendLimit = 20; 197 TextureSendLimit = 20;
208 } 198 }
209 199
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 6c01927..7d2dc5a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
72 { 72 {
73 m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); 73 m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
74 74
75 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 75 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
76 } 76 }
77 77
78 public void OnNewClient(IClientAPI client) 78 public void OnNewClient(IClientAPI client)
@@ -109,7 +109,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
109 { 109 {
110 // TODO: grab the parcel ID from ILandModule 110 // TODO: grab the parcel ID from ILandModule
111 // and send that along 111 // and send that along
112 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 112 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
113 } 113 }
114 114
115 } 115 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
index d914a57..76e030f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
@@ -162,9 +162,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
162 return m_GridUserService.SetHome(userID, homeID, homePosition, homeLookAt); 162 return m_GridUserService.SetHome(userID, homeID, homePosition, homeLookAt);
163 } 163 }
164 164
165 public bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) 165 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
166 { 166 {
167 return m_GridUserService.SetLastPosition(userID, regionID, lastPosition, lastLookAt); 167 return m_GridUserService.SetLastPosition(userID, sessionID, regionID, lastPosition, lastLookAt);
168 } 168 }
169 169
170 public GridUserInfo GetGridUserInfo(string userID) 170 public GridUserInfo GetGridUserInfo(string userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
index e3e2e61..fb11e9a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
@@ -137,9 +137,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
137 return m_RemoteConnector.SetHome(userID, regionID, position, lookAt); 137 return m_RemoteConnector.SetHome(userID, regionID, position, lookAt);
138 } 138 }
139 139
140 public bool SetLastPosition(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 140 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
141 { 141 {
142 return m_RemoteConnector.SetLastPosition(userID, regionID, position, lookAt); 142 return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt);
143 } 143 }
144 144
145 public GridUserInfo GetGridUserInfo(string userID) 145 public GridUserInfo GetGridUserInfo(string userID)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
index 1fbc733..1ad4db2 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
@@ -154,6 +154,22 @@ namespace OpenSim.Region.CoreModules.World.Land
154 m_landManagementModule.UpdateLandObject(localID, data); 154 m_landManagementModule.UpdateLandObject(localID, data);
155 } 155 }
156 } 156 }
157
158 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
159 {
160 if (m_landManagementModule != null)
161 {
162 m_landManagementModule.Join(start_x, start_y, end_x, end_y, attempting_user_id);
163 }
164 }
165
166 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
167 {
168 if (m_landManagementModule != null)
169 {
170 m_landManagementModule.Subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
171 }
172 }
157 173
158 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 174 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
159 { 175 {
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 139e6ff..4ccd0f0 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -948,6 +948,16 @@ namespace OpenSim.Region.CoreModules.World.Land
948 masterLandObject.SendLandUpdateToAvatarsOverMe(); 948 masterLandObject.SendLandUpdateToAvatarsOverMe();
949 } 949 }
950 950
951 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
952 {
953 join(start_x, start_y, end_x, end_y, attempting_user_id);
954 }
955
956 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
957 {
958 subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
959 }
960
951 #endregion 961 #endregion
952 962
953 #region Parcel Updating 963 #region Parcel Updating
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 09611af..aac47d1 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -528,14 +528,6 @@ namespace OpenSim.Region.Examples.SimpleModule
528 { 528 {
529 } 529 }
530 530
531 public virtual void SendAvatarData(SendAvatarData data)
532 {
533 }
534
535 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
536 {
537 }
538
539 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 531 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
540 { 532 {
541 } 533 }
@@ -548,15 +540,15 @@ namespace OpenSim.Region.Examples.SimpleModule
548 { 540 {
549 } 541 }
550 542
551 public virtual void SendPrimitiveToClient(SendPrimitiveData data) 543 public void SendAvatarDataImmediate(ISceneEntity avatar)
552 { 544 {
553 } 545 }
554 546
555 public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data) 547 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
556 { 548 {
557 } 549 }
558 550
559 public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 551 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
560 { 552 {
561 } 553 }
562 554
diff --git a/OpenSim/Region/Framework/Interfaces/ILandChannel.cs b/OpenSim/Region/Framework/Interfaces/ILandChannel.cs
index f71e31d..20b8ab6 100644
--- a/OpenSim/Region/Framework/Interfaces/ILandChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ILandChannel.cs
@@ -76,5 +76,8 @@ namespace OpenSim.Region.Framework.Interfaces
76 void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel); 76 void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel);
77 void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel); 77 void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel);
78 void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime); 78 void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime);
79
80 void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id);
81 void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id);
79 } 82 }
80} 83}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index ce11267..ef13c98 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -68,8 +68,9 @@ namespace OpenSim.Region.Framework.Scenes
68 68
69 #region Fields 69 #region Fields
70 70
71 protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>(); 71 protected object m_presenceLock = new object();
72 protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0]; 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
73 74
74 // SceneObjects is not currently populated or used. 75 // SceneObjects is not currently populated or used.
75 //public Dictionary<UUID, SceneObjectGroup> SceneObjects; 76 //public Dictionary<UUID, SceneObjectGroup> SceneObjects;
@@ -132,10 +133,12 @@ namespace OpenSim.Region.Framework.Scenes
132 133
133 protected internal void Close() 134 protected internal void Close()
134 { 135 {
135 lock (m_scenePresences) 136 lock (m_presenceLock)
136 { 137 {
137 m_scenePresences.Clear(); 138 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
138 m_scenePresenceArray = new ScenePresence[0]; 139 List<ScenePresence> newlist = new List<ScenePresence>();
140 m_scenePresenceMap = newmap;
141 m_scenePresenceArray = newlist;
139 } 142 }
140 143
141 lock (m_dictionary_lock) 144 lock (m_dictionary_lock)
@@ -518,34 +521,29 @@ namespace OpenSim.Region.Framework.Scenes
518 521
519 Entities[presence.UUID] = presence; 522 Entities[presence.UUID] = presence;
520 523
521 lock (m_scenePresences) 524 lock (m_presenceLock)
522 { 525 {
523 if (!m_scenePresences.ContainsKey(presence.UUID)) 526 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
527 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
528
529 if (!newmap.ContainsKey(presence.UUID))
524 { 530 {
525 m_scenePresences.Add(presence.UUID, presence); 531 newmap.Add(presence.UUID, presence);
526 532 newlist.Add(presence);
527 // Create a new array of ScenePresence references
528 int oldLength = m_scenePresenceArray.Length;
529 ScenePresence[] newArray = new ScenePresence[oldLength + 1];
530 Array.Copy(m_scenePresenceArray, newArray, oldLength);
531 newArray[oldLength] = presence;
532 m_scenePresenceArray = newArray;
533 } 533 }
534 else 534 else
535 { 535 {
536 m_scenePresences[presence.UUID] = presence; 536 // Remember the old presene reference from the dictionary
537 537 ScenePresence oldref = newmap[presence.UUID];
538 // Do a linear search through the array of ScenePresence references 538 // Replace the presence reference in the dictionary with the new value
539 // and update the modified entry 539 newmap[presence.UUID] = presence;
540 for (int i = 0; i < m_scenePresenceArray.Length; i++) 540 // Find the index in the list where the old ref was stored and update the reference
541 { 541 newlist[newlist.IndexOf(oldref)] = presence;
542 if (m_scenePresenceArray[i].UUID == presence.UUID)
543 {
544 m_scenePresenceArray[i] = presence;
545 break;
546 }
547 }
548 } 542 }
543
544 // Swap out the dictionary and list with new references
545 m_scenePresenceMap = newmap;
546 m_scenePresenceArray = newlist;
549 } 547 }
550 } 548 }
551 549
@@ -561,25 +559,21 @@ namespace OpenSim.Region.Framework.Scenes
561 agentID); 559 agentID);
562 } 560 }
563 561
564 lock (m_scenePresences) 562 lock (m_presenceLock)
565 { 563 {
566 if (m_scenePresences.Remove(agentID)) 564 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
565 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
566
567 // Remember the old presene reference from the dictionary
568 ScenePresence oldref = newmap[agentID];
569 // Remove the presence reference from the dictionary
570 if (newmap.Remove(agentID))
567 { 571 {
568 // Copy all of the elements from the previous array 572 // Find the index in the list where the old ref was stored and remove the reference
569 // into the new array except the removed element 573 newlist.RemoveAt(newlist.IndexOf(oldref));
570 int oldLength = m_scenePresenceArray.Length; 574 // Swap out the dictionary and list with new references
571 ScenePresence[] newArray = new ScenePresence[oldLength - 1]; 575 m_scenePresenceMap = newmap;
572 int j = 0; 576 m_scenePresenceArray = newlist;
573 for (int i = 0; i < m_scenePresenceArray.Length; i++)
574 {
575 ScenePresence presence = m_scenePresenceArray[i];
576 if (presence.UUID != agentID)
577 {
578 newArray[j] = presence;
579 ++j;
580 }
581 }
582 m_scenePresenceArray = newArray;
583 } 577 }
584 else 578 else
585 { 579 {
@@ -698,7 +692,7 @@ namespace OpenSim.Region.Framework.Scenes
698 } 692 }
699 693
700 /// <summary> 694 /// <summary>
701 /// Request a copy of m_scenePresences in this World 695 /// Get a reference to the scene presence list. Changes to the list will be done in a copy
702 /// There is no guarantee that presences will remain in the scene after the list is returned. 696 /// There is no guarantee that presences will remain in the scene after the list is returned.
703 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead 697 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
704 /// pass a delegate to ForEachScenePresence. 698 /// pass a delegate to ForEachScenePresence.
@@ -706,8 +700,7 @@ namespace OpenSim.Region.Framework.Scenes
706 /// <returns></returns> 700 /// <returns></returns>
707 private List<ScenePresence> GetScenePresences() 701 private List<ScenePresence> GetScenePresences()
708 { 702 {
709 lock (m_scenePresences) 703 return m_scenePresenceArray;
710 return new List<ScenePresence>(m_scenePresenceArray);
711 } 704 }
712 705
713 /// <summary> 706 /// <summary>
@@ -717,12 +710,10 @@ namespace OpenSim.Region.Framework.Scenes
717 /// <returns>null if the presence was not found</returns> 710 /// <returns>null if the presence was not found</returns>
718 protected internal ScenePresence GetScenePresence(UUID agentID) 711 protected internal ScenePresence GetScenePresence(UUID agentID)
719 { 712 {
720 ScenePresence sp; 713 Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
721 lock (m_scenePresences) 714 ScenePresence presence;
722 { 715 presences.TryGetValue(agentID, out presence);
723 m_scenePresences.TryGetValue(agentID, out sp); 716 return presence;
724 }
725 return sp;
726 } 717 }
727 718
728 /// <summary> 719 /// <summary>
@@ -733,7 +724,8 @@ namespace OpenSim.Region.Framework.Scenes
733 /// <returns>null if the presence was not found</returns> 724 /// <returns>null if the presence was not found</returns>
734 protected internal ScenePresence GetScenePresence(string firstName, string lastName) 725 protected internal ScenePresence GetScenePresence(string firstName, string lastName)
735 { 726 {
736 foreach (ScenePresence presence in GetScenePresences()) 727 List<ScenePresence> presences = GetScenePresences();
728 foreach (ScenePresence presence in presences)
737 { 729 {
738 if (presence.Firstname == firstName && presence.Lastname == lastName) 730 if (presence.Firstname == firstName && presence.Lastname == lastName)
739 return presence; 731 return presence;
@@ -748,7 +740,8 @@ namespace OpenSim.Region.Framework.Scenes
748 /// <returns>null if the presence was not found</returns> 740 /// <returns>null if the presence was not found</returns>
749 protected internal ScenePresence GetScenePresence(uint localID) 741 protected internal ScenePresence GetScenePresence(uint localID)
750 { 742 {
751 foreach (ScenePresence presence in GetScenePresences()) 743 List<ScenePresence> presences = GetScenePresences();
744 foreach (ScenePresence presence in presences)
752 if (presence.LocalId == localID) 745 if (presence.LocalId == localID)
753 return presence; 746 return presence;
754 return null; 747 return null;
@@ -756,10 +749,8 @@ namespace OpenSim.Region.Framework.Scenes
756 749
757 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) 750 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar)
758 { 751 {
759 lock (m_scenePresences) 752 Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
760 { 753 presences.TryGetValue(agentID, out avatar);
761 m_scenePresences.TryGetValue(agentID, out avatar);
762 }
763 return (avatar != null); 754 return (avatar != null);
764 } 755 }
765 756
@@ -1036,8 +1027,9 @@ namespace OpenSim.Region.Framework.Scenes
1036 }); 1027 });
1037 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction); 1028 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
1038 */ 1029 */
1039 // For now, perform actiona serially 1030 // For now, perform actions serially
1040 foreach (ScenePresence sp in GetScenePresences()) 1031 List<ScenePresence> presences = GetScenePresences();
1032 foreach (ScenePresence sp in presences)
1041 { 1033 {
1042 try 1034 try
1043 { 1035 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 46eadee..71c8018 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -104,7 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
104 104
105 #endregion Enumerations 105 #endregion Enumerations
106 106
107 public class SceneObjectPart : IScriptHost 107 public class SceneObjectPart : IScriptHost, ISceneEntity
108 { 108 {
109 /// <value> 109 /// <value>
110 /// Denote all sides of the prim 110 /// Denote all sides of the prim
@@ -712,6 +712,24 @@ namespace OpenSim.Region.Framework.Scenes
712 } 712 }
713 } 713 }
714 714
715 public Vector3 RelativePosition
716 {
717 get
718 {
719 if (IsRoot)
720 {
721 if (IsAttachment)
722 return AttachedPos;
723 else
724 return AbsolutePosition;
725 }
726 else
727 {
728 return OffsetPosition;
729 }
730 }
731 }
732
715 public Quaternion RotationOffset 733 public Quaternion RotationOffset
716 { 734 {
717 get 735 get
@@ -973,7 +991,6 @@ namespace OpenSim.Region.Framework.Scenes
973 get { return AggregateScriptEvents; } 991 get { return AggregateScriptEvents; }
974 } 992 }
975 993
976
977 public Quaternion SitTargetOrientation 994 public Quaternion SitTargetOrientation
978 { 995 {
979 get { return m_sitTargetOrientation; } 996 get { return m_sitTargetOrientation; }
@@ -2925,11 +2942,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 //if (LocalId != ParentGroup.RootPart.LocalId) 2942 //if (LocalId != ParentGroup.RootPart.LocalId)
2926 //isattachment = ParentGroup.RootPart.IsAttachment; 2943 //isattachment = ParentGroup.RootPart.IsAttachment;
2927 2944
2928 byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A}; 2945 remoteClient.SendPrimUpdate(this, PrimUpdateFlags.FullUpdate);
2929 remoteClient.SendPrimitiveToClient(new SendPrimitiveData(m_regionHandle, m_parentGroup.GetTimeDilation(), LocalId, m_shape,
2930 lPos, Velocity, Acceleration, RotationOffset, AngularVelocity, clientFlags, m_uuid, _ownerID,
2931 m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment,
2932 AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius, ParentGroup.GetUpdatePriority(remoteClient)));
2933 } 2946 }
2934 2947
2935 /// <summary> 2948 /// <summary>
@@ -4640,11 +4653,7 @@ namespace OpenSim.Region.Framework.Scenes
4640 4653
4641 // Causes this thread to dig into the Client Thread Data. 4654 // Causes this thread to dig into the Client Thread Data.
4642 // Remember your locking here! 4655 // Remember your locking here!
4643 remoteClient.SendPrimTerseUpdate(new SendPrimitiveTerseData(m_regionHandle, 4656 remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
4644 m_parentGroup.GetTimeDilation(), LocalId, lPos,
4645 RotationOffset, Velocity, Acceleration,
4646 AngularVelocity, FromItemID,
4647 OwnerID, (int)AttachmentPoint, null, ParentGroup.GetUpdatePriority(remoteClient)));
4648 } 4657 }
4649 4658
4650 public void AddScriptLPS(int count) 4659 public void AddScriptLPS(int count)
@@ -4694,7 +4703,8 @@ namespace OpenSim.Region.Framework.Scenes
4694 4703
4695 public Color4 GetTextColor() 4704 public Color4 GetTextColor()
4696 { 4705 {
4697 return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A)); 4706 Color color = Color;
4707 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4698 } 4708 }
4699 } 4709 }
4700} 4710}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 30eafd7..ee0eb07 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Scenes
67 67
68 public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence); 68 public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence);
69 69
70 public class ScenePresence : EntityBase 70 public class ScenePresence : EntityBase, ISceneEntity
71 { 71 {
72// ~ScenePresence() 72// ~ScenePresence()
73// { 73// {
@@ -478,6 +478,12 @@ namespace OpenSim.Region.Framework.Scenes
478 } 478 }
479 } 479 }
480 480
481 public Vector3 OffsetPosition
482 {
483 get { return m_pos; }
484 set { m_pos = value; }
485 }
486
481 /// <summary> 487 /// <summary>
482 /// Current velocity of the avatar. 488 /// Current velocity of the avatar.
483 /// </summary> 489 /// </summary>
@@ -1036,8 +1042,9 @@ namespace OpenSim.Region.Framework.Scenes
1036 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1042 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
1037 } 1043 }
1038 1044
1039 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1045 ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position);
1040 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1046 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
1047 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1041 } 1048 }
1042 1049
1043 public void AddNeighbourRegion(ulong regionHandle, string cap) 1050 public void AddNeighbourRegion(ulong regionHandle, string cap)
@@ -2360,8 +2367,7 @@ namespace OpenSim.Region.Framework.Scenes
2360 2367
2361 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); 2368 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
2362 2369
2363 remoteClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 2370 remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
2364 pos, velocity, Vector3.Zero, m_bodyRot, CollisionPlane, m_uuid, null, GetUpdatePriority(remoteClient)));
2365 2371
2366 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2372 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2367 m_scene.StatsReporter.AddAgentUpdates(1); 2373 m_scene.StatsReporter.AddAgentUpdates(1);
@@ -2457,9 +2463,7 @@ namespace OpenSim.Region.Framework.Scenes
2457 Vector3 pos = m_pos; 2463 Vector3 pos = m_pos;
2458 pos.Z += m_appearance.HipOffset; 2464 pos.Z += m_appearance.HipOffset;
2459 2465
2460 remoteAvatar.m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, 2466 remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this);
2461 LocalId, pos, m_appearance.Texture.GetBytes(),
2462 m_parentID, m_bodyRot));
2463 m_scene.StatsReporter.AddAgentUpdates(1); 2467 m_scene.StatsReporter.AddAgentUpdates(1);
2464 } 2468 }
2465 2469
@@ -2527,8 +2531,7 @@ namespace OpenSim.Region.Framework.Scenes
2527 Vector3 pos = m_pos; 2531 Vector3 pos = m_pos;
2528 pos.Z += m_appearance.HipOffset; 2532 pos.Z += m_appearance.HipOffset;
2529 2533
2530 m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, 2534 m_controllingClient.SendAvatarDataImmediate(this);
2531 pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
2532 2535
2533 SendInitialFullUpdateToAllClients(); 2536 SendInitialFullUpdateToAllClients();
2534 SendAppearanceToAllOtherAgents(); 2537 SendAppearanceToAllOtherAgents();
@@ -2638,9 +2641,7 @@ namespace OpenSim.Region.Framework.Scenes
2638 Vector3 pos = m_pos; 2641 Vector3 pos = m_pos;
2639 pos.Z += m_appearance.HipOffset; 2642 pos.Z += m_appearance.HipOffset;
2640 2643
2641 m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, 2644 m_controllingClient.SendAvatarDataImmediate(this);
2642 pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
2643
2644 } 2645 }
2645 2646
2646 public void SetWearable(int wearableId, AvatarWearable wearable) 2647 public void SetWearable(int wearableId, AvatarWearable wearable)
@@ -3906,7 +3907,7 @@ namespace OpenSim.Region.Framework.Scenes
3906 3907
3907 private void Reprioritize(object sender, ElapsedEventArgs e) 3908 private void Reprioritize(object sender, ElapsedEventArgs e)
3908 { 3909 {
3909 m_controllingClient.ReprioritizeUpdates(StateUpdateTypes.All, UpdatePriority); 3910 m_controllingClient.ReprioritizeUpdates(UpdatePriority);
3910 3911
3911 lock (m_reprioritization_timer) 3912 lock (m_reprioritization_timer)
3912 { 3913 {
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 69e78b3..84faac0 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1045,16 +1045,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1045 1045
1046 } 1046 }
1047 1047
1048 public void SendAvatarData(SendAvatarData data)
1049 {
1050
1051 }
1052
1053 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
1054 {
1055
1056 }
1057
1058 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 1048 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
1059 { 1049 {
1060 1050
@@ -1065,32 +1055,27 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1065 1055
1066 } 1056 }
1067 1057
1068 public void SetChildAgentThrottle(byte[] throttle) 1058 public void SendAvatarDataImmediate(ISceneEntity avatar)
1069 { 1059 {
1070
1071 }
1072 1060
1073 public void SendPrimitiveToClient(SendPrimitiveData data)
1074 {
1075
1076 } 1061 }
1077 1062
1078 public void SendPrimTerseUpdate(SendPrimitiveTerseData data) 1063 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
1079 { 1064 {
1080 1065
1081 } 1066 }
1082 1067
1083 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 1068 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
1084 { 1069 {
1085 1070
1086 } 1071 }
1087 1072
1088 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems) 1073 public void FlushPrimUpdates()
1089 { 1074 {
1090 1075
1091 } 1076 }
1092 1077
1093 public void FlushPrimUpdates() 1078 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems)
1094 { 1079 {
1095 1080
1096 } 1081 }
@@ -1420,6 +1405,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1420 1405
1421 } 1406 }
1422 1407
1408 public virtual void SetChildAgentThrottle(byte[] throttle)
1409 {
1410
1411 }
1412
1423 public byte[] GetThrottlesPacked(float multiplier) 1413 public byte[] GetThrottlesPacked(float multiplier)
1424 { 1414 {
1425 return new byte[0]; 1415 return new byte[0];
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 6360c99..9066691 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -618,14 +618,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
618 { 618 {
619 } 619 }
620 620
621 public virtual void SendAvatarData(SendAvatarData data)
622 {
623 }
624
625 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
626 {
627 }
628
629 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 621 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
630 { 622 {
631 } 623 }
@@ -638,15 +630,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
638 { 630 {
639 } 631 }
640 632
641 public virtual void SendPrimitiveToClient(SendPrimitiveData data) 633 public void SendAvatarDataImmediate(ISceneEntity avatar)
642 { 634 {
643 } 635 }
644 636
645 public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data) 637 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
646 { 638 {
647 } 639 }
648 640
649 public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 641 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
650 { 642 {
651 } 643 }
652 644
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
index 9da818a..33ff707 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
@@ -140,6 +140,16 @@ public class RegionCombinerLargeLandChannel : ILandChannel
140 RootRegionLandChannel.UpdateLandObject(localID, data); 140 RootRegionLandChannel.UpdateLandObject(localID, data);
141 } 141 }
142 142
143 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
144 {
145 RootRegionLandChannel.Join(start_x, start_y, end_x, end_y, attempting_user_id);
146 }
147
148 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
149 {
150 RootRegionLandChannel.Subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
151 }
152
143 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 153 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
144 { 154 {
145 RootRegionLandChannel.ReturnObjectsInParcel(localID, returnType, agentIDs, taskIDs, remoteClient); 155 RootRegionLandChannel.ReturnObjectsInParcel(localID, returnType, agentIDs, taskIDs, remoteClient);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 7e68cc7..15469db 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -1129,7 +1129,89 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1129 return 0.0f; 1129 return 0.0f;
1130 } 1130 }
1131 1131
1132 // Routines for creating and managing parcels programmatically
1133 public void osParcelJoin(LSL_Vector pos1, LSL_Vector pos2)
1134 {
1135 CheckThreatLevel(ThreatLevel.High, "osParcelJoin");
1136 m_host.AddScriptLPS(1);
1137
1138 int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x);
1139 int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y);
1140 int endx = (int)(pos1.x > pos2.x ? pos1.x : pos2.x);
1141 int endy = (int)(pos1.y > pos2.y ? pos1.y : pos2.y);
1142
1143 World.LandChannel.Join(startx,starty,endx,endy,m_host.OwnerID);
1144 }
1145
1146 public void osParcelSubdivide(LSL_Vector pos1, LSL_Vector pos2)
1147 {
1148 CheckThreatLevel(ThreatLevel.High, "osParcelSubdivide");
1149 m_host.AddScriptLPS(1);
1150
1151 int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x);
1152 int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y);
1153 int endx = (int)(pos1.x > pos2.x ? pos1.x : pos2.x);
1154 int endy = (int)(pos1.y > pos2.y ? pos1.y : pos2.y);
1132 1155
1156 World.LandChannel.Subdivide(startx,starty,endx,endy,m_host.OwnerID);
1157 }
1158
1159 public void osParcelSetDetails(LSL_Vector pos, LSL_List rules)
1160 {
1161 CheckThreatLevel(ThreatLevel.High, "osParcelSetDetails");
1162 m_host.AddScriptLPS(1);
1163
1164 // Get a reference to the land data and make sure the owner of the script
1165 // can modify it
1166
1167 ILandObject startLandObject = World.LandChannel.GetLandObject((int)pos.x, (int)pos.y);
1168 if (startLandObject == null)
1169 {
1170 OSSLShoutError("There is no land at that location");
1171 return;
1172 }
1173
1174 if (! World.Permissions.CanEditParcel(m_host.OwnerID, startLandObject))
1175 {
1176 OSSLShoutError("You do not have permission to modify the parcel");
1177 return;
1178 }
1179
1180 // Create a new land data object we can modify
1181 LandData newLand = startLandObject.LandData.Copy();
1182 UUID uuid;
1183
1184 // Process the rules, not sure what the impact would be of changing owner or group
1185 for (int idx = 0; idx < rules.Length; )
1186 {
1187 int code = rules.GetLSLIntegerItem(idx++);
1188 string arg = rules.GetLSLStringItem(idx++);
1189 switch (code)
1190 {
1191 case 0:
1192 newLand.Name = arg;
1193 break;
1194
1195 case 1:
1196 newLand.Description = arg;
1197 break;
1198
1199 case 2:
1200 CheckThreatLevel(ThreatLevel.VeryHigh, "osParcelSetDetails");
1201 if (UUID.TryParse(arg , out uuid))
1202 newLand.OwnerID = uuid;
1203 break;
1204
1205 case 3:
1206 CheckThreatLevel(ThreatLevel.VeryHigh, "osParcelSetDetails");
1207 if (UUID.TryParse(arg , out uuid))
1208 newLand.GroupID = uuid;
1209 break;
1210 }
1211 }
1212
1213 World.LandChannel.UpdateLandObject(newLand.LocalID,newLand);
1214 }
1133 1215
1134 public double osList2Double(LSL_Types.list src, int index) 1216 public double osList2Double(LSL_Types.list src, int index)
1135 { 1217 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 60b8050..7a8f469 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -123,6 +123,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
123 void osWindParamSet(string plugin, string param, float value); 123 void osWindParamSet(string plugin, string param, float value);
124 float osWindParamGet(string plugin, string param); 124 float osWindParamGet(string plugin, string param);
125 125
126 // Parcel commands
127 void osParcelJoin(vector pos1, vector pos2);
128 void osParcelSubdivide(vector pos1, vector pos2);
129 void osParcelSetDetails(vector pos, LSL_List rules);
126 130
127 string osGetScriptEngineName(); 131 string osGetScriptEngineName();
128 string osGetSimulatorVersion(); 132 string osGetSimulatorVersion();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 3870af3..fd9309a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -106,6 +106,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
106// return m_OSSL_Functions.osWindParamGet(plugin, param); 106// return m_OSSL_Functions.osWindParamGet(plugin, param);
107// } 107// }
108 108
109 public void osParcelJoin(vector pos1, vector pos2)
110 {
111 m_OSSL_Functions.osParcelJoin(pos1,pos2);
112 }
113
114 public void osParcelSubdivide(vector pos1, vector pos2)
115 {
116 m_OSSL_Functions.osParcelSubdivide(pos1, pos2);
117 }
118
119 public void osParcelSetDetails(vector pos, LSL_List rules)
120 {
121 m_OSSL_Functions.osParcelSetDetails(pos,rules);
122 }
123
109 public double osList2Double(LSL_Types.list src, int index) 124 public double osList2Double(LSL_Types.list src, int index)
110 { 125 {
111 return m_OSSL_Functions.osList2Double(src, index); 126 return m_OSSL_Functions.osList2Double(src, index);
diff --git a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
index f8fa429..b1e7eac 100644
--- a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
@@ -156,6 +156,7 @@ namespace OpenSim.Server.Handlers.GridUser
156 byte[] SetPosition(Dictionary<string, object> request) 156 byte[] SetPosition(Dictionary<string, object> request)
157 { 157 {
158 string user = string.Empty; 158 string user = string.Empty;
159 UUID sessionID = UUID.Zero;
159 UUID region = UUID.Zero; 160 UUID region = UUID.Zero;
160 Vector3 position = new Vector3(128, 128, 70); 161 Vector3 position = new Vector3(128, 128, 70);
161 Vector3 look = Vector3.Zero; 162 Vector3 look = Vector3.Zero;
@@ -166,7 +167,7 @@ namespace OpenSim.Server.Handlers.GridUser
166 if (!UnpackArgs(request, out user, out region, out position, out look)) 167 if (!UnpackArgs(request, out user, out region, out position, out look))
167 return FailureResult(); 168 return FailureResult();
168 169
169 if (m_GridUserService.SetLastPosition(user, region, position, look)) 170 if (m_GridUserService.SetLastPosition(user, sessionID, region, position, look))
170 return SuccessResult(); 171 return SuccessResult();
171 172
172 return FailureResult(); 173 return FailureResult();
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
index b4500a5..f222e31 100644
--- a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
+++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
@@ -123,7 +123,7 @@ namespace OpenSim.Services.Connectors
123 return Set(sendData, userID, regionID, position, lookAt); 123 return Set(sendData, userID, regionID, position, lookAt);
124 } 124 }
125 125
126 public bool SetLastPosition(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 126 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
127 { 127 {
128 Dictionary<string, object> sendData = new Dictionary<string, object>(); 128 Dictionary<string, object> sendData = new Dictionary<string, object>();
129 //sendData["SCOPEID"] = scopeID.ToString(); 129 //sendData["SCOPEID"] = scopeID.ToString();
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
new file mode 100644
index 0000000..8cc5671
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
@@ -0,0 +1,113 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Services.Interfaces;
34using OpenMetaverse;
35using log4net;
36
37namespace OpenSim.Services.Connectors.SimianGrid
38{
39 public class SimianActivityDetector
40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 private IGridUserService m_GridUserService;
44 private Scene m_aScene;
45
46 public SimianActivityDetector(IGridUserService guservice)
47 {
48 m_GridUserService = guservice;
49 m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Started");
50 }
51
52 public void AddRegion(Scene scene)
53 {
54 // For now the only events we listen to are these
55 // But we could trigger the position update more often
56 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
57 scene.EventManager.OnNewClient += OnNewClient;
58 scene.EventManager.OnAvatarEnteringNewParcel += OnEnteringNewParcel;
59
60 if (m_aScene == null)
61 m_aScene = scene;
62 }
63
64 public void RemoveRegion(Scene scene)
65 {
66 scene.EventManager.OnMakeRootAgent -= OnMakeRootAgent;
67 scene.EventManager.OnNewClient -= OnNewClient;
68 scene.EventManager.OnAvatarEnteringNewParcel -= OnEnteringNewParcel;
69 }
70
71 public void OnMakeRootAgent(ScenePresence sp)
72 {
73 m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
74 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
75 }
76
77 public void OnNewClient(IClientAPI client)
78 {
79 client.OnConnectionClosed += OnConnectionClose;
80 }
81
82 public void OnConnectionClose(IClientAPI client)
83 {
84 if (client.IsLoggingOut)
85 {
86 object sp = null;
87 Vector3 position = new Vector3(128, 128, 0);
88 Vector3 lookat = new Vector3(0, 1, 0);
89
90 if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
91 {
92 if (sp is ScenePresence)
93 {
94 if (((ScenePresence)sp).IsChildAgent)
95 return;
96
97 position = ((ScenePresence)sp).AbsolutePosition;
98 lookat = ((ScenePresence)sp).Lookat;
99 }
100 }
101
102 m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
103 m_GridUserService.LoggedOut(client.AgentId.ToString(), client.Scene.RegionInfo.RegionID, position, lookat);
104 }
105
106 }
107
108 void OnEnteringNewParcel(ScenePresence sp, int localLandID, UUID regionID)
109 {
110 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
111 }
112 }
113}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
index b86c45c..ec9cf67 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
@@ -58,6 +58,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
58 MethodBase.GetCurrentMethod().DeclaringType); 58 MethodBase.GetCurrentMethod().DeclaringType);
59 59
60 private string m_serverUrl = String.Empty; 60 private string m_serverUrl = String.Empty;
61 private SimianActivityDetector m_activityDetector;
61 62
62 #region ISharedRegionModule 63 #region ISharedRegionModule
63 64
@@ -66,7 +67,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
66 public void PostInitialise() { } 67 public void PostInitialise() { }
67 public void Close() { } 68 public void Close() { }
68 69
69 public SimianPresenceServiceConnector() { } 70 public SimianPresenceServiceConnector() { m_activityDetector = new SimianActivityDetector(this); }
70 public string Name { get { return "SimianPresenceServiceConnector"; } } 71 public string Name { get { return "SimianPresenceServiceConnector"; } }
71 public void AddRegion(Scene scene) 72 public void AddRegion(Scene scene)
72 { 73 {
@@ -75,9 +76,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
75 scene.RegisterModuleInterface<IPresenceService>(this); 76 scene.RegisterModuleInterface<IPresenceService>(this);
76 scene.RegisterModuleInterface<IGridUserService>(this); 77 scene.RegisterModuleInterface<IGridUserService>(this);
77 78
78 scene.EventManager.OnMakeRootAgent += MakeRootAgentHandler; 79 m_activityDetector.AddRegion(scene);
79 scene.EventManager.OnNewClient += NewClientHandler;
80 scene.EventManager.OnSignificantClientMovement += SignificantClientMovementHandler;
81 80
82 LogoutRegionAgents(scene.RegionInfo.RegionID); 81 LogoutRegionAgents(scene.RegionInfo.RegionID);
83 } 82 }
@@ -89,9 +88,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
89 scene.UnregisterModuleInterface<IPresenceService>(this); 88 scene.UnregisterModuleInterface<IPresenceService>(this);
90 scene.UnregisterModuleInterface<IGridUserService>(this); 89 scene.UnregisterModuleInterface<IGridUserService>(this);
91 90
92 scene.EventManager.OnMakeRootAgent -= MakeRootAgentHandler; 91 m_activityDetector.RemoveRegion(scene);
93 scene.EventManager.OnNewClient -= NewClientHandler;
94 scene.EventManager.OnSignificantClientMovement -= SignificantClientMovementHandler;
95 92
96 LogoutRegionAgents(scene.RegionInfo.RegionID); 93 LogoutRegionAgents(scene.RegionInfo.RegionID);
97 } 94 }
@@ -193,29 +190,8 @@ namespace OpenSim.Services.Connectors.SimianGrid
193 190
194 public bool ReportAgent(UUID sessionID, UUID regionID) 191 public bool ReportAgent(UUID sessionID, UUID regionID)
195 { 192 {
196 return ReportAgent(sessionID, regionID, Vector3.Zero, Vector3.Zero); 193 // Not needed for SimianGrid
197 } 194 return true;
198
199 protected bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
200 {
201 //m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Updating session data for agent with sessionID " + sessionID);
202
203 NameValueCollection requestArgs = new NameValueCollection
204 {
205 { "RequestMethod", "UpdateSession" },
206 { "SessionID", sessionID.ToString() },
207 { "SceneID", regionID.ToString() },
208 { "ScenePosition", position.ToString() },
209 { "SceneLookAt", lookAt.ToString() }
210 };
211
212 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
213 bool success = response["Success"].AsBoolean();
214
215 if (!success)
216 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to update agent session " + sessionID + ": " + response["Message"].AsString());
217
218 return success;
219 } 195 }
220 196
221 public PresenceInfo GetAgent(UUID sessionID) 197 public PresenceInfo GetAgent(UUID sessionID)
@@ -274,14 +250,27 @@ namespace OpenSim.Services.Connectors.SimianGrid
274 250
275 public GridUserInfo LoggedIn(string userID) 251 public GridUserInfo LoggedIn(string userID)
276 { 252 {
277 // never implemented at the sim 253 // Never implemented at the sim
278 return null; 254 return null;
279 } 255 }
280 256
281 public bool LoggedOut(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) 257 public bool LoggedOut(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
282 { 258 {
283 // Not needed for simian grid, event handler is doing it 259 // Save our last position as user data
284 return true; 260 NameValueCollection requestArgs = new NameValueCollection
261 {
262 { "RequestMethod", "AddUserData" },
263 { "UserID", userID.ToString() },
264 { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) }
265 };
266
267 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
268 bool success = response["Success"].AsBoolean();
269
270 if (!success)
271 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to set last location for " + userID + ": " + response["Message"].AsString());
272
273 return success;
285 } 274 }
286 275
287 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 276 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
@@ -304,10 +293,9 @@ namespace OpenSim.Services.Connectors.SimianGrid
304 return success; 293 return success;
305 } 294 }
306 295
307 public bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) 296 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
308 { 297 {
309 // Not needed for simian grid, presence detection is doing it 298 return UpdateSession(sessionID, regionID, lastPosition, lastLookAt);
310 return true;
311 } 299 }
312 300
313 public GridUserInfo GetGridUserInfo(string user) 301 public GridUserInfo GetGridUserInfo(string user)
@@ -334,54 +322,6 @@ namespace OpenSim.Services.Connectors.SimianGrid
334 322
335 #endregion 323 #endregion
336 324
337 #region Presence Detection
338
339 private void MakeRootAgentHandler(ScenePresence sp)
340 {
341 m_log.DebugFormat("[PRESENCE DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
342
343 ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
344 SetLastLocation(sp.UUID, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
345 }
346
347 private void NewClientHandler(IClientAPI client)
348 {
349 client.OnConnectionClosed += LogoutHandler;
350 }
351
352 private void SignificantClientMovementHandler(IClientAPI client)
353 {
354 ScenePresence sp;
355 if (client.Scene is Scene && ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out sp))
356 ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
357 }
358
359 private void LogoutHandler(IClientAPI client)
360 {
361 if (client.IsLoggingOut)
362 {
363 client.OnConnectionClosed -= LogoutHandler;
364
365 object obj;
366 if (client.Scene.TryGetScenePresence(client.AgentId, out obj) && obj is ScenePresence)
367 {
368 // The avatar is still in the scene, we can get the exact logout position
369 ScenePresence sp = (ScenePresence)obj;
370 SetLastLocation(client.AgentId, client.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
371 }
372 else
373 {
374 // The avatar was already removed from the scene, store LastLocation using the most recent session data
375 m_log.Warn("[PRESENCE]: " + client.Name + " has already been removed from the scene, storing approximate LastLocation");
376 SetLastLocation(client.SessionId);
377 }
378
379 LogoutAgent(client.SessionId);
380 }
381 }
382
383 #endregion Presence Detection
384
385 #region Helpers 325 #region Helpers
386 326
387 private OSDMap GetUserData(UUID userID) 327 private OSDMap GetUserData(UUID userID)
@@ -453,57 +393,60 @@ namespace OpenSim.Services.Connectors.SimianGrid
453 return presences; 393 return presences;
454 } 394 }
455 395
456 /// <summary> 396 private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
457 /// Fetch the last known avatar location with GetSession and persist it
458 /// as user data with AddUserData
459 /// </summary>
460 private bool SetLastLocation(UUID sessionID)
461 { 397 {
398 // Save our current location as session data
462 NameValueCollection requestArgs = new NameValueCollection 399 NameValueCollection requestArgs = new NameValueCollection
463 { 400 {
464 { "RequestMethod", "GetSession" }, 401 { "RequestMethod", "UpdateSession" },
465 { "SessionID", sessionID.ToString() } 402 { "SessionID", sessionID.ToString() },
403 { "SceneID", regionID.ToString() },
404 { "ScenePosition", lastPosition.ToString() },
405 { "SceneLookAt", lastLookAt.ToString() }
466 }; 406 };
467 407
468 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 408 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
469 bool success = response["Success"].AsBoolean(); 409 bool success = response["Success"].AsBoolean();
470 410
471 if (success)
472 {
473 UUID userID = response["UserID"].AsUUID();
474 UUID sceneID = response["SceneID"].AsUUID();
475 Vector3 position = response["ScenePosition"].AsVector3();
476 Vector3 lookAt = response["SceneLookAt"].AsVector3();
477
478 return SetLastLocation(userID, sceneID, position, lookAt);
479 }
480 else
481 {
482 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve presence information for session " + sessionID +
483 " while saving last location: " + response["Message"].AsString());
484 }
485
486 return success;
487 }
488
489 private bool SetLastLocation(UUID userID, UUID sceneID, Vector3 position, Vector3 lookAt)
490 {
491 NameValueCollection requestArgs = new NameValueCollection
492 {
493 { "RequestMethod", "AddUserData" },
494 { "UserID", userID.ToString() },
495 { "LastLocation", SerializeLocation(sceneID, position, lookAt) }
496 };
497
498 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
499 bool success = response["Success"].AsBoolean();
500
501 if (!success) 411 if (!success)
502 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to set last location for " + userID + ": " + response["Message"].AsString()); 412 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to update agent session " + sessionID + ": " + response["Message"].AsString());
503 413
504 return success; 414 return success;
505 } 415 }
506 416
417 ///// <summary>
418 ///// Fetch the last known avatar location with GetSession and persist it
419 ///// as user data with AddUserData
420 ///// </summary>
421 //private bool SetLastLocation(UUID sessionID)
422 //{
423 // NameValueCollection requestArgs = new NameValueCollection
424 // {
425 // { "RequestMethod", "GetSession" },
426 // { "SessionID", sessionID.ToString() }
427 // };
428
429 // OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
430 // bool success = response["Success"].AsBoolean();
431
432 // if (success)
433 // {
434 // UUID userID = response["UserID"].AsUUID();
435 // UUID sceneID = response["SceneID"].AsUUID();
436 // Vector3 position = response["ScenePosition"].AsVector3();
437 // Vector3 lookAt = response["SceneLookAt"].AsVector3();
438
439 // return SetLastLocation(userID, sceneID, position, lookAt);
440 // }
441 // else
442 // {
443 // m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve presence information for session " + sessionID +
444 // " while saving last location: " + response["Message"].AsString());
445 // }
446
447 // return success;
448 //}
449
507 private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse) 450 private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse)
508 { 451 {
509 if (sessionResponse == null) 452 if (sessionResponse == null)
diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs
index e629dff..3d11b3e 100644
--- a/OpenSim/Services/Interfaces/IGridUserService.cs
+++ b/OpenSim/Services/Interfaces/IGridUserService.cs
@@ -108,7 +108,7 @@ namespace OpenSim.Services.Interfaces
108 bool LoggedOut(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt); 108 bool LoggedOut(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt);
109 109
110 bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt); 110 bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt);
111 bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt); 111 bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt);
112 112
113 GridUserInfo GetGridUserInfo(string userID); 113 GridUserInfo GetGridUserInfo(string userID);
114 } 114 }
diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs
index 697ba63..00a1ae2 100644
--- a/OpenSim/Services/UserAccountService/GridUserService.cs
+++ b/OpenSim/Services/UserAccountService/GridUserService.cs
@@ -139,7 +139,7 @@ namespace OpenSim.Services.UserAccountService
139 return m_Database.Store(d); 139 return m_Database.Store(d);
140 } 140 }
141 141
142 public bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) 142 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
143 { 143 {
144 //m_log.DebugFormat("[Grid User Service]: SetLastPosition for {0}", userID); 144 //m_log.DebugFormat("[Grid User Service]: SetLastPosition for {0}", userID);
145 GridUserData d = m_Database.Get(userID); 145 GridUserData d = m_Database.Get(userID);
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index b07a072..edb7642 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -621,14 +621,6 @@ namespace OpenSim.Tests.Common.Mock
621 { 621 {
622 } 622 }
623 623
624 public virtual void SendAvatarData(SendAvatarData data)
625 {
626 }
627
628 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
629 {
630 }
631
632 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 624 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
633 { 625 {
634 } 626 }
@@ -641,15 +633,15 @@ namespace OpenSim.Tests.Common.Mock
641 { 633 {
642 } 634 }
643 635
644 public virtual void SendPrimitiveToClient(SendPrimitiveData data) 636 public void SendAvatarDataImmediate(ISceneEntity avatar)
645 { 637 {
646 } 638 }
647 639
648 public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data) 640 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
649 { 641 {
650 } 642 }
651 643
652 public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 644 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
653 { 645 {
654 } 646 }
655 647
diff --git a/OpenSim/Tests/Common/Mock/TestLandChannel.cs b/OpenSim/Tests/Common/Mock/TestLandChannel.cs
index be28c27..159764c 100644
--- a/OpenSim/Tests/Common/Mock/TestLandChannel.cs
+++ b/OpenSim/Tests/Common/Mock/TestLandChannel.cs
@@ -85,5 +85,9 @@ namespace OpenSim.Tests.Common.Mock
85 public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) {} 85 public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) {}
86 public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) {} 86 public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) {}
87 public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) {} 87 public void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) {}
88
89 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) {}
90 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) {}
91
88 } 92 }
89} 93}