diff options
author | John Hurliman | 2009-10-29 15:24:31 -0700 |
---|---|---|
committer | John Hurliman | 2009-10-29 15:24:31 -0700 |
commit | 2913c24c8a5a4a50e9267aa125abcc7956a388d1 (patch) | |
tree | f1556d66cea9f8198a317960de93798ab6718a69 /OpenSim/Region/Framework/Scenes | |
parent | More performance improvements to XEngine script loading (diff) | |
download | opensim-SC_OLD-2913c24c8a5a4a50e9267aa125abcc7956a388d1.zip opensim-SC_OLD-2913c24c8a5a4a50e9267aa125abcc7956a388d1.tar.gz opensim-SC_OLD-2913c24c8a5a4a50e9267aa125abcc7956a388d1.tar.bz2 opensim-SC_OLD-2913c24c8a5a4a50e9267aa125abcc7956a388d1.tar.xz |
* Commented out two noisy debug lines in the LLUDP server
* Misc. cleanup in ScenePresence.HandleAgentUpdate()
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.Permissions.cs | 36 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 263 |
2 files changed, 142 insertions, 157 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index d01cef7..d1d6b6a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs | |||
@@ -35,7 +35,7 @@ using OpenSim.Region.Framework.Interfaces; | |||
35 | namespace OpenSim.Region.Framework.Scenes | 35 | namespace OpenSim.Region.Framework.Scenes |
36 | { | 36 | { |
37 | #region Delegates | 37 | #region Delegates |
38 | public delegate uint GenerateClientFlagsHandler(UUID userID, UUID objectIDID); | 38 | public delegate uint GenerateClientFlagsHandler(UUID userID, UUID objectID); |
39 | public delegate void SetBypassPermissionsHandler(bool value); | 39 | public delegate void SetBypassPermissionsHandler(bool value); |
40 | public delegate bool BypassPermissionsHandler(); | 40 | public delegate bool BypassPermissionsHandler(); |
41 | public delegate bool PropagatePermissionsHandler(); | 41 | public delegate bool PropagatePermissionsHandler(); |
@@ -147,28 +147,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
147 | 147 | ||
148 | public uint GenerateClientFlags(UUID userID, UUID objectID) | 148 | public uint GenerateClientFlags(UUID userID, UUID objectID) |
149 | { | 149 | { |
150 | SceneObjectPart part=m_scene.GetSceneObjectPart(objectID); | 150 | // libomv will moan about PrimFlags.ObjectYouOfficer being |
151 | // obsolete... | ||
152 | #pragma warning disable 0612 | ||
153 | const PrimFlags DEFAULT_FLAGS = | ||
154 | PrimFlags.ObjectModify | | ||
155 | PrimFlags.ObjectCopy | | ||
156 | PrimFlags.ObjectMove | | ||
157 | PrimFlags.ObjectTransfer | | ||
158 | PrimFlags.ObjectYouOwner | | ||
159 | PrimFlags.ObjectAnyOwner | | ||
160 | PrimFlags.ObjectOwnerModify | | ||
161 | PrimFlags.ObjectYouOfficer; | ||
162 | #pragma warning restore 0612 | ||
163 | |||
164 | SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); | ||
151 | 165 | ||
152 | if (part == null) | 166 | if (part == null) |
153 | return 0; | 167 | return 0; |
154 | 168 | ||
155 | // libomv will moan about PrimFlags.ObjectYouOfficer being | 169 | uint perms = part.GetEffectiveObjectFlags() | (uint)DEFAULT_FLAGS; |
156 | // obsolete... | ||
157 | #pragma warning disable 0612 | ||
158 | uint perms=part.GetEffectiveObjectFlags() | | ||
159 | (uint)PrimFlags.ObjectModify | | ||
160 | (uint)PrimFlags.ObjectCopy | | ||
161 | (uint)PrimFlags.ObjectMove | | ||
162 | (uint)PrimFlags.ObjectTransfer | | ||
163 | (uint)PrimFlags.ObjectYouOwner | | ||
164 | (uint)PrimFlags.ObjectAnyOwner | | ||
165 | (uint)PrimFlags.ObjectOwnerModify | | ||
166 | (uint)PrimFlags.ObjectYouOfficer; | ||
167 | #pragma warning restore 0612 | ||
168 | |||
169 | GenerateClientFlagsHandler handlerGenerateClientFlags = | ||
170 | OnGenerateClientFlags; | ||
171 | 170 | ||
171 | GenerateClientFlagsHandler handlerGenerateClientFlags = OnGenerateClientFlags; | ||
172 | if (handlerGenerateClientFlags != null) | 172 | if (handlerGenerateClientFlags != null) |
173 | { | 173 | { |
174 | Delegate[] list = handlerGenerateClientFlags.GetInvocationList(); | 174 | Delegate[] list = handlerGenerateClientFlags.GetInvocationList(); |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index e510f75..04c22d0 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -76,7 +76,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
76 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 76 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
77 | 77 | ||
78 | private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; | 78 | private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; |
79 | public static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); | 79 | private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); |
80 | private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); | ||
81 | private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); | ||
80 | 82 | ||
81 | public UUID currentParcelUUID = UUID.Zero; | 83 | public UUID currentParcelUUID = UUID.Zero; |
82 | 84 | ||
@@ -171,7 +173,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
171 | protected Vector3 m_CameraAtAxis; | 173 | protected Vector3 m_CameraAtAxis; |
172 | protected Vector3 m_CameraLeftAxis; | 174 | protected Vector3 m_CameraLeftAxis; |
173 | protected Vector3 m_CameraUpAxis; | 175 | protected Vector3 m_CameraUpAxis; |
174 | private uint m_AgentControlFlags; | 176 | private AgentManager.ControlFlags m_AgentControlFlags; |
175 | private Quaternion m_headrotation = Quaternion.Identity; | 177 | private Quaternion m_headrotation = Quaternion.Identity; |
176 | private byte m_state; | 178 | private byte m_state; |
177 | 179 | ||
@@ -380,8 +382,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
380 | 382 | ||
381 | public uint AgentControlFlags | 383 | public uint AgentControlFlags |
382 | { | 384 | { |
383 | get { return m_AgentControlFlags; } | 385 | get { return (uint)m_AgentControlFlags; } |
384 | set { m_AgentControlFlags = value; } | 386 | set { m_AgentControlFlags = (AgentManager.ControlFlags)value; } |
385 | } | 387 | } |
386 | 388 | ||
387 | /// <summary> | 389 | /// <summary> |
@@ -707,25 +709,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
707 | 709 | ||
708 | private void SetDirectionVectors() | 710 | private void SetDirectionVectors() |
709 | { | 711 | { |
710 | Dir_Vectors[0] = new Vector3(1, 0, 0); //FORWARD | 712 | Dir_Vectors[0] = Vector3.UnitX; //FORWARD |
711 | Dir_Vectors[1] = new Vector3(-1, 0, 0); //BACK | 713 | Dir_Vectors[1] = -Vector3.UnitX; //BACK |
712 | Dir_Vectors[2] = new Vector3(0, 1, 0); //LEFT | 714 | Dir_Vectors[2] = Vector3.UnitY; //LEFT |
713 | Dir_Vectors[3] = new Vector3(0, -1, 0); //RIGHT | 715 | Dir_Vectors[3] = -Vector3.UnitY; //RIGHT |
714 | Dir_Vectors[4] = new Vector3(0, 0, 1); //UP | 716 | Dir_Vectors[4] = Vector3.UnitZ; //UP |
715 | Dir_Vectors[5] = new Vector3(0, 0, -1); //DOWN | 717 | Dir_Vectors[5] = -Vector3.UnitZ; //DOWN |
716 | Dir_Vectors[5] = new Vector3(0, 0, -0.5f); //DOWN_Nudge | 718 | Dir_Vectors[5] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge |
717 | } | 719 | } |
718 | 720 | ||
719 | private Vector3[] GetWalkDirectionVectors() | 721 | private Vector3[] GetWalkDirectionVectors() |
720 | { | 722 | { |
721 | Vector3[] vector = new Vector3[6]; | 723 | Vector3[] vector = new Vector3[6]; |
722 | vector[0] = new Vector3(m_CameraUpAxis.Z, 0, -m_CameraAtAxis.Z); //FORWARD | 724 | vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD |
723 | vector[1] = new Vector3(-m_CameraUpAxis.Z, 0, m_CameraAtAxis.Z); //BACK | 725 | vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK |
724 | vector[2] = new Vector3(0, 1, 0); //LEFT | 726 | vector[2] = Vector3.UnitY; //LEFT |
725 | vector[3] = new Vector3(0, -1, 0); //RIGHT | 727 | vector[3] = -Vector3.UnitY; //RIGHT |
726 | vector[4] = new Vector3(m_CameraAtAxis.Z, 0, m_CameraUpAxis.Z); //UP | 728 | vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP |
727 | vector[5] = new Vector3(-m_CameraAtAxis.Z, 0, -m_CameraUpAxis.Z); //DOWN | 729 | vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN |
728 | vector[5] = new Vector3(-m_CameraAtAxis.Z, 0, -m_CameraUpAxis.Z); //DOWN_Nudge | 730 | vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge |
729 | return vector; | 731 | return vector; |
730 | } | 732 | } |
731 | 733 | ||
@@ -1074,7 +1076,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1074 | } | 1076 | } |
1075 | 1077 | ||
1076 | m_isChildAgent = false; | 1078 | m_isChildAgent = false; |
1077 | bool m_flying = ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 1079 | bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
1078 | MakeRootAgent(AbsolutePosition, m_flying); | 1080 | MakeRootAgent(AbsolutePosition, m_flying); |
1079 | 1081 | ||
1080 | if ((m_callbackURI != null) && !m_callbackURI.Equals("")) | 1082 | if ((m_callbackURI != null) && !m_callbackURI.Equals("")) |
@@ -1101,9 +1103,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1101 | /// <param name="distance"></param> | 1103 | /// <param name="distance"></param> |
1102 | public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance) | 1104 | public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance) |
1103 | { | 1105 | { |
1106 | const float POSITION_TOLERANCE = 0.02f; | ||
1107 | const float VELOCITY_TOLERANCE = 0.02f; | ||
1108 | const float ROTATION_TOLERANCE = 0.02f; | ||
1109 | |||
1104 | if (m_followCamAuto) | 1110 | if (m_followCamAuto) |
1105 | { | 1111 | { |
1106 | |||
1107 | if (hitYN) | 1112 | if (hitYN) |
1108 | { | 1113 | { |
1109 | CameraConstraintActive = true; | 1114 | CameraConstraintActive = true; |
@@ -1112,11 +1117,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1112 | Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); | 1117 | Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); |
1113 | ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); | 1118 | ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); |
1114 | } | 1119 | } |
1115 | else | 1120 | else |
1116 | { | 1121 | { |
1117 | if ((m_pos - m_lastPosition).Length() > 0.02f || | 1122 | if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || |
1118 | (m_velocity - m_lastVelocity).Length() > 0.02f || | 1123 | !m_velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || |
1119 | m_bodyRot != m_lastRotation) | 1124 | !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) |
1120 | { | 1125 | { |
1121 | if (CameraConstraintActive) | 1126 | if (CameraConstraintActive) |
1122 | { | 1127 | { |
@@ -1125,13 +1130,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1125 | } | 1130 | } |
1126 | } | 1131 | } |
1127 | } | 1132 | } |
1128 | } | 1133 | } |
1129 | } | 1134 | } |
1130 | 1135 | ||
1131 | Array m_dirControlFlags = Enum.GetValues(typeof(Dir_ControlFlags)); | ||
1132 | |||
1133 | /// <summary> | 1136 | /// <summary> |
1134 | /// This is the event handler for client movement. If a client is moving, this event is triggering. | 1137 | /// This is the event handler for client movement. If a client is moving, this event is triggering. |
1135 | /// </summary> | 1138 | /// </summary> |
1136 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | 1139 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) |
1137 | { | 1140 | { |
@@ -1147,15 +1150,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1147 | if (m_movementUpdateCount < 1) | 1150 | if (m_movementUpdateCount < 1) |
1148 | m_movementUpdateCount = 1; | 1151 | m_movementUpdateCount = 1; |
1149 | 1152 | ||
1150 | // Must check for standing up even when PhysicsActor is null, | 1153 | #region Sanity Checking |
1151 | // since sitting currently removes avatar from physical scene | ||
1152 | //m_log.Debug("agentPos:" + AbsolutePosition.ToString()); | ||
1153 | 1154 | ||
1154 | // This is irritating. Really. | 1155 | // This is irritating. Really. |
1155 | if (!AbsolutePosition.IsFinite()) | 1156 | if (!AbsolutePosition.IsFinite()) |
1156 | { | 1157 | { |
1157 | RemoveFromPhysicalScene(); | 1158 | RemoveFromPhysicalScene(); |
1158 | m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error# 9999902"); | 1159 | m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); |
1159 | 1160 | ||
1160 | m_pos = m_LastFinitePos; | 1161 | m_pos = m_LastFinitePos; |
1161 | if (!m_pos.IsFinite()) | 1162 | if (!m_pos.IsFinite()) |
@@ -1163,7 +1164,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1163 | m_pos.X = 127f; | 1164 | m_pos.X = 127f; |
1164 | m_pos.Y = 127f; | 1165 | m_pos.Y = 127f; |
1165 | m_pos.Z = 127f; | 1166 | m_pos.Z = 127f; |
1166 | m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error# 9999903"); | 1167 | m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); |
1167 | } | 1168 | } |
1168 | 1169 | ||
1169 | AddToPhysicalScene(false); | 1170 | AddToPhysicalScene(false); |
@@ -1173,18 +1174,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1173 | m_LastFinitePos = m_pos; | 1174 | m_LastFinitePos = m_pos; |
1174 | } | 1175 | } |
1175 | 1176 | ||
1176 | //m_physicsActor.AddForce(new PhysicsVector(999999999, 99999999, 999999999999999), true); | 1177 | #endregion Sanity Checking |
1177 | 1178 | ||
1178 | //ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); | 1179 | #region Inputs |
1179 | //if (land != null) | ||
1180 | //{ | ||
1181 | //if (land.landData.landingType == (byte)1 && land.landData.userLocation != Vector3.Zero) | ||
1182 | //{ | ||
1183 | // agent.startpos = land.landData.userLocation; | ||
1184 | //} | ||
1185 | //} | ||
1186 | 1180 | ||
1187 | uint flags = agentData.ControlFlags; | 1181 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; |
1188 | Quaternion bodyRotation = agentData.BodyRotation; | 1182 | Quaternion bodyRotation = agentData.BodyRotation; |
1189 | 1183 | ||
1190 | // Camera location in world. We'll need to raytrace | 1184 | // Camera location in world. We'll need to raytrace |
@@ -1205,87 +1199,85 @@ namespace OpenSim.Region.Framework.Scenes | |||
1205 | // The Agent's Draw distance setting | 1199 | // The Agent's Draw distance setting |
1206 | m_DrawDistance = agentData.Far; | 1200 | m_DrawDistance = agentData.Far; |
1207 | 1201 | ||
1208 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) | ||
1209 | { | ||
1210 | StandUp(); | ||
1211 | } | ||
1212 | |||
1213 | // Check if Client has camera in 'follow cam' or 'build' mode. | 1202 | // Check if Client has camera in 'follow cam' or 'build' mode. |
1214 | Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); | 1203 | Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); |
1215 | 1204 | ||
1216 | m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) | 1205 | m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) |
1217 | && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; | 1206 | && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; |
1218 | 1207 | ||
1208 | m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; | ||
1209 | m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; | ||
1210 | |||
1211 | #endregion Inputs | ||
1212 | |||
1213 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) | ||
1214 | { | ||
1215 | StandUp(); | ||
1216 | } | ||
1217 | |||
1219 | //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); | 1218 | //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); |
1220 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view | 1219 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view |
1221 | if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) | 1220 | if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) |
1222 | { | 1221 | { |
1223 | if (m_followCamAuto) | 1222 | if (m_followCamAuto) |
1224 | { | 1223 | { |
1225 | Vector3 headadjustment = new Vector3(0, 0, 0.3f); | 1224 | Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; |
1226 | m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - (m_pos + headadjustment)), Vector3.Distance(m_CameraCenter, (m_pos + headadjustment)) + 0.3f, RayCastCameraCallback); | 1225 | m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); |
1227 | } | 1226 | } |
1228 | } | 1227 | } |
1229 | 1228 | ||
1230 | m_mouseLook = (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; | ||
1231 | m_leftButtonDown = (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; | ||
1232 | |||
1233 | lock (scriptedcontrols) | 1229 | lock (scriptedcontrols) |
1234 | { | 1230 | { |
1235 | if (scriptedcontrols.Count > 0) | 1231 | if (scriptedcontrols.Count > 0) |
1236 | { | 1232 | { |
1237 | SendControlToScripts(flags); | 1233 | SendControlToScripts((uint)flags); |
1238 | flags = RemoveIgnoredControls(flags, IgnoredControls); | 1234 | flags = RemoveIgnoredControls(flags, IgnoredControls); |
1239 | } | 1235 | } |
1240 | } | 1236 | } |
1241 | 1237 | ||
1242 | if (PhysicsActor == null) | ||
1243 | { | ||
1244 | return; | ||
1245 | } | ||
1246 | |||
1247 | if (m_autopilotMoving) | 1238 | if (m_autopilotMoving) |
1248 | CheckAtSitTarget(); | 1239 | CheckAtSitTarget(); |
1249 | 1240 | ||
1250 | if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) | 1241 | if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) |
1251 | { | 1242 | { |
1252 | // TODO: This doesn't prevent the user from walking yet. | 1243 | // TODO: This doesn't prevent the user from walking yet. |
1253 | // Setting parent ID would fix this, if we knew what value | 1244 | // Setting parent ID would fix this, if we knew what value |
1254 | // to use. Or we could add a m_isSitting variable. | 1245 | // to use. Or we could add a m_isSitting variable. |
1255 | |||
1256 | TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); | 1246 | TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); |
1257 | } | 1247 | } |
1248 | |||
1258 | // In the future, these values might need to go global. | 1249 | // In the future, these values might need to go global. |
1259 | // Here's where you get them. | 1250 | // Here's where you get them. |
1260 | |||
1261 | m_AgentControlFlags = flags; | 1251 | m_AgentControlFlags = flags; |
1262 | m_headrotation = agentData.HeadRotation; | 1252 | m_headrotation = agentData.HeadRotation; |
1263 | m_state = agentData.State; | 1253 | m_state = agentData.State; |
1264 | 1254 | ||
1255 | PhysicsActor actor = PhysicsActor; | ||
1256 | if (actor == null) | ||
1257 | { | ||
1258 | return; | ||
1259 | } | ||
1260 | |||
1265 | if (m_allowMovement) | 1261 | if (m_allowMovement) |
1266 | { | 1262 | { |
1267 | int i = 0; | 1263 | int i = 0; |
1268 | bool update_movementflag = false; | 1264 | bool update_movementflag = false; |
1269 | bool update_rotation = false; | 1265 | bool update_rotation = false; |
1270 | bool DCFlagKeyPressed = false; | 1266 | bool DCFlagKeyPressed = false; |
1271 | Vector3 agent_control_v3 = new Vector3(0, 0, 0); | 1267 | Vector3 agent_control_v3 = Vector3.Zero; |
1272 | Quaternion q = bodyRotation; | 1268 | Quaternion q = bodyRotation; |
1273 | if (PhysicsActor != null) | ||
1274 | { | ||
1275 | bool oldflying = PhysicsActor.Flying; | ||
1276 | 1269 | ||
1277 | if (m_forceFly) | 1270 | bool oldflying = PhysicsActor.Flying; |
1278 | PhysicsActor.Flying = true; | ||
1279 | else if (m_flyDisabled) | ||
1280 | PhysicsActor.Flying = false; | ||
1281 | else | ||
1282 | PhysicsActor.Flying = ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | ||
1283 | 1271 | ||
1284 | if (PhysicsActor.Flying != oldflying) | 1272 | if (m_forceFly) |
1285 | { | 1273 | actor.Flying = true; |
1286 | update_movementflag = true; | 1274 | else if (m_flyDisabled) |
1287 | } | 1275 | actor.Flying = false; |
1288 | } | 1276 | else |
1277 | actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | ||
1278 | |||
1279 | if (actor.Flying != oldflying) | ||
1280 | update_movementflag = true; | ||
1289 | 1281 | ||
1290 | if (q != m_bodyRot) | 1282 | if (q != m_bodyRot) |
1291 | { | 1283 | { |
@@ -1307,10 +1299,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1307 | else | 1299 | else |
1308 | dirVectors = Dir_Vectors; | 1300 | dirVectors = Dir_Vectors; |
1309 | 1301 | ||
1310 | 1302 | foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) | |
1311 | foreach (Dir_ControlFlags DCF in m_dirControlFlags) | ||
1312 | { | 1303 | { |
1313 | if ((flags & (uint)DCF) != 0) | 1304 | if (((uint)flags & (uint)DCF) != 0) |
1314 | { | 1305 | { |
1315 | bResetMoveToPosition = true; | 1306 | bResetMoveToPosition = true; |
1316 | DCFlagKeyPressed = true; | 1307 | DCFlagKeyPressed = true; |
@@ -1356,7 +1347,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1356 | if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) | 1347 | if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) |
1357 | { | 1348 | { |
1358 | //Check the error term of the current position in relation to the target position | 1349 | //Check the error term of the current position in relation to the target position |
1359 | if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 1.5) | 1350 | if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 1.5f) |
1360 | { | 1351 | { |
1361 | // we are close enough to the target | 1352 | // we are close enough to the target |
1362 | m_moveToPositionTarget = Vector3.Zero; | 1353 | m_moveToPositionTarget = Vector3.Zero; |
@@ -1437,8 +1428,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1437 | if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) | 1428 | if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) |
1438 | { | 1429 | { |
1439 | // Are the landing controls requirements filled? | 1430 | // Are the landing controls requirements filled? |
1440 | bool controlland = (((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || | 1431 | bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || |
1441 | ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); | 1432 | ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); |
1442 | 1433 | ||
1443 | // Are the collision requirements fulfilled? | 1434 | // Are the collision requirements fulfilled? |
1444 | bool colliding = (m_physicsActor.IsColliding == true); | 1435 | bool colliding = (m_physicsActor.IsColliding == true); |
@@ -1605,7 +1596,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1605 | } | 1596 | } |
1606 | 1597 | ||
1607 | m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); | 1598 | m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); |
1608 | m_parentPosition = new Vector3(); | 1599 | m_parentPosition = Vector3.Zero; |
1609 | 1600 | ||
1610 | m_parentID = 0; | 1601 | m_parentID = 0; |
1611 | SendFullUpdateToAllClients(); | 1602 | SendFullUpdateToAllClients(); |
@@ -2776,11 +2767,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2776 | agentpos.CopyFrom(cadu); | 2767 | agentpos.CopyFrom(cadu); |
2777 | 2768 | ||
2778 | m_scene.SendOutChildAgentUpdates(agentpos, this); | 2769 | m_scene.SendOutChildAgentUpdates(agentpos, this); |
2779 | |||
2780 | m_LastChildAgentUpdatePosition.X = AbsolutePosition.X; | ||
2781 | m_LastChildAgentUpdatePosition.Y = AbsolutePosition.Y; | ||
2782 | m_LastChildAgentUpdatePosition.Z = AbsolutePosition.Z; | ||
2783 | 2770 | ||
2771 | m_LastChildAgentUpdatePosition = AbsolutePosition; | ||
2784 | } | 2772 | } |
2785 | } | 2773 | } |
2786 | 2774 | ||
@@ -2905,9 +2893,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2905 | m_inTransit = true; | 2893 | m_inTransit = true; |
2906 | 2894 | ||
2907 | if ((m_physicsActor != null) && m_physicsActor.Flying) | 2895 | if ((m_physicsActor != null) && m_physicsActor.Flying) |
2908 | m_AgentControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; | 2896 | m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY; |
2909 | else if ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) | 2897 | else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) |
2910 | m_AgentControlFlags &= ~(uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; | 2898 | m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY; |
2911 | } | 2899 | } |
2912 | 2900 | ||
2913 | public void NotInTransit() | 2901 | public void NotInTransit() |
@@ -2923,7 +2911,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2923 | public void Reset() | 2911 | public void Reset() |
2924 | { | 2912 | { |
2925 | // Put the child agent back at the center | 2913 | // Put the child agent back at the center |
2926 | AbsolutePosition = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 70); | 2914 | AbsolutePosition = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); |
2927 | ResetAnimations(); | 2915 | ResetAnimations(); |
2928 | } | 2916 | } |
2929 | 2917 | ||
@@ -3093,7 +3081,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3093 | 3081 | ||
3094 | cAgent.HeadRotation = m_headrotation; | 3082 | cAgent.HeadRotation = m_headrotation; |
3095 | cAgent.BodyRotation = m_bodyRot; | 3083 | cAgent.BodyRotation = m_bodyRot; |
3096 | cAgent.ControlFlags = m_AgentControlFlags; | 3084 | cAgent.ControlFlags = (uint)m_AgentControlFlags; |
3097 | 3085 | ||
3098 | if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) | 3086 | if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) |
3099 | cAgent.GodLevel = (byte)m_godlevel; | 3087 | cAgent.GodLevel = (byte)m_godlevel; |
@@ -3181,7 +3169,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3181 | 3169 | ||
3182 | m_headrotation = cAgent.HeadRotation; | 3170 | m_headrotation = cAgent.HeadRotation; |
3183 | m_bodyRot = cAgent.BodyRotation; | 3171 | m_bodyRot = cAgent.BodyRotation; |
3184 | m_AgentControlFlags = cAgent.ControlFlags; | 3172 | m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; |
3185 | 3173 | ||
3186 | if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) | 3174 | if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) |
3187 | m_godlevel = cAgent.GodLevel; | 3175 | m_godlevel = cAgent.GodLevel; |
@@ -3594,19 +3582,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3594 | IgnoredControls &= ~(ScriptControlled)controls; | 3582 | IgnoredControls &= ~(ScriptControlled)controls; |
3595 | if (scriptedcontrols.ContainsKey(Script_item_UUID)) | 3583 | if (scriptedcontrols.ContainsKey(Script_item_UUID)) |
3596 | scriptedcontrols.Remove(Script_item_UUID); | 3584 | scriptedcontrols.Remove(Script_item_UUID); |
3597 | |||
3598 | } | 3585 | } |
3599 | else | 3586 | else |
3600 | { | 3587 | { |
3601 | 3588 | scriptedcontrols[Script_item_UUID] = obj; | |
3602 | if (scriptedcontrols.ContainsKey(Script_item_UUID)) | ||
3603 | { | ||
3604 | scriptedcontrols[Script_item_UUID] = obj; | ||
3605 | } | ||
3606 | else | ||
3607 | { | ||
3608 | scriptedcontrols.Add(Script_item_UUID, obj); | ||
3609 | } | ||
3610 | } | 3589 | } |
3611 | } | 3590 | } |
3612 | ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); | 3591 | ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); |
@@ -3624,12 +3603,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3624 | 3603 | ||
3625 | public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) | 3604 | public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) |
3626 | { | 3605 | { |
3606 | ScriptControllers takecontrols; | ||
3607 | |||
3627 | lock (scriptedcontrols) | 3608 | lock (scriptedcontrols) |
3628 | { | 3609 | { |
3629 | if (scriptedcontrols.ContainsKey(Script_item_UUID)) | 3610 | if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols)) |
3630 | { | 3611 | { |
3631 | ScriptControllers takecontrolls = scriptedcontrols[Script_item_UUID]; | 3612 | ScriptControlled sctc = takecontrols.eventControls; |
3632 | ScriptControlled sctc = takecontrolls.eventControls; | 3613 | |
3633 | ControllingClient.SendTakeControls((int)sctc, false, false); | 3614 | ControllingClient.SendTakeControls((int)sctc, false, false); |
3634 | ControllingClient.SendTakeControls((int)sctc, true, false); | 3615 | ControllingClient.SendTakeControls((int)sctc, true, false); |
3635 | 3616 | ||
@@ -3640,7 +3621,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3640 | IgnoredControls |= scData.ignoreControls; | 3621 | IgnoredControls |= scData.ignoreControls; |
3641 | } | 3622 | } |
3642 | } | 3623 | } |
3643 | |||
3644 | } | 3624 | } |
3645 | } | 3625 | } |
3646 | 3626 | ||
@@ -3707,9 +3687,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
3707 | { | 3687 | { |
3708 | lock (scriptedcontrols) | 3688 | lock (scriptedcontrols) |
3709 | { | 3689 | { |
3710 | foreach (UUID scriptUUID in scriptedcontrols.Keys) | 3690 | foreach (KeyValuePair<UUID, ScriptControllers> kvp in scriptedcontrols) |
3711 | { | 3691 | { |
3712 | ScriptControllers scriptControlData = scriptedcontrols[scriptUUID]; | 3692 | UUID scriptUUID = kvp.Key; |
3693 | ScriptControllers scriptControlData = kvp.Value; | ||
3694 | |||
3713 | ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us | 3695 | ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us |
3714 | ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle | 3696 | ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle |
3715 | ScriptControlled localChange = localHeld ^ localLast; // the changed bits | 3697 | ScriptControlled localChange = localHeld ^ localLast; // the changed bits |
@@ -3725,37 +3707,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
3725 | LastCommands = allflags; | 3707 | LastCommands = allflags; |
3726 | } | 3708 | } |
3727 | 3709 | ||
3728 | internal static uint RemoveIgnoredControls(uint flags, ScriptControlled Ignored) | 3710 | internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored) |
3729 | { | 3711 | { |
3730 | if (Ignored == ScriptControlled.CONTROL_ZERO) | 3712 | if (ignored == ScriptControlled.CONTROL_ZERO) |
3731 | return flags; | 3713 | return flags; |
3732 | if ((Ignored & ScriptControlled.CONTROL_BACK) != 0) | 3714 | |
3733 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); | 3715 | if ((ignored & ScriptControlled.CONTROL_BACK) != 0) |
3734 | if ((Ignored & ScriptControlled.CONTROL_FWD) != 0) | 3716 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); |
3735 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS); | 3717 | if ((ignored & ScriptControlled.CONTROL_FWD) != 0) |
3736 | if ((Ignored & ScriptControlled.CONTROL_DOWN) != 0) | 3718 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS); |
3737 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG); | 3719 | if ((ignored & ScriptControlled.CONTROL_DOWN) != 0) |
3738 | if ((Ignored & ScriptControlled.CONTROL_UP) != 0) | 3720 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG); |
3739 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS); | 3721 | if ((ignored & ScriptControlled.CONTROL_UP) != 0) |
3740 | if ((Ignored & ScriptControlled.CONTROL_LEFT) != 0) | 3722 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS); |
3741 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); | 3723 | if ((ignored & ScriptControlled.CONTROL_LEFT) != 0) |
3742 | if ((Ignored & ScriptControlled.CONTROL_RIGHT) != 0) | 3724 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); |
3743 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG); | 3725 | if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0) |
3744 | if ((Ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0) | 3726 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG); |
3745 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG); | 3727 | if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0) |
3746 | if ((Ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0) | 3728 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG); |
3747 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS); | 3729 | if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0) |
3748 | if ((Ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0) | 3730 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS); |
3749 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN); | 3731 | if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0) |
3750 | if ((Ignored & ScriptControlled.CONTROL_LBUTTON) != 0) | 3732 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN); |
3751 | flags &= ~((uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN); | 3733 | if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0) |
3752 | //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, | 3734 | flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN); |
3753 | //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, | 3735 | |
3754 | //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, | 3736 | //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, |
3755 | //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, | 3737 | //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, |
3756 | //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, | 3738 | //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, |
3757 | //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, | 3739 | //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, |
3758 | //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG | 3740 | //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, |
3741 | //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, | ||
3742 | //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG | ||
3743 | |||
3759 | return flags; | 3744 | return flags; |
3760 | } | 3745 | } |
3761 | 3746 | ||