Merge branch 'dev' of ssh://island.sciencesim.com/home/sceneapi/sceneapi into dev
						commit
						a7ec095063
					
				|  | @ -0,0 +1,604 @@ | |||
| using System; | ||||
| using System.IO; | ||||
| using System.Net; | ||||
| using System.Net.Sockets; | ||||
| using System.Text; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.Packets; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Services.Interfaces; | ||||
| using OpenSim.Framework.Client; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Region.Framework.Scenes.Serialization; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Region.Framework.Scenes.Types; | ||||
| using log4net; | ||||
| 
 | ||||
| using Nini.Config; | ||||
| 
 | ||||
| namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||
| { | ||||
|     //The data structure that maintains the list of quarks a script engine subscribes to. | ||||
|     //It might be better to organize the quarks in a k-d tree structure, for easier | ||||
|     //partitioning of the quarks based on spatial information. | ||||
|     //But for now, we just assume the quarks each script engine operates on form a rectangle shape. | ||||
|     //So we just use xmin,ymin and xmax,ymax to identify the rectange; and use a List structure to | ||||
|     //store the quarks. | ||||
|     //Quark size is defined in QuarkInfo.SizeX and QuarkInfo.SizeY. | ||||
| 
 | ||||
|     // The RegionSyncPhysEngine has a receive thread to process messages from the RegionSyncServer. | ||||
|     // It is the client side of the synchronization channel, and send to and receive updates from the  | ||||
|     // Auth. Scene. The server side thread handling the sync channel is implemented in RegionSyncScriptAPI.cs. | ||||
|     //  | ||||
|     // The current implementation is very similar to RegionSyncClient. | ||||
|     // TODO: eventually the same RegionSyncSceneAPI should handle all traffic from different actors, e.g.  | ||||
|     //       using a pub/sub model. | ||||
|     public class PhysEngineToSceneConnector | ||||
|     { | ||||
|         #region PhysEngineToSceneConnector members | ||||
| 
 | ||||
|         // Set the addr and port of RegionSyncServer | ||||
|         private IPAddress m_addr; | ||||
|         private string m_addrString; | ||||
|         private Int32 m_port; | ||||
| 
 | ||||
|         // A reference to the local scene | ||||
|         private Scene m_validLocalScene; | ||||
| 
 | ||||
|         // The avatars added to this client manager for clients on other client managers | ||||
|         object m_syncRoot = new object(); | ||||
| 
 | ||||
|         // The logfile | ||||
|         private ILog m_log; | ||||
| 
 | ||||
|         private string LogHeader = "[PHYSICS ENGINE TO SCENE CONNECTOR]"; | ||||
| 
 | ||||
|         // The listener and the thread which listens for connections from client managers | ||||
|         private Thread m_rcvLoop; | ||||
| 
 | ||||
|         // The client connection to the RegionSyncServer | ||||
|         private TcpClient m_client = new TcpClient(); | ||||
| 
 | ||||
| 
 | ||||
|         //KittyL: Comment out m_statsTimer for now, will figure out whether we need it for PhysEngine later | ||||
|         //private System.Timers.Timer m_statsTimer = new System.Timers.Timer(30000); | ||||
| 
 | ||||
|         // The queue of incoming messages which need handling | ||||
|         //private Queue<string> m_inQ = new Queue<string>(); | ||||
| 
 | ||||
|         //KittyL: added to identify different actors | ||||
|         private ActorType m_actorType = ActorType.PhysicsEngine; | ||||
| 
 | ||||
|         private bool m_debugWithViewer = false; | ||||
|         private long m_messagesSent = 0; | ||||
|         private long m_messagesReceived = 0; | ||||
| 
 | ||||
|         private QuarkSubsriptionInfo m_subscribedQuarks;  | ||||
|          | ||||
| 
 | ||||
|         private IConfig m_sysConfig; | ||||
| 
 | ||||
|         //members for load balancing purpose | ||||
|         //private TcpClient m_loadMigrationSouceEnd = null; | ||||
|         private LoadMigrationEndPoint m_loadMigrationSouceEnd = null; | ||||
|         private Thread m_loadMigrationSrcRcvLoop; | ||||
|         private LoadMigrationListener m_loadMigrationListener = null; | ||||
| 
 | ||||
|         //List of queued messages, when the space that the updated object is located is being migrated | ||||
|         private List<RegionSyncMessage> m_updateMsgQueue = new List<RegionSyncMessage>(); | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
| 
 | ||||
|         // Constructor | ||||
|         public PhysEngineToSceneConnector(Scene validLocalScene, string addr, int port, bool debugWithViewer,  | ||||
|                             IConfig sysConfig) | ||||
|         { | ||||
|             m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||||
|             m_validLocalScene = validLocalScene; | ||||
|             m_addr = IPAddress.Parse(addr); | ||||
|             m_addrString = addr; | ||||
|             m_port = port; | ||||
|             m_debugWithViewer = debugWithViewer; | ||||
|             //m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed); | ||||
|             m_sysConfig = sysConfig; | ||||
| 
 | ||||
|             logEnabled = m_sysConfig.GetBoolean("LogEnabled", false); | ||||
|             logDir = m_sysConfig.GetString("LogDir", "."); | ||||
| 
 | ||||
|             //assume we are connecting to the whole scene as one big quark | ||||
|             m_subscribedQuarks = new QuarkSubsriptionInfo(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize); | ||||
|         } | ||||
| 
 | ||||
|         private List<string> GetQuarkStringList() | ||||
|         { | ||||
|             List<string> quarkList = new List<string>(); | ||||
|             foreach (QuarkInfo quark in m_subscribedQuarks.QuarkList) | ||||
|             { | ||||
|                 quarkList.Add(quark.QuarkStringRepresentation); | ||||
|             } | ||||
|             return quarkList; | ||||
|         } | ||||
|           | ||||
|         // Start the RegionSyncPhysEngine client thread | ||||
|         public bool Start() | ||||
|         { | ||||
|             if (EstablishConnection()) | ||||
|             { | ||||
|                 StartStateSync(); | ||||
|                 return true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private bool EstablishConnection() | ||||
|         { | ||||
|             if (m_client.Connected) | ||||
|             { | ||||
|                 m_log.Warn(LogHeader + ": already connected"); | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 m_client.Connect(m_addr, m_port); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.WarnFormat("{0} [Start] Could not connect to SceneToPhysEngineSyncServer at {1}:{2}", LogHeader, m_addr, m_port); | ||||
|                 m_log.Warn(e.Message); | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             m_log.WarnFormat("{0} Connected to SceneToPhysEngineSyncServer at {1}:{2}", LogHeader, m_addr, m_port); | ||||
| 
 | ||||
|             m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop)); | ||||
|             m_rcvLoop.Name = "PhysEngineToSceneConnector ReceiveLoop"; | ||||
|             m_log.WarnFormat("{0} Starting {1} thread", LogHeader, m_rcvLoop.Name); | ||||
|             m_rcvLoop.Start(); | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         private void StartStateSync() | ||||
|         { | ||||
|             RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStatus, Convert.ToString((int)ActorStatus.Sync)); | ||||
|             Send(msg); | ||||
|             // SendQuarkSubscription(); | ||||
|             Thread.Sleep(100); | ||||
|             DoInitialSync(); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         private void SendQuarkSubscription() | ||||
|         { | ||||
|             List<string> quarkStringList = GetQuarkStringList(); | ||||
|             string quarkString = RegionSyncUtil.QuarkStringListToString(quarkStringList); | ||||
| 
 | ||||
|             m_log.Debug(LogHeader + ": subscribe to quarks: " + quarkString); | ||||
|             //Send(quarkString); | ||||
|             RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.QuarkSubscription, quarkString); | ||||
|             Send(msg); | ||||
|         } | ||||
| 
 | ||||
|         public void SetQuarkSubscription(QuarkSubsriptionInfo quarks) | ||||
|         { | ||||
|             m_subscribedQuarks = quarks; | ||||
|         } | ||||
| 
 | ||||
|         public void RegisterIdle() | ||||
|         { | ||||
|             EstablishConnection(); | ||||
|             RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStatus, Convert.ToString((int)ActorStatus.Idle)); | ||||
|             Send(msg); | ||||
|         } | ||||
| 
 | ||||
|         private void DoInitialSync() | ||||
|         { | ||||
|             // m_validLocalScene.DeleteAllSceneObjects(); | ||||
|             //m_log.Debug(LogHeader + ": send actor type " + m_actorType); | ||||
|             //Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ActorType, Convert.ToString((int)m_actorType))); | ||||
|             //KittyL??? Do we need to send in RegionName? | ||||
| 
 | ||||
|             //Send(new RegionSyncMessage(RegionSyncMessage.MsgType.RegionName, m_scene.RegionInfo.RegionName)); | ||||
|             //m_log.WarnFormat("Sending region name: \"{0}\"", m_scene.RegionInfo.RegionName); | ||||
| 
 | ||||
|             // Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetTerrain)); | ||||
|             // Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetObjects)); | ||||
| 
 | ||||
|             // Register for events which will be forwarded to authoritative scene | ||||
|             // m_scene.EventManager.OnNewClient += EventManager_OnNewClient; | ||||
|             //m_scene.EventManager.OnClientClosed += new EventManager.ClientClosed(RemoveLocalClient); | ||||
|         } | ||||
| 
 | ||||
|         // Disconnect from the RegionSyncServer and close client thread | ||||
|         public void Stop() | ||||
|         { | ||||
|             Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStop, "stop")); | ||||
|             // The remote scene will remove the SceneToPhysEngineConnector when we disconnect | ||||
|             m_rcvLoop.Abort(); | ||||
|             ShutdownClient(); | ||||
| 
 | ||||
|             //stop the migration connections | ||||
|             //ShutdownClient(m_loadMigrationSouceEnd); | ||||
|             if (m_loadMigrationListener != null) | ||||
|                 m_loadMigrationListener.Shutdown(); | ||||
|         } | ||||
| 
 | ||||
|         public void ReportStatus() | ||||
|         { | ||||
|             m_log.WarnFormat("{0} Synchronized to RegionSyncServer at {1}:{2}", LogHeader, m_addr, m_port); | ||||
|             m_log.WarnFormat("{0} Received={1}, Sent={2}", LogHeader, m_messagesReceived, m_messagesSent); | ||||
|             lock (m_syncRoot) | ||||
|             { | ||||
|                 //TODO: should be reporting about the information of the objects/scripts | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void ShutdownClient() | ||||
|         { | ||||
|             m_log.WarnFormat("{0} Disconnected from RegionSyncServer. Shutting down.", LogHeader); | ||||
| 
 | ||||
|             //TODO: remove the objects and scripts | ||||
|             //lock (m_syncRoot) | ||||
|             //{ | ||||
|                  | ||||
|             //} | ||||
| 
 | ||||
|             if (m_client != null) | ||||
|             { | ||||
|                 // Close the connection | ||||
|                 m_client.Client.Close(); | ||||
|                 m_client.Close(); | ||||
|             } | ||||
|             LogMessageClose(); | ||||
|         } | ||||
| 
 | ||||
|         // Listen for messages from a RegionSyncServer | ||||
|         // *** This is the main thread loop for each connected client | ||||
|         private void ReceiveLoop() | ||||
|         { | ||||
|             m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name); | ||||
|             while (true && m_client.Connected) | ||||
|             { | ||||
|                 RegionSyncMessage msg; | ||||
|                 // Try to get the message from the network stream | ||||
|                 try | ||||
|                 { | ||||
|                     msg = new RegionSyncMessage(m_client.GetStream()); | ||||
|                     //m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString()); | ||||
|                 } | ||||
|                 // If there is a problem reading from the client, shut 'er down.  | ||||
|                 catch | ||||
|                 { | ||||
|                     ShutdownClient(); | ||||
|                     return; | ||||
|                 } | ||||
|                 // Try handling the message | ||||
|                 try | ||||
|                 { | ||||
|                     //lock (m_syncRoot) -- KittyL: why do we need to lock here? We could lock inside HandleMessage if necessary, and lock on different objects for better performance | ||||
|                     m_messagesReceived++; | ||||
|                     HandleMessage(msg); | ||||
|                 } | ||||
|                 catch (Exception e) | ||||
|                 { | ||||
|                     m_log.WarnFormat("{0} Encountered an exception: {1} (MSGTYPE = {2})", LogHeader, e.Message, msg.ToString()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         #region SEND | ||||
|         //DSG-TODO: for Scene based DSG, Send() also needs to figure out which Scene to send to, e.g. needs a switching function based on object position | ||||
| 
 | ||||
|         // Send a message to a single connected RegionSyncServer | ||||
|         private void Send(string msg) | ||||
|         { | ||||
|             LogMessage(logOutput, msg); | ||||
|             byte[] bmsg = System.Text.Encoding.ASCII.GetBytes(msg + System.Environment.NewLine); | ||||
|             Send(bmsg); | ||||
|         } | ||||
| 
 | ||||
|         private void Send(RegionSyncMessage msg) | ||||
|         { | ||||
|             LogMessage(logOutput, msg); | ||||
|             Send(msg.ToBytes()); | ||||
|             //m_log.WarnFormat("{0} Sent {1}", LogHeader, msg.ToString()); | ||||
|         } | ||||
| 
 | ||||
|         private void Send(byte[] data) | ||||
|         { | ||||
|             if (m_client.Connected) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     m_client.GetStream().Write(data, 0, data.Length); | ||||
|                     m_messagesSent++; | ||||
|                 } | ||||
|                 // If there is a problem reading from the client, shut 'er down.  | ||||
|                 // *** Still need to alert the module that it's no longer connected! | ||||
|                 catch | ||||
|                 { | ||||
|                     ShutdownClient(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         #endregion SEND | ||||
| 
 | ||||
|         //KittyL: Has to define SendCoarseLocations() here, since it's defined in IRegionSyncClientModule. | ||||
|         //        But should not do much as being PhysEngine, not ClientManager | ||||
|         public void SendCoarseLocations() | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         // Handle an incoming message | ||||
|         // Dan-TODO: This should not be synchronous with the receive! | ||||
|         //           Instead, handle messages from an incoming Queue so server doesn't block sending | ||||
|         // | ||||
|         // KittyL: This is the function that PhysEngine and ClientManager have the most different implementations | ||||
|         private void HandleMessage(RegionSyncMessage msg) | ||||
|         { | ||||
|             //TO FINISH:  | ||||
| 
 | ||||
|             LogMessage(logInput, msg); | ||||
|             switch (msg.Type) | ||||
|             { | ||||
|                 case RegionSyncMessage.MsgType.RegionName: | ||||
|                     { | ||||
|                         return; | ||||
|                     } | ||||
|                 case RegionSyncMessage.MsgType.PhysUpdateAttributes: | ||||
|                     { | ||||
|                         HandlePhysUpdateAttributes(msg); | ||||
|                         return; | ||||
|                     } | ||||
|                 default: | ||||
|                     { | ||||
|                         RegionSyncMessage.HandleError(LogHeader, msg, String.Format("{0} Unsupported message type: {1}", LogHeader, ((int)msg.Type).ToString())); | ||||
|                         return; | ||||
|                     } | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The physics engine has some updates to the attributes. Unpack the parameters, find the | ||||
|         /// correct PhysicsActor and plug in the new values; | ||||
|         /// </summary> | ||||
|         /// <param name="msg"></param> | ||||
|         private void HandlePhysUpdateAttributes(RegionSyncMessage msg) | ||||
|         { | ||||
|             // TODO:  | ||||
|             OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader); | ||||
|             try | ||||
|             { | ||||
|                 uint localID = data["localID"].AsUInteger(); | ||||
|                 string actorID = data["actorID"].AsString(); | ||||
|                 // m_log.DebugFormat("{0}: HandlPhysUpdateAttributes for {1}", LogHeader, localID); | ||||
|                 PhysicsActor pa = FindPhysicsActor(localID); | ||||
|                 if (pa != null) | ||||
|                 { | ||||
|                     // pa.Size = data["size"].AsVector3(); | ||||
|                     pa.ChangingActorID = actorID; | ||||
|                     pa.Position = data["position"].AsVector3(); | ||||
|                     pa.Force = data["force"].AsVector3(); | ||||
|                     pa.Velocity = data["velocity"].AsVector3(); | ||||
|                     pa.Torque = data["torque"].AsVector3(); | ||||
|                     pa.Orientation = data["orientantion"].AsQuaternion(); | ||||
|                     pa.IsPhysical = data["isPhysical"].AsBoolean();  // receive?? | ||||
|                     pa.Flying = data["flying"].AsBoolean();      // receive?? | ||||
|                     pa.Kinematic = data["kinematic"].AsBoolean();    // receive?? | ||||
|                     pa.Buoyancy = (float)(data["buoyancy"].AsReal()); | ||||
|                     SceneObjectPart sop = m_validLocalScene.GetSceneObjectPart(localID); | ||||
|                     if (sop != null) | ||||
|                     { | ||||
|                         pa.Shape = sop.Shape; | ||||
|                     } | ||||
|                     m_validLocalScene.PhysicsScene.AddPhysicsActorTaint(pa); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     m_log.WarnFormat("{0}: attribute update for unknown localID {1}", LogHeader, localID); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.WarnFormat("{0}: EXCEPTION processing UpdateAttributes: {1}", LogHeader, e); | ||||
|                 return; | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Find the physics actor whether it is an object or a scene presence | ||||
|         private PhysicsActor FindPhysicsActor(uint localID) | ||||
|         { | ||||
|             SceneObjectPart sop = m_validLocalScene.GetSceneObjectPart(localID); | ||||
|             if (sop != null) | ||||
|             { | ||||
|                 return sop.PhysActor; | ||||
|             } | ||||
|             ScenePresence sp = m_validLocalScene.GetScenePresence(localID); | ||||
|             if (sp != null) | ||||
|             { | ||||
|                 return sp.PhysicsActor; | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         public void SendPhysUpdateAttributes(PhysicsActor pa) | ||||
|         { | ||||
|             // m_log.DebugFormat("{0}: SendPhysUpdateAttributes for {1}", LogHeader, pa.LocalID); | ||||
|             OSDMap data = new OSDMap(9); | ||||
|             data["localID"] = OSD.FromUInteger(pa.LocalID); | ||||
|             data["actorID"] = OSD.FromString(RegionSyncServerModule.ActorID); | ||||
|             data["size"] = OSD.FromVector3(pa.Size); | ||||
|             data["position"] = OSD.FromVector3(pa.Position); | ||||
|             data["force"] = OSD.FromVector3(pa.Force); | ||||
|             data["velocity"] = OSD.FromVector3(pa.Velocity); | ||||
|             data["torque"] = OSD.FromVector3(pa.Torque); | ||||
|             data["orientation"] = OSD.FromQuaternion(pa.Orientation); | ||||
|             data["isPhysical"] = OSD.FromBoolean(pa.IsPhysical); | ||||
|             data["flying"] = OSD.FromBoolean(pa.Flying); | ||||
|             data["buoyancy"] = OSD.FromReal(pa.Buoyancy); | ||||
|             data["isColliding"] = OSD.FromBoolean(pa.IsColliding); | ||||
|             data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround); | ||||
| 
 | ||||
|             RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,  | ||||
|                                                                 OSDParser.SerializeJsonString(data)); | ||||
|             Send(rsm); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         #region Utility functions | ||||
| 
 | ||||
|         private OSDMap GetOSDMap(string strdata) | ||||
|         { | ||||
|             OSDMap args = null; | ||||
|             OSD buffer = OSDParser.DeserializeJson(strdata); | ||||
|             if (buffer.Type == OSDType.Map) | ||||
|             { | ||||
|                 args = (OSDMap)buffer; | ||||
|                 return args; | ||||
|             } | ||||
|             return null; | ||||
|          | ||||
|         } | ||||
| 
 | ||||
|         HashSet<string> exceptions = new HashSet<string>(); | ||||
|         private OSDMap DeserializeMessage(RegionSyncMessage msg) | ||||
|         { | ||||
|             OSDMap data = null; | ||||
|             try | ||||
|             { | ||||
|                 data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap; | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 lock (exceptions) | ||||
|                     // If this is a new message, then print the underlying data that caused it | ||||
|                     if (!exceptions.Contains(e.Message)) | ||||
|                         m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length)); | ||||
|                 data = null; | ||||
|             } | ||||
|             return data; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         public string GetServerAddressAndPort() | ||||
|         { | ||||
|             return m_addr.ToString() + ":" + m_port.ToString(); | ||||
|         } | ||||
| 
 | ||||
|         #endregion Utility functions | ||||
| 
 | ||||
|         #region Handlers for Scene events | ||||
| 
 | ||||
|         private void HandleAddOrUpdateObjectInLocalScene(RegionSyncMessage msg) | ||||
|         { | ||||
|             // TODO: modify for physics | ||||
|             OSDMap data = DeserializeMessage(msg); | ||||
|             /* | ||||
|             if (data["locX"] == null || data["locY"] == null || data["sogXml"] == null) | ||||
|             { | ||||
|                 m_log.Warn(LogHeader + ": parameters missing in NewObject/UpdatedObject message, need to have locX, locY, sogXml"); | ||||
|                 return; | ||||
|             } | ||||
|              * */ | ||||
|             uint locX = data["locX"].AsUInteger(); | ||||
|             uint locY = data["locY"].AsUInteger(); | ||||
|             string sogxml = data["sogXml"].AsString(); | ||||
|             SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         #endregion Handlers for events/updates from Scene | ||||
|         #region Message Logging | ||||
|         private bool logInput = false; | ||||
|         private bool logOutput = true; | ||||
|         private bool logEnabled = true; | ||||
|         private class MsgLogger | ||||
|         { | ||||
|             public DateTime startTime; | ||||
|             public string path = null; | ||||
|             public System.IO.TextWriter Log = null; | ||||
|         } | ||||
|         private MsgLogger logWriter = null; | ||||
|         private TimeSpan logMaxFileTime = new TimeSpan(0, 5, 0);   // (h,m,s) => 5 minutes | ||||
|         private string logDir = "/stats/stats"; | ||||
|         private object logLocker = new Object(); | ||||
| 
 | ||||
|         private void LogMessage(bool direction, RegionSyncMessage rsm) | ||||
|         { | ||||
|             if (!logEnabled) return;    // save to work of the ToStringFull if not enabled | ||||
|             LogMessage(direction, rsm.ToStringFull()); | ||||
|         } | ||||
| 
 | ||||
|         private void LogMessage(bool direction, string msg) | ||||
|         { | ||||
|             if (!logEnabled) return; | ||||
| 
 | ||||
|             lock (logLocker) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     DateTime now = DateTime.Now; | ||||
|                     if (logWriter == null || (now > logWriter.startTime + logMaxFileTime)) | ||||
|                     { | ||||
|                         if (logWriter != null && logWriter.Log != null) | ||||
|                         { | ||||
|                             logWriter.Log.Close(); | ||||
|                             logWriter.Log.Dispose(); | ||||
|                             logWriter.Log = null; | ||||
|                         } | ||||
| 
 | ||||
|                         // First log file or time has expired, start writing to a new log file | ||||
|                         logWriter = new MsgLogger(); | ||||
|                         logWriter.startTime = now; | ||||
|                         logWriter.path = (logDir.Length > 0 ? logDir + System.IO.Path.DirectorySeparatorChar.ToString() : "") | ||||
|                                 + String.Format("physics-{0}.log", now.ToString("yyyyMMddHHmmss")); | ||||
|                         logWriter.Log = new StreamWriter(File.Open(logWriter.path, FileMode.Append, FileAccess.Write)); | ||||
|                     } | ||||
|                     if (logWriter != null && logWriter.Log != null) | ||||
|                     { | ||||
|                         StringBuilder buff = new StringBuilder(); | ||||
|                         buff.Append(now.ToString("yyyyMMddHHmmss")); | ||||
|                         buff.Append(" "); | ||||
|                         buff.Append(direction ? "A->S:" : "S->A:"); | ||||
|                         buff.Append(msg); | ||||
|                         buff.Append("\r\n"); | ||||
|                         logWriter.Log.Write(buff.ToString()); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception e) | ||||
|                 { | ||||
|                     m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); | ||||
|                     logEnabled = false; | ||||
|                 } | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         private void LogMessageClose() | ||||
|         { | ||||
|             if (logWriter != null && logWriter.Log != null) | ||||
|             { | ||||
|                 logWriter.Log.Close(); | ||||
|                 logWriter.Log.Dispose(); | ||||
|                 logWriter.Log = null; | ||||
|                 logWriter = null; | ||||
|             } | ||||
|             logEnabled = false; | ||||
|         } | ||||
|         #endregion Message Logging | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,465 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSim Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using Nini.Config; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Framework.Client; | ||||
| using OpenSim.Region.CoreModules.Framework.InterfaceCommander; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| using log4net; | ||||
| using System.Net; | ||||
| using System.Net.Sockets; | ||||
| 
 | ||||
| namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||
| { | ||||
|     //The connector that connects the local Scene (cache) and remote authoratative Scene | ||||
|     public class PhysEngineToSceneConnectorModule : IRegionModule, IPhysEngineToSceneConnectorModule, ICommandableModule | ||||
|     { | ||||
|         #region PhysEngineToSceneConnectorModule members and functions | ||||
| 
 | ||||
|         private static int m_activeActors = 0; | ||||
|         private bool m_active = false; | ||||
|         private string m_serveraddr; | ||||
|         private int m_serverport; | ||||
|         private Scene m_scene; | ||||
|         private static List<Scene> m_allScenes = new List<Scene>(); | ||||
|         private ILog m_log; | ||||
|         private Object m_client_lock = new Object(); | ||||
|         //private PhysEngineToSceneConnector m_scriptEngineToSceneConnector = null; | ||||
|         private IConfig m_syncConfig = null; | ||||
|         public IConfig SyncConfig { get { return m_syncConfig; } } | ||||
|         private bool m_debugWithViewer = false; | ||||
|         public bool DebugWithViewer { get { return m_debugWithViewer; } } | ||||
|         private string m_regionSyncMode = ""; | ||||
| 
 | ||||
|         //Variables relavant for multi-scene subscription.  | ||||
|         private Dictionary<string, PhysEngineToSceneConnector> m_PEToSceneConnectors = new Dictionary<string, PhysEngineToSceneConnector>(); //connector for each auth. scene | ||||
|         private string LogHeader = "[PhysEngineToSceneConnectorModule]"; | ||||
|         private PhysEngineToSceneConnector m_idlePEToSceneConnector = null; | ||||
|         private PhysEngineToSceneConnector m_physEngineToSceneConnector = null; | ||||
| 
 | ||||
|         //quark information | ||||
|         //private int QuarkInfo.SizeX; | ||||
|         //private int QuarkInfo.SizeY; | ||||
|         //private string m_quarkListString; | ||||
|         private string m_subscriptionSpaceString; | ||||
| 
 | ||||
|         #endregion PhysEngineToSceneConnectorModule members and functions | ||||
| 
 | ||||
|         #region IRegionModule Members | ||||
| 
 | ||||
|         public void Initialise(Scene scene, IConfigSource config) | ||||
|         { | ||||
|             m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
|             m_active = false; //set to false unless this is the valid local scene | ||||
| 
 | ||||
|             //Read in configuration | ||||
|             IConfig syncConfig = config.Configs["RegionSyncModule"]; | ||||
|             if (syncConfig != null  | ||||
|                     && syncConfig.GetBoolean("Enabled", false) | ||||
|                     // && syncConfig.GetString("Mode", "").ToLower() == "client" | ||||
|                     && syncConfig.GetBoolean("PhysEngineClient", false) | ||||
|                 ) | ||||
|             { | ||||
|                 scene.RegionSyncEnabled = true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 scene.RegionSyncEnabled = false; | ||||
|                 m_log.Warn(LogHeader + ": Not in physics engine client mode. Shutting down."); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             m_active = true; | ||||
|             m_activeActors++; | ||||
| 
 | ||||
|             m_log.Debug(LogHeader + " Init PEToSceneConnectorModule, for local scene " + scene.RegionInfo.RegionName); | ||||
| 
 | ||||
|             string configString = scene.RegionInfo.RegionName + "_SceneToPESyncServerIP"; | ||||
|             m_serveraddr = syncConfig.GetString(configString, "127.0.0.1"); | ||||
|             configString = scene.RegionInfo.RegionName + "_SceneToPESyncServerPort"; | ||||
|             m_serverport = syncConfig.GetInt(configString, 13000); | ||||
| 
 | ||||
|             m_scene = scene; | ||||
|             m_scene.RegisterModuleInterface<IPhysEngineToSceneConnectorModule>(this); | ||||
|             m_syncConfig = syncConfig; | ||||
|             m_debugWithViewer = syncConfig.GetBoolean("PhysEngineDebugWithViewer", false); | ||||
| 
 | ||||
|             //read in the quark size information | ||||
|             //QuarkInfo.SizeX = syncConfig.GetInt("QuarkSizeX", (int)Constants.RegionSize); | ||||
|             //QuarkInfo.SizeY = syncConfig.GetInt("QuarkSizeY", (int)Constants.RegionSize); | ||||
|             QuarkInfo.SizeX = syncConfig.GetInt("QuarkSizeX", (int)Constants.RegionSize); | ||||
|             QuarkInfo.SizeY = syncConfig.GetInt("QuarkSizeY", (int)Constants.RegionSize); | ||||
| 
 | ||||
|             //m_quarkListString = syncConfig.GetString("InitQuarkSet", ""); //if not specified, dost not subscribe to any quark | ||||
|             //if (m_quarkListString.Equals("all")) | ||||
|             //{ | ||||
|             //    m_quarkListString = RegionSyncUtil.QuarkStringListToString(RegionSyncUtil.GetAllQuarkStringInScene(QuarkInfo.SizeX, QuarkInfo.SizeY)); | ||||
|             //} | ||||
|             m_subscriptionSpaceString = syncConfig.GetString("InitSubscriptionSpace", "0_0,256_256"); | ||||
|              | ||||
|               | ||||
|             // Setup the command line interface | ||||
|             m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; | ||||
|             InstallInterfaces(); | ||||
| 
 | ||||
|             SyncStart(null);    // fake a 'phys start' to get things going | ||||
| 
 | ||||
|             m_log.Warn(LogHeader + " Initialised"); | ||||
| 
 | ||||
|             // collect all the scenes for later routing | ||||
|             if (!m_allScenes.Contains(scene)) | ||||
|             { | ||||
|                 m_allScenes.Add(scene); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void PostInitialise() | ||||
|         { | ||||
|             if (!m_active) | ||||
|                 return; | ||||
| 
 | ||||
|             //m_log.Warn(LogHeader + " Post-Initialised"); | ||||
|         } | ||||
| 
 | ||||
|         public void Close() | ||||
|         { | ||||
|             if (m_active) | ||||
|             { | ||||
|             } | ||||
|             m_scene = null; | ||||
|             m_active = false; | ||||
|             m_activeActors--; | ||||
|         } | ||||
| 
 | ||||
|         public string Name | ||||
|         { | ||||
|             get { return "RegionSyncPhysEngineModule"; } | ||||
|         } | ||||
| 
 | ||||
|         public bool IsSharedModule | ||||
|         { | ||||
|             get { return false; } | ||||
|         } | ||||
|         #endregion | ||||
| 
 | ||||
|         #region ICommandableModule Members | ||||
|         private readonly Commander m_commander = new Commander("phys"); | ||||
|         public ICommander CommandInterface | ||||
|         { | ||||
|             get { return m_commander; } | ||||
|         } | ||||
|         #endregion | ||||
| 
 | ||||
|         #region IPhysEngineToSceneConnectorModule members | ||||
| 
 | ||||
| 
 | ||||
|         public bool Active | ||||
|         { | ||||
|             get { return m_active; } | ||||
|         } | ||||
| 
 | ||||
|         public bool Synced | ||||
|         { | ||||
|             get  | ||||
|             {  | ||||
|                 lock(m_client_lock) | ||||
|                 { | ||||
|                     return (m_PEToSceneConnectors.Count > 0); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         bool IPhysEngineToSceneConnectorModule.IsPhysEngineActor() | ||||
|         { | ||||
|             return PhysEngineToSceneConnectorModule.IsPhysEngineActorS; | ||||
|         } | ||||
|         bool IPhysEngineToSceneConnectorModule.IsPhysEngineScene() | ||||
|         { | ||||
|             return PhysEngineToSceneConnectorModule.IsPhysEngineSceneS; | ||||
|         } | ||||
|         bool IPhysEngineToSceneConnectorModule.IsActivePhysEngineScene() | ||||
|         { | ||||
|             return PhysEngineToSceneConnectorModule.IsActivePhysEngineSceneS; | ||||
|         } | ||||
| 
 | ||||
|         public static bool IsPhysEngineSceneS | ||||
|         { | ||||
|             get { return SceneToPhysEngineSyncServer.IsPhysEngineScene2S(); } | ||||
|         } | ||||
|         public static bool IsActivePhysEngineSceneS | ||||
|         { | ||||
|             get { return SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S(); } | ||||
|         } | ||||
|         public static bool IsPhysEngineActorS | ||||
|         { | ||||
|             get { return (m_activeActors != 0); } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The scene is unknown by ODE so we have to look through the scenes to | ||||
|         /// find the one with this PhysicsActor so we can send the update. | ||||
|         /// </summary> | ||||
|         /// <param name="pa"></param> | ||||
|         public static void RouteUpdate(PhysicsActor pa) | ||||
|         { | ||||
|             SceneObjectPart sop; | ||||
|             ScenePresence sp; | ||||
|             Scene s = null; | ||||
|             foreach (Scene ss in m_allScenes) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     sop = ss.GetSceneObjectPart(pa.LocalID); | ||||
|                 } | ||||
|                 catch | ||||
|                 { | ||||
|                     sop = null; | ||||
|                 } | ||||
|                 if (sop != null) | ||||
|                 { | ||||
|                     s = ss; | ||||
|                     break; | ||||
|                 } | ||||
|                 try | ||||
|                 { | ||||
|                     sp = ss.GetScenePresence(pa.LocalID); | ||||
|                 } | ||||
|                 catch | ||||
|                 { | ||||
|                     sp = null; | ||||
|                 } | ||||
|                 if (sp != null) | ||||
|                 { | ||||
|                     s = ss; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             if (s != null) | ||||
|             { | ||||
|                 if (s.PhysEngineToSceneConnectorModule != null) | ||||
|                 { | ||||
|                     s.PhysEngineToSceneConnectorModule.SendUpdate(pa); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     Console.WriteLine("RouteUpdate: PhysEngineToSceneConnectorModule is null"); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Console.WriteLine("RouteUpdate: no SOP found for {0}", pa.LocalID); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
| 
 | ||||
|         #region Event Handlers | ||||
|         #endregion | ||||
| 
 | ||||
|         private void DebugSceneStats() | ||||
|         { | ||||
|             return; | ||||
|             /* | ||||
|             List<ScenePresence> avatars = m_scene.GetAvatars();  | ||||
|             List<EntityBase> entities = m_scene.GetEntities(); | ||||
|             m_log.WarnFormat("{0} There are {1} avatars and {2} entities in the scene", LogHeader, avatars.Count, entities.Count); | ||||
|              */ | ||||
|         } | ||||
| 
 | ||||
|         public void SendUpdate(PhysicsActor pa) | ||||
|         { | ||||
|             this.m_physEngineToSceneConnector.SendPhysUpdateAttributes(pa); | ||||
|         } | ||||
| 
 | ||||
|         #region Console Command Interface | ||||
|         //IMPORTANT: these functions should only be actived for the PhysEngineToSceneConnectorModule that is associated with the valid local scene | ||||
| 
 | ||||
|         private void InstallInterfaces() | ||||
|         { | ||||
|             Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer."); | ||||
|             //cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer"); | ||||
|              | ||||
|             Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer."); | ||||
|             //cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String"); | ||||
|             //cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer"); | ||||
| 
 | ||||
|             Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status."); | ||||
| 
 | ||||
|             //The following two commands are more for easier debugging purpose | ||||
|             Command cmdSyncSetQuarks = new Command("quarkSpace", CommandIntentions.COMMAND_HAZARDOUS, SetQuarkList, "Set the set of quarks to subscribe to. For debugging purpose. Should be issued before \"sync start\""); | ||||
|             cmdSyncSetQuarks.AddArgument("quarkSpace", "The (rectangle) space of quarks to subscribe, represented by x0_y0,x1_y1, the left-bottom and top-right corners of the rectangel space", "String"); | ||||
| 
 | ||||
|             Command cmdSyncSetQuarkSize = new Command("quarksize", CommandIntentions.COMMAND_HAZARDOUS, SetQuarkSize, "Set the size of each quark. For debugging purpose. Should be issued before \"sync quarks\""); | ||||
|             cmdSyncSetQuarkSize.AddArgument("quarksizeX", "The size on x axis of each quark", "Integer"); | ||||
|             cmdSyncSetQuarkSize.AddArgument("quarksizeY", "The size on y axis of each quark", "Integer"); | ||||
| 
 | ||||
|             m_commander.RegisterCommand("start", cmdSyncStart); | ||||
|             m_commander.RegisterCommand("stop", cmdSyncStop); | ||||
|             m_commander.RegisterCommand("status", cmdSyncStatus); | ||||
|             m_commander.RegisterCommand("quarkSpace", cmdSyncSetQuarks); | ||||
| 
 | ||||
|             lock (m_scene) | ||||
|             { | ||||
|                 // Add this to our scene so scripts can call these functions | ||||
|                 m_scene.RegisterModuleCommander(m_commander); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Processes commandline input. Do not call directly. | ||||
|         /// </summary> | ||||
|         /// <param name="args">Commandline arguments</param> | ||||
|         private void EventManager_OnPluginConsole(string[] args) | ||||
|         { | ||||
|             if (args[0] == "phys") | ||||
|             { | ||||
|                 if (args.Length == 1) | ||||
|                 { | ||||
|                     m_commander.ProcessConsoleCommand("help", new string[0]); | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 string[] tmpArgs = new string[args.Length - 2]; | ||||
|                 int i; | ||||
|                 for (i = 2; i < args.Length; i++) | ||||
|                     tmpArgs[i - 2] = args[i]; | ||||
| 
 | ||||
|                 m_commander.ProcessConsoleCommand(args[1], tmpArgs); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void SyncStart(Object[] args) | ||||
|         { | ||||
|             lock (m_client_lock) | ||||
|             { | ||||
|                 //m_log.Warn(LogHeader + " Starting synchronization"); | ||||
|                 m_log.Warn(LogHeader + ": Starting RegionSyncPhysEngine"); | ||||
| 
 | ||||
|                 //Only one remote scene to connect to. Subscribe to whatever specified in the config file. | ||||
|                 //List<string> quarkStringList = RegionSyncUtil.QuarkStringToStringList(m_quarkListString); | ||||
|                 //InitPhysEngineToSceneConnector(quarkStringList); | ||||
|                 InitPhysEngineToSceneConnector(m_subscriptionSpaceString); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void SetQuarkList(Object[] args) | ||||
|         { | ||||
|             m_subscriptionSpaceString = (string)args[0]; | ||||
| 
 | ||||
|             InitPhysEngineToSceneConnector(m_subscriptionSpaceString); | ||||
|         } | ||||
| 
 | ||||
|         private void SetQuarkSize(Object[] args) | ||||
|         { | ||||
|             QuarkInfo.SizeX = (int)args[0]; | ||||
|             QuarkInfo.SizeY = (int)args[1]; | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         private void InitPhysEngineToSceneConnector(string space) | ||||
|         { | ||||
|              | ||||
|             m_physEngineToSceneConnector = new PhysEngineToSceneConnector(m_scene,  | ||||
|                     m_serveraddr, m_serverport, m_debugWithViewer, /* space,*/ m_syncConfig); | ||||
|             if (m_physEngineToSceneConnector.Start()) | ||||
|             { | ||||
|                 m_PEToSceneConnectors.Add(m_scene.RegionInfo.RegionName, m_physEngineToSceneConnector); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void SyncStop(Object[] args) | ||||
|         { | ||||
|             lock (m_client_lock) | ||||
|             { | ||||
|                 //if (m_scriptEngineToSceneConnector == null) | ||||
|                 if(m_PEToSceneConnectors.Count==0 && m_idlePEToSceneConnector==null) | ||||
|                 { | ||||
|                     m_log.Warn(LogHeader + " Already stopped"); | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 if (m_PEToSceneConnectors.Count > 0) | ||||
|                 { | ||||
|                     foreach (KeyValuePair<string, PhysEngineToSceneConnector> valPair in m_PEToSceneConnectors) | ||||
|                     { | ||||
|                         PhysEngineToSceneConnector connector = valPair.Value; | ||||
|                         if (connector == null) | ||||
|                         { | ||||
|                             continue; | ||||
|                         } | ||||
|                         connector.Stop(); | ||||
|                     } | ||||
|                     m_PEToSceneConnectors.Clear(); | ||||
|                 } | ||||
|                 else if (m_idlePEToSceneConnector != null) | ||||
|                 { | ||||
|                     m_idlePEToSceneConnector.Stop(); | ||||
|                     m_idlePEToSceneConnector = null; | ||||
|                 } | ||||
| 
 | ||||
|                 //m_scriptEngineToSceneConnector.Stop(); | ||||
|                 //m_scriptEngineToSceneConnector = null; | ||||
|                 m_log.Warn(LogHeader+": Stopping synchronization"); | ||||
|             } | ||||
| 
 | ||||
|             //save script state and stop script instances | ||||
|             // TODO: Load balancing. next line commented out to compile | ||||
|             // m_scene.EventManager.TriggerPhysEngineSyncStop(); | ||||
|             //remove all objects | ||||
|             m_scene.DeleteAllSceneObjects(); | ||||
|              | ||||
|         } | ||||
| 
 | ||||
|         private void SyncStatus(Object[] args) | ||||
|         { | ||||
|             lock (m_client_lock) | ||||
|             { | ||||
|                 if (m_PEToSceneConnectors.Count == 0) | ||||
|                 { | ||||
|                     m_log.Warn(LogHeader + " Not currently synchronized"); | ||||
|                     return; | ||||
|                 } | ||||
|                 foreach (KeyValuePair<string, PhysEngineToSceneConnector> pair in m_PEToSceneConnectors) | ||||
|                 { | ||||
|                     PhysEngineToSceneConnector sceneConnector = pair.Value; | ||||
|                     sceneConnector.ReportStatus(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
|  | @ -301,6 +301,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|                         if(!m_symSync) | ||||
|                         { | ||||
|                         m_scene.Heightmap.LoadFromXmlString(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)); | ||||
|                         m_scene.PhysicsScene.SetTerrain(m_scene.Heightmap.GetFloatsSerialised()); | ||||
|                         RegionSyncMessage.HandleSuccess(LogHeader(), msg, "Synchronized terrain"); | ||||
|                         } | ||||
|                         return; | ||||
|  | @ -369,6 +370,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|                         UUID agentID = data["agentID"].AsUUID(); | ||||
|                         string first = data["first"].AsString(); | ||||
|                         string last = data["last"].AsString(); | ||||
|                         uint localID = data["localID"].AsUInteger(); | ||||
|                         Vector3 startPos = data["startPos"].AsVector3(); | ||||
|                         if (agentID == null || agentID == UUID.Zero || first == null || last == null || startPos == null) | ||||
|                         { | ||||
|  | @ -402,6 +404,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|                         else | ||||
|                         { | ||||
|                             sp.IsSyncedAvatar = true; | ||||
|                             m_log.DebugFormat("{0}: Setting avatar local ID to {1}", LogHeader(), localID); | ||||
|                             sp.LocalId = localID; | ||||
|                             if (sp.PhysicsActor != null) | ||||
|                             { | ||||
|                                 sp.PhysicsActor.LocalID = localID; | ||||
|                             } | ||||
|                         } | ||||
|                         //RegionSyncMessage.HandlerDebug(LogHeader(), msg, String.Format("Added new remote avatar \"{0}\" ({1})", first + " " + last, agentID)); | ||||
|                         RegionSyncMessage.HandleSuccess(LogHeader(), msg, String.Format("Added new remote avatar \"{0}\" ({1})", first + " " + last, agentID)); | ||||
|  | @ -968,7 +976,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
| 
 | ||||
|         public void HandleAgentRequestSit(object sender, UUID agentID, UUID targetID, Vector3 offset) | ||||
|         { | ||||
|             m_log.DebugFormat("{0} HandleAgentRequestSit for {1}", LogHeader(), agentID.ToString()); | ||||
|             // m_log.DebugFormat("{0} HandleAgentRequestSit for {1}", LogHeader(), agentID.ToString()); | ||||
|             OSDMap data = new OSDMap(3); | ||||
|             data["agentID"] = OSD.FromUUID(agentID); | ||||
|             data["targetID"] = OSD.FromUUID(targetID); | ||||
|  | @ -978,7 +986,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
| 
 | ||||
|         public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) | ||||
|         { | ||||
|             m_log.DebugFormat("{0} HandleAgentSit for {1}", LogHeader(), agentID.ToString()); | ||||
|             // m_log.DebugFormat("{0} HandleAgentSit for {1}", LogHeader(), agentID.ToString()); | ||||
|             OSDMap data = new OSDMap(1); | ||||
|             data["agentID"] = OSD.FromUUID(agentID); | ||||
|             Send(new RegionSyncMessage(RegionSyncMessage.MsgType.AgentSit, OSDParser.SerializeJsonString(data))); | ||||
|  | @ -986,7 +994,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
| 
 | ||||
|         public void HandleGrabObject(uint localID, Vector3 offsetPos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs) | ||||
|         { | ||||
|             m_log.DebugFormat("{0} HandleGrabObject for {1}", LogHeader(), remoteClient.AgentId.ToString()); | ||||
|             // m_log.DebugFormat("{0} HandleGrabObject for {1}", LogHeader(), remoteClient.AgentId.ToString()); | ||||
|             OSDMap data = new OSDMap(4); | ||||
|             data["agentID"] = OSD.FromUUID(remoteClient.AgentId); | ||||
|             data["localID"] = OSD.FromUInteger(localID); | ||||
|  | @ -997,7 +1005,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
| 
 | ||||
|         public void HandleGrabUpdate(UUID objectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs) | ||||
|         { | ||||
|             m_log.DebugFormat("{0} HandleGrabUpdate for {1}", LogHeader(), remoteClient.AgentId.ToString()); | ||||
|             // m_log.DebugFormat("{0} HandleGrabUpdate for {1}", LogHeader(), remoteClient.AgentId.ToString()); | ||||
|             OSDMap data = new OSDMap(5); | ||||
|             data["agentID"] = OSD.FromUUID(remoteClient.AgentId); | ||||
|             data["objectID"] = OSD.FromUUID(objectID); | ||||
|  | @ -1009,7 +1017,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
| 
 | ||||
|         public void HandleDeGrabObject(uint localID, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs) | ||||
|         { | ||||
|             m_log.DebugFormat("{0} HandleDeGrabObject for {1}", LogHeader(), remoteClient.AgentId.ToString()); | ||||
|             // m_log.DebugFormat("{0} HandleDeGrabObject for {1}", LogHeader(), remoteClient.AgentId.ToString()); | ||||
|             OSDMap data = new OSDMap(3); | ||||
|             data["agentID"] = OSD.FromUUID(remoteClient.AgentId); | ||||
|             data["localID"] = OSD.FromUInteger(localID); | ||||
|  |  | |||
|  | @ -339,6 +339,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|                             // Let the client managers know about this avatar | ||||
|                             OSDMap data = new OSDMap(1); | ||||
|                             data["agentID"] = OSD.FromUUID(presence.ControllingClient.AgentId); | ||||
|                             data["localID"] = OSD.FromUInteger(presence.LocalId); | ||||
|                             data["first"] = OSD.FromString(presence.ControllingClient.FirstName); | ||||
|                             data["last"] = OSD.FromString(presence.ControllingClient.LastName); | ||||
|                             data["startPos"] = OSD.FromVector3(presence.ControllingClient.StartPos); | ||||
|  | @ -612,8 +613,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|                         } | ||||
|                         UUID agentID = data["agentID"].AsUUID(); | ||||
|                         UUID objectID = data["objectID"].AsUUID(); | ||||
|                         m_log.DebugFormat("{0} GrabUpdate for {1}. ObjectID={2}",  | ||||
|                                         LogHeader, agentID.ToString(), objectID.ToString()); | ||||
|                         // m_log.DebugFormat("{0} GrabUpdate for {1}. ObjectID={2}",  | ||||
|                         //                 LogHeader, agentID.ToString(), objectID.ToString()); | ||||
|                         Vector3 offset = data["offset"].AsVector3(); | ||||
|                         Vector3 pos = data["pos"].AsVector3(); | ||||
|                         OSDArray surfaceArray = (OSDArray)data["surfaceArgs"]; | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| using System; | ||||
| using System.Text; | ||||
| using System.IO; | ||||
| using OpenMetaverse; | ||||
| using log4net; | ||||
|  | @ -10,7 +11,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|     { | ||||
|         Null, | ||||
|         ClientManager, | ||||
|         ScriptEngine | ||||
|         ScriptEngine, | ||||
|         PhysicsEngine | ||||
|     } | ||||
|     #endregion | ||||
| 
 | ||||
|  | @ -107,6 +109,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|             ScriptStateSyncEnd, | ||||
|             //Idle script engine overloaded -> overloaded script engine | ||||
|             ScriptStateSyncRequest, | ||||
|             // Physics Engine -> Scene | ||||
|             PhysTerseUpdate, | ||||
|             PhysOutOfBounds, | ||||
|             PhysCollisionUpdate, | ||||
|             // Scene -> Physics Engine | ||||
|             PhysUpdateAttributes, | ||||
|         } | ||||
|         #endregion | ||||
| 
 | ||||
|  | @ -198,6 +206,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|         { | ||||
|             return String.Format("{0} ({1} bytes)", m_type.ToString(), m_data.Length.ToString()); | ||||
|         } | ||||
|         public string ToStringFull() | ||||
|         { | ||||
|             return String.Format("{0}:{1})", m_type.ToString(), Encoding.ASCII.GetString(m_data)); | ||||
|         } | ||||
|         #endregion | ||||
| 
 | ||||
|         public static void HandleSuccess(string header, RegionSyncMessage msg, string message) | ||||
|  |  | |||
|  | @ -48,6 +48,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|     public class RegionSyncServerModule : IRegionModule, IRegionSyncServerModule, ICommandableModule | ||||
|     { | ||||
|         private static int DefaultPort = 13000; | ||||
|         public static string ActorID = "XX"; | ||||
|         private static int PortUnknown = -1; | ||||
|         private static string IPAddrUnknown = ""; | ||||
| 
 | ||||
|  | @ -76,6 +77,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // get identifying actor ID whether in client or server mode | ||||
|             ActorID = syncConfig.GetString("ActorID", "ZZ"); | ||||
| 
 | ||||
|             // If syncConfig does not indicate "server", do not start up server mode | ||||
|             //string mode = syncConfig.GetString("Mode", "server").ToLower(); | ||||
|             string mode = syncConfig.GetString("Mode", "").ToLower(); | ||||
|  | @ -112,6 +116,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|             m_seSyncServerport = syncConfig.GetInt(seServerPort, PortUnknown); | ||||
|             DefaultPort++; | ||||
| 
 | ||||
|             //Get sync server info for Physics Engine actors  | ||||
|             string peServerAddr = scene.RegionInfo.RegionName + "_SceneToPESyncServerIP"; | ||||
|             m_peSyncServeraddr = syncConfig.GetString(peServerAddr, "127.0.0.1"); | ||||
|             string peServerPort = scene.RegionInfo.RegionName + "_SceneToPESyncServerPort"; | ||||
|             m_peSyncServerport = syncConfig.GetInt(peServerPort, DefaultPort); | ||||
|             DefaultPort++; | ||||
|              | ||||
|             m_symsync = syncConfig.GetBoolean("SymSync", false); | ||||
| 
 | ||||
|             //Get quark information | ||||
|  | @ -170,6 +181,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|                 m_sceneToSESyncServer = new SceneToScriptEngineSyncServer(m_scene, m_seSyncServeraddr, m_seSyncServerport); | ||||
|                 m_sceneToSESyncServer.Start(); | ||||
|             } | ||||
| 
 | ||||
|             if (!m_peSyncServeraddr.Equals(IPAddrUnknown) && m_peSyncServerport != PortUnknown) | ||||
|             { | ||||
|                 m_log.Warn("[REGION SYNC SERVER MODULE] Starting SceneToPhysEngineSyncServer"); | ||||
|                 //Start the sync server for physics engines | ||||
|                 m_sceneToPESyncServer = new SceneToPhysEngineSyncServer(m_scene, m_peSyncServeraddr, m_peSyncServerport); | ||||
|                 m_sceneToPESyncServer.Start(); | ||||
|             } | ||||
|             //m_log.Warn("[REGION SYNC SERVER MODULE] Post-Initialised"); | ||||
|         } | ||||
| 
 | ||||
|  | @ -485,6 +504,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|         private string m_seSyncServeraddr; | ||||
|         private int m_seSyncServerport; | ||||
|         private SceneToScriptEngineSyncServer m_sceneToSESyncServer = null; | ||||
| 
 | ||||
|         //Sync-server for physics engine | ||||
|         private string m_peSyncServeraddr; | ||||
|         private int m_peSyncServerport; | ||||
|         private SceneToPhysEngineSyncServer m_sceneToPESyncServer = null; | ||||
|          | ||||
|         //a boolean variable to indicate in symmetric sync is configured | ||||
|         private bool m_symsync = false; | ||||
|  | @ -687,6 +711,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | |||
|             // Let the client managers know that a new agent has connected | ||||
|             OSDMap data = new OSDMap(1); | ||||
|             data["agentID"] = OSD.FromUUID(client.AgentId); | ||||
|             data["localID"] = OSD.FromUInteger(m_scene.GetScenePresence(client.AgentId).LocalId); | ||||
|             data["first"] = OSD.FromString(client.FirstName); | ||||
|             data["last"] = OSD.FromString(client.LastName); | ||||
|             data["startPos"] = OSD.FromVector3(client.StartPos); | ||||
|  |  | |||
|  | @ -0,0 +1,552 @@ | |||
| using System; | ||||
| using System.IO; | ||||
| using System.Net; | ||||
| using System.Net.Sockets; | ||||
| using System.Text; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading; | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.Packets; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Region.Framework.Scenes.Serialization; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| using log4net; | ||||
| 
 | ||||
| namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||
| { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     //KittyL: NOTE -- We need to define an interface for all actors to connect into the Scene, | ||||
|     //        e.g. IActorConnector, that runs on the Scene side, processes messages from actors, | ||||
|     //        and apply Scene/Object operations. | ||||
| 
 | ||||
|     // The SceneToPhysEngineConnector acts as a thread on the RegionSyncServer to handle incoming | ||||
|     // messages from PhysEngineToSceneConnectors that run on Physics Engines. It connects the  | ||||
|     // authoratative Scene with remote script engines. | ||||
|     public class SceneToPhysEngineConnector | ||||
|     { | ||||
|         #region SceneToPhysEngineConnector members | ||||
| 
 | ||||
|         object stats = new object(); | ||||
|         private DateTime lastStatTime; | ||||
|         private long msgsIn; | ||||
|         private long msgsOut; | ||||
|         private long bytesIn; | ||||
|         private long bytesOut; | ||||
|         private long pollBlocks; | ||||
|         private int lastTotalCount; | ||||
|         private int lastLocalCount; | ||||
|         private int lastRemoteCount; | ||||
| 
 | ||||
|         private int msgCount = 0; | ||||
| 
 | ||||
|         // The TcpClient this view uses to communicate with its RegionSyncClient | ||||
|         private TcpClient m_tcpclient; | ||||
|         // Set the addr and port for TcpListener | ||||
|         private IPAddress m_addr; | ||||
|         private Int32 m_port; | ||||
|         private int m_connection_number; | ||||
|         private Scene m_scene; | ||||
| 
 | ||||
|         object m_syncRoot = new object(); | ||||
|         Dictionary<UUID, RegionSyncAvatar> m_syncedAvatars = new Dictionary<UUID, RegionSyncAvatar>(); | ||||
| 
 | ||||
|         // A queue for incoming and outgoing traffic | ||||
|         private OpenMetaverse.BlockingQueue<RegionSyncMessage> inbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>(); | ||||
|         private OpenMetaverse.BlockingQueue<RegionSyncMessage> outbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>(); | ||||
| 
 | ||||
|         private ILog m_log; | ||||
| 
 | ||||
|         private Thread m_receive_loop; | ||||
|         private string m_regionName; | ||||
| 
 | ||||
|         private SceneToPhysEngineSyncServer m_syncServer = null; | ||||
| 
 | ||||
|         // A string of the format [REGION SYNC SCRIPT API (regionname)] for use in log headers | ||||
|         private string LogHeader | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 if (m_regionName == null) | ||||
|                     return String.Format("[SceneToPhysEngineConnector #{0}]", m_connection_number); | ||||
|                 return String.Format("[SceneToPhysEngineConnector #{0} ({1:10})]", m_connection_number, m_regionName); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // A string of the format "RegionSyncClientView #X" for use in describing the object itself | ||||
|         public string Description | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 if (m_regionName == null) | ||||
|                     return String.Format("RegionSyncPhysAPI #{0}", m_connection_number); | ||||
|                 return String.Format("RegionSyncPhysAPI #{0} ({1:10})", m_connection_number, m_regionName); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public int ConnectionNum | ||||
|         { | ||||
|             get { return m_connection_number; } | ||||
|         } | ||||
| 
 | ||||
|         public string GetStats() | ||||
|         { | ||||
|             string ret; | ||||
|             //lock (m_syncRoot) | ||||
|             //    syncedAvCount = m_syncedAvatars.Count; | ||||
|             lock (stats) | ||||
|             { | ||||
|                 double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds; | ||||
|                 lastStatTime = DateTime.Now; | ||||
| 
 | ||||
|                 // ret = String.Format("[{0,4}/{1,4}], [{2,4}/{3,4}], [{4,4}/{5,4}], [{6,4} ({7,4})], [{8,8} ({9,8:00.00})], [{10,4} ({11,4})], [{12,8} ({13,8:00.00})], [{14,8} ({15,4}]", | ||||
|                 ret = String.Format("[{0,4}/{1,4}], [{2,6}/{3,6}], [{4,4}/{5,4}], [{6,6} ({7,6})], [{8,4} ({9,4})]", | ||||
|                     //lastTotalCount, totalAvCount, // TOTAL AVATARS | ||||
|                     //lastLocalCount, syncedAvCount, // LOCAL TO THIS CLIENT VIEW | ||||
|                     //lastRemoteCount, totalAvCount - syncedAvCount, // REMOTE (SHOULD = TOTAL - LOCAL) | ||||
|                     msgsIn, (int)(msgsIn / secondsSinceLastStats), | ||||
|                     bytesIn, 8 * (bytesIn / secondsSinceLastStats / 1000000), // IN | ||||
|                     msgsOut, (int)(msgsOut / secondsSinceLastStats), | ||||
|                     bytesOut, 8 * (bytesOut / secondsSinceLastStats / 1000000), // OUT | ||||
|                     pollBlocks, (int)(pollBlocks / secondsSinceLastStats)); // NUMBER OF TIMES WE BLOCKED WRITING TO SOCKET | ||||
| 
 | ||||
|                 msgsIn = msgsOut = bytesIn = bytesOut = pollBlocks = 0; | ||||
|             } | ||||
|             return ret; | ||||
|         } | ||||
| 
 | ||||
|         // Check if the client is connected | ||||
|         public bool Connected | ||||
|         { get { return m_tcpclient.Connected; } } | ||||
| 
 | ||||
|         //private int QuarkInfo.SizeX; | ||||
|         //private int QuarkInfo.SizeY; | ||||
|         //private List<QuarkInfo> m_quarkSubscriptions; | ||||
|         Dictionary<string, QuarkInfo> m_quarkSubscriptions; | ||||
|         public Dictionary<string, QuarkInfo> QuarkSubscriptionList | ||||
|         { | ||||
|             get { return m_quarkSubscriptions; } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         // Constructor | ||||
|         public SceneToPhysEngineConnector(int num, Scene scene, TcpClient client, SceneToPhysEngineSyncServer syncServer) | ||||
|         { | ||||
|             m_connection_number = num; | ||||
|             m_scene = scene; | ||||
|             m_tcpclient = client; | ||||
|             m_addr = ((IPEndPoint)client.Client.RemoteEndPoint).Address; | ||||
|             m_port = ((IPEndPoint)client.Client.RemoteEndPoint).Port; | ||||
|             m_syncServer = syncServer; | ||||
| 
 | ||||
|             //QuarkInfo.SizeX = quarkSizeX; | ||||
|             //QuarkInfo.SizeY = quarkSizeY; | ||||
| 
 | ||||
|             m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||||
|             //m_log.WarnFormat("{0} Constructed", LogHeader); | ||||
| 
 | ||||
|             //Register for events from Scene.EventManager | ||||
|             //m_scene.EventManager.OnRezScript += SEConnectorOnRezScript; | ||||
|             //m_scene.EventManager.OnScriptReset += SEConnectorOnScriptReset; | ||||
|             //m_scene.EventManager.OnUpdateScript += SEConnectorOnUpdateScript; | ||||
| 
 | ||||
|             // Create a thread for the receive loop | ||||
|             m_receive_loop = new Thread(new ThreadStart(delegate() { ReceiveLoop(); })); | ||||
|             m_receive_loop.Name = Description; | ||||
|             //m_log.WarnFormat("{0} Started thread: {1}", LogHeader, m_receive_loop.Name); | ||||
|             m_receive_loop.Start(); | ||||
| 
 | ||||
|             //tell the remote script engine about the locX, locY of this authoritative scene | ||||
|             // SendSceneLoc(); | ||||
|             m_log.DebugFormat("{0}: SceneToPhysEngineConnector initialized", LogHeader); | ||||
|         } | ||||
| 
 | ||||
|         // Stop the listening thread, disconnecting the RegionSyncPhysEngine | ||||
|         public void Shutdown() | ||||
|         { | ||||
|             m_syncServer.RemoveSyncedPhysEngine(this); | ||||
|             // m_scene.EventManager.OnChatFromClient -= EventManager_OnChatFromClient; | ||||
|             // Abort ReceiveLoop Thread, close Socket and TcpClient | ||||
|             m_receive_loop.Abort(); | ||||
|             m_tcpclient.Client.Close(); | ||||
|             m_tcpclient.Close(); | ||||
| 
 | ||||
|             //m_scene.EventManager.OnRezScript -= SEConnectorOnRezScript; | ||||
|             //m_scene.EventManager.OnScriptReset -= SEConnectorOnScriptReset; | ||||
|             //m_scene.EventManager.OnUpdateScript -= SEConnectorOnUpdateScript; | ||||
|         } | ||||
| 
 | ||||
|         #region Send/Receive messages to/from the remote Physics Engine | ||||
| 
 | ||||
|         // Listen for messages from a RegionSyncClient | ||||
|         // *** This is the main thread loop for each connected client | ||||
|         private void ReceiveLoop() | ||||
|         { | ||||
|             //m_scene.EventManager.OnChatFromClient += new EventManager.ChatFromClientEvent(EventManager_OnChatFromClient); | ||||
| 
 | ||||
|             // Reset stats and time | ||||
|             lastStatTime = DateTime.Now; | ||||
|             msgsIn = msgsOut = bytesIn = bytesOut = 0; | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 while (true) | ||||
|                 { | ||||
|                     RegionSyncMessage msg = GetMessage(); | ||||
|                     lock (stats) | ||||
|                     { | ||||
|                         msgsIn++; | ||||
|                         bytesIn += msg.Length; | ||||
|                     } | ||||
|                     lock (m_syncRoot) | ||||
|                         HandleMessage(msg); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.WarnFormat("{0}: has disconnected: {1}", LogHeader, e.Message); | ||||
|             } | ||||
|             Shutdown(); | ||||
|         } | ||||
| 
 | ||||
|         // Get a message from the RegionSyncClient | ||||
|         private RegionSyncMessage GetMessage() | ||||
|         { | ||||
|             // Get a RegionSyncMessager from the incoming stream | ||||
|             RegionSyncMessage msg = new RegionSyncMessage(m_tcpclient.GetStream()); | ||||
|             //m_log.WarnFormat("{0} Received {1}", LogHeader, msg.ToString()); | ||||
|             return msg; | ||||
|         } | ||||
| 
 | ||||
|         // Handle an incoming message | ||||
|         // *** Perhaps this should not be synchronous with the receive | ||||
|         // We could handle messages from an incoming Queue | ||||
|         private void HandleMessage(RegionSyncMessage msg) | ||||
|         { | ||||
|             msgCount++; | ||||
|             //string handlerMessage = ""; | ||||
|             switch (msg.Type) | ||||
|             { | ||||
|                 case RegionSyncMessage.MsgType.ActorStop: | ||||
|                     { | ||||
|                         Shutdown(); | ||||
|                     } | ||||
|                     return; | ||||
|                     /* | ||||
|                 case RegionSyncMessage.MsgType.LoadBalanceRequest: | ||||
|                     { | ||||
|                         m_syncServer.HandleLoadBalanceRequest(this); | ||||
|                         return; | ||||
|                     } | ||||
|                      | ||||
|                 case RegionSyncMessage.MsgType.ActorStatus: | ||||
|                     { | ||||
|                         string status = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); | ||||
|                         ActorStatus actorStatus = (ActorStatus)Convert.ToInt32(status); | ||||
|                         if (actorStatus == ActorStatus.Sync) | ||||
|                         { | ||||
|                             m_log.Debug(LogHeader + ": received ActorStatus " + actorStatus.ToString()); | ||||
|                             m_syncServer.AddSyncedPhysEngine(this); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             m_log.Warn(LogHeader + ": not supposed to received RegionSyncMessage.MsgType.ActorStatus==" + status.ToString()); | ||||
|                         } | ||||
|                         return; | ||||
|                     } | ||||
|                     */ | ||||
| 
 | ||||
|                 case RegionSyncMessage.MsgType.PhysTerseUpdate: | ||||
|                     { | ||||
|                         HandlePhysTerseUpdate(msg); | ||||
|                         return; | ||||
|                     } | ||||
|                 case RegionSyncMessage.MsgType.PhysOutOfBounds: | ||||
|                     { | ||||
|                         HandlePhysOutOfBounds(msg); | ||||
|                         return; | ||||
|                     } | ||||
|                 case RegionSyncMessage.MsgType.PhysCollisionUpdate: | ||||
|                     { | ||||
|                         HandlePhysCollisionUpdate(msg); | ||||
|                         return; | ||||
|                     } | ||||
|                 case RegionSyncMessage.MsgType.PhysUpdateAttributes: | ||||
|                     { | ||||
|                         HandlePhysUpdateAttributes(msg); | ||||
|                         return; | ||||
|                     } | ||||
|                 default: | ||||
|                     { | ||||
|                         m_log.WarnFormat("{0} Unable to handle unsupported message type", LogHeader); | ||||
|                         return; | ||||
|                     } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void HandlePhysTerseUpdate(RegionSyncMessage msg) | ||||
|         { | ||||
|             OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader); | ||||
|             try | ||||
|             { | ||||
|                 uint localID = data["localID"].AsUInteger(); | ||||
|                 // m_log.DebugFormat("{0}: received PhysUpdateAttributes for {1}", LogHeader, localID); | ||||
|                 PhysicsActor pa = FindPhysicsActor(localID); | ||||
|                 if (pa != null) | ||||
|                 { | ||||
|                     pa.RequestPhysicsterseUpdate(); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     m_log.WarnFormat("{0}: terse update for unknown localID {1}", LogHeader, localID); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.WarnFormat("{0}: EXCEPTION processing PhysTerseUpdate: {1}", LogHeader, e); | ||||
|                 return; | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         private void HandlePhysOutOfBounds(RegionSyncMessage msg) | ||||
|         { | ||||
|             // TODO:  | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         private void HandlePhysCollisionUpdate(RegionSyncMessage msg) | ||||
|         { | ||||
|             // TODO:  | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The physics engine has some updates to the attributes. Unpack the parameters, find the | ||||
|         /// correct PhysicsActor and plug in the new values; | ||||
|         /// </summary> | ||||
|         /// <param name="msg"></param> | ||||
|         private void HandlePhysUpdateAttributes(RegionSyncMessage msg) | ||||
|         { | ||||
|             OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader); | ||||
|             try | ||||
|             { | ||||
|                 uint localID = data["localID"].AsUInteger(); | ||||
|                 string actorID = data["actorID"].AsString(); | ||||
|                 // m_log.DebugFormat("{0}: received PhysUpdateAttributes for {1}", LogHeader, localID); | ||||
|                 PhysicsActor pa = FindPhysicsActor(localID); | ||||
|                 if (pa != null) | ||||
|                 { | ||||
|                     pa.ChangingActorID = actorID; | ||||
|                     pa.Size = data["size"].AsVector3(); | ||||
|                     pa.Position = data["position"].AsVector3(); | ||||
|                     pa.Force = data["force"].AsVector3(); | ||||
|                     pa.Velocity = data["velocity"].AsVector3(); | ||||
|                     pa.Torque = data["torque"].AsVector3(); | ||||
|                     pa.Orientation = data["orientantion"].AsQuaternion(); | ||||
|                     pa.IsPhysical = data["isPhysical"].AsBoolean();  // receive?? | ||||
|                     pa.Flying = data["flying"].AsBoolean();      // receive?? | ||||
|                     pa.Kinematic = data["kinematic"].AsBoolean();    // receive?? | ||||
|                     pa.Buoyancy = (float)(data["buoyancy"].AsReal()); | ||||
|                     pa.CollidingGround = data["isCollidingGround"].AsBoolean(); | ||||
|                     pa.IsColliding = data["isCollidingGround"].AsBoolean(); | ||||
| 
 | ||||
|                     pa.RequestPhysicsterseUpdate(); // tell the system the values have changed | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     m_log.WarnFormat("{0}: attribute update for unknown localID {1}", LogHeader, localID); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.WarnFormat("{0}: EXCEPTION processing UpdateAttributes: {1}", LogHeader, e); | ||||
|                 return; | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Find the physics actor whether it is an object or a scene presence | ||||
|         private PhysicsActor FindPhysicsActor(uint localID) | ||||
|         { | ||||
|             SceneObjectPart sop = m_scene.GetSceneObjectPart(localID); | ||||
|             if (sop != null) | ||||
|             { | ||||
|                 return sop.PhysActor; | ||||
|             } | ||||
|             ScenePresence sp = m_scene.GetScenePresence(localID); | ||||
|             if (sp != null) | ||||
|             { | ||||
|                 return sp.PhysicsActor; | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         public void SendPhysUpdateAttributes(PhysicsActor pa) | ||||
|         { | ||||
|             // m_log.DebugFormat("{0}: sending PhysUpdateAttributes for {1}", LogHeader, pa.LocalID); | ||||
|             OSDMap data = new OSDMap(9); | ||||
|             data["localID"] = OSD.FromUInteger(pa.LocalID); | ||||
|             data["actorID"] = OSD.FromString(RegionSyncServerModule.ActorID); | ||||
|             data["size"] = OSD.FromVector3(pa.Size); | ||||
|             data["position"] = OSD.FromVector3(pa.Position); | ||||
|             data["force"] = OSD.FromVector3(pa.Force); | ||||
|             data["velocity"] = OSD.FromVector3(pa.Velocity); | ||||
|             data["torque"] = OSD.FromVector3(pa.Torque); | ||||
|             data["orientation"] = OSD.FromQuaternion(pa.Orientation); | ||||
|             data["isPhysical"] = OSD.FromBoolean(pa.IsPhysical); | ||||
|             data["flying"] = OSD.FromBoolean(pa.Flying); | ||||
|             data["buoyancy"] = OSD.FromReal(pa.Buoyancy); | ||||
|             // data["isColliding"] = OSD.FromBoolean(pa.IsColliding); | ||||
|             // data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround); | ||||
| 
 | ||||
|             RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,  | ||||
|                                                                 OSDParser.SerializeJsonString(data)); | ||||
|             Send(rsm); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         //For simplicity, we assume the subscription sent by PhysEngine is legistimate (no overlapping with other script engines, etc) | ||||
|         private void HandleQuarkSubscription(RegionSyncMessage msg) | ||||
|         { | ||||
|             string quarkString = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); | ||||
|             m_log.Debug(LogHeader + ": received quark-string: " + quarkString); | ||||
| 
 | ||||
|             List<string> quarkStringList = RegionSyncUtil.QuarkStringToStringList(quarkString); | ||||
|             //m_quarkSubscriptions = RegionSyncUtil.GetQuarkInfoList(quarkStringList, QuarkInfo.SizeX, QuarkInfo.SizeY); | ||||
|             List<QuarkInfo> quarkList = RegionSyncUtil.GetQuarkInfoList(quarkStringList); | ||||
|             m_syncServer.RegisterQuarkSubscription(quarkList, this); | ||||
| 
 | ||||
|             m_quarkSubscriptions = new Dictionary<string, QuarkInfo>(); | ||||
|             foreach (QuarkInfo quark in quarkList) | ||||
|             { | ||||
|                 m_quarkSubscriptions.Add(quark.QuarkStringRepresentation, quark); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private RegionSyncMessage PrepareObjectUpdateMessage(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog) | ||||
|         { | ||||
|             OSDMap data = new OSDMap(3); | ||||
|             data["locX"] = OSD.FromUInteger(m_scene.RegionInfo.RegionLocX); | ||||
|             data["locY"] = OSD.FromUInteger(m_scene.RegionInfo.RegionLocY); | ||||
|             string sogxml = SceneObjectSerializer.ToXml2Format(sog); | ||||
|             data["sogXml"] = OSD.FromString(sogxml); | ||||
| 
 | ||||
|             RegionSyncMessage rsm = new RegionSyncMessage(msgType, OSDParser.SerializeJsonString(data)); | ||||
|             return rsm; | ||||
|         } | ||||
| 
 | ||||
|         private void SendSceneLoc() | ||||
|         { | ||||
|             uint locX = m_scene.RegionInfo.RegionLocX; | ||||
|             uint locY = m_scene.RegionInfo.RegionLocY; | ||||
| 
 | ||||
|             OSDMap data = new OSDMap(2); | ||||
|             data["locX"] = OSD.FromUInteger(locX); | ||||
|             data["locY"] = OSD.FromUInteger(locY); | ||||
|             Send(new RegionSyncMessage(RegionSyncMessage.MsgType.SceneLocation, OSDParser.SerializeJsonString(data))); | ||||
|         } | ||||
| 
 | ||||
|         public void Send(RegionSyncMessage msg) | ||||
|         { | ||||
|             if (msg.Type == RegionSyncMessage.MsgType.AvatarAppearance) | ||||
|                 m_log.WarnFormat("{0} Sending AvatarAppearance to client manager", LogHeader); | ||||
| 
 | ||||
|             Send(msg.ToBytes()); | ||||
|         } | ||||
| 
 | ||||
|         private void Send(byte[] data) | ||||
|         { | ||||
|             if (m_tcpclient.Connected) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     lock (stats) | ||||
|                     { | ||||
|                         msgsOut++; | ||||
|                         bytesOut += data.Length; | ||||
|                     } | ||||
|                     m_tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar => | ||||
|                     { | ||||
|                         if (m_tcpclient.Connected) | ||||
|                         { | ||||
|                             try | ||||
|                             { | ||||
|                                 m_tcpclient.GetStream().EndWrite(ar); | ||||
|                             } | ||||
|                             catch (Exception) | ||||
|                             { | ||||
|                                 m_log.WarnFormat("{0} Write to output stream failed", LogHeader); | ||||
|                             } | ||||
|                         } | ||||
|                     }, null); | ||||
|                 } | ||||
|                 catch (IOException) | ||||
|                 { | ||||
|                     m_log.WarnFormat("{0} Physics Engine has disconnected.", LogHeader); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_log.DebugFormat("{0} Attempt to send with no connection", LogHeader); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         public void SendObjectUpdate(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog) | ||||
|         { | ||||
|             Send(PrepareObjectUpdateMessage(msgType, sog)); | ||||
|         } | ||||
| 
 | ||||
|         #endregion Send/Receive messages to/from the remote Physics Engine | ||||
| 
 | ||||
|         #region Spacial query functions (should be eventually implemented within Scene) | ||||
|         /* | ||||
|         //This should be a function of Scene, but since we don't have the quark concept in Scene yet,  | ||||
|         //for now we implement it here. | ||||
|         //Ideally, for quark based space representation, the Scene has a list of quarks, and each quark points | ||||
|         //to a list of objects within that quark. Then it's much easier to return the right set of objects within | ||||
|         //a certain space. (Or use DB that supports spatial queries.) | ||||
|         List<SceneObjectGroup> GetObjectsInGivenSpace(Scene scene, Dictionary<string, QuarkInfo> quarkSubscriptions) | ||||
|         { | ||||
|             List<EntityBase> entities = m_scene.GetEntities(); | ||||
|             List<SceneObjectGroup> sogList = new List<SceneObjectGroup>(); | ||||
|             foreach (EntityBase e in entities) | ||||
|             { | ||||
|                 if (e is SceneObjectGroup) | ||||
|                 { | ||||
|                     SceneObjectGroup sog = (SceneObjectGroup)e; | ||||
|                     string quarkID = RegionSyncUtil.GetQuarkIDByPosition(sog.AbsolutePosition); | ||||
|                     if (m_quarkSubscriptions.ContainsKey(quarkID)) | ||||
|                     { | ||||
|                         sogList.Add(sog); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return sogList; | ||||
|         } | ||||
|         */ | ||||
| 
 | ||||
|         #endregion  | ||||
| 
 | ||||
|         #region Load balancing functions | ||||
|         /* | ||||
|         public void SendLoadBalanceRejection(string response) | ||||
|         { | ||||
|             RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceRejection, response); | ||||
|             Send(msg); | ||||
|         } | ||||
|         */ | ||||
|         #endregion   | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,678 @@ | |||
| using System; | ||||
| using System.IO; | ||||
| using System.Net; | ||||
| using System.Net.Sockets; | ||||
| using System.Text; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.CoreModules.Framework.InterfaceCommander; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Region.Framework.Interfaces; | ||||
| using log4net; | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| using OpenMetaverse.StructuredData; | ||||
| using OpenSim.Region.Framework.Scenes.Serialization; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| 
 | ||||
| namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||
| { | ||||
|     //Information of a registered idle physics engine. | ||||
|     //Note, this is a temporary solution to inlcude idle physics engines here.  | ||||
|     //In the future, there might be a independent load balaner that keeps track | ||||
|     //of available idle hardware. | ||||
|     public class IdlePhysEngineInfo | ||||
|     { | ||||
|         public TcpClient TClient; | ||||
|         //public IPAddress PhysEngineIPAddr; | ||||
|         //public int PhysEnginePort; | ||||
|         public string ID; | ||||
| 
 | ||||
|         //Will be used to store the overloaded PE that has send LB request and paired with this idle PE | ||||
|         public SceneToPhysEngineConnector AwaitOverloadedSE=null;  | ||||
| 
 | ||||
|         public IdlePhysEngineInfo(TcpClient tclient) | ||||
|         { | ||||
|             if(tclient==null) return; | ||||
|             TClient = tclient; | ||||
|             IPAddress ipAddr = ((IPEndPoint)tclient.Client.RemoteEndPoint).Address; | ||||
|             int port = ((IPEndPoint)tclient.Client.RemoteEndPoint).Port; | ||||
|             ID = ipAddr.ToString()+":"+port; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     //Here is the per actor type listening server for physics Engines. | ||||
|     public class SceneToPhysEngineSyncServer : ISceneToPhysEngineServer, ICommandableModule | ||||
|     { | ||||
|         #region SceneToPhysEngineSyncServer members | ||||
|         // Set the addr and port for TcpListener | ||||
|         private IPAddress m_addr; | ||||
|         private Int32 m_port; | ||||
| 
 | ||||
|         //this field is only meaning for the QuarkInfo records on the Scene side | ||||
|         private SceneToPhysEngineConnector m_peConnector=null; | ||||
|         public SceneToPhysEngineConnector PEConnector | ||||
|         { | ||||
|             get { return m_peConnector; } | ||||
|             set { m_peConnector = value; } | ||||
|         } | ||||
| 
 | ||||
|         private int peCounter; | ||||
| 
 | ||||
|         // static counters that are used to compute global configuration state | ||||
|         private static int m_syncServerInitialized = 0; | ||||
|         private static int m_totalConnections = 0; | ||||
|         private static List<Scene> m_allScenes = new List<Scene>(); | ||||
| 
 | ||||
|         // The local scene. | ||||
|         private Scene m_scene; | ||||
| 
 | ||||
|         private ILog m_log; | ||||
| 
 | ||||
|         // The listener and the thread which listens for connections from client managers | ||||
|         private TcpListener m_listener; | ||||
|         private Thread m_listenerThread; | ||||
| 
 | ||||
|         private object m_physEngineConnector_lock = new object(); | ||||
|         //private Dictionary<string, SceneToPhysEngineConnector> m_physEngineConnectors = new Dictionary<string, SceneToPhysEngineConnector>(); | ||||
|         private List<SceneToPhysEngineConnector> m_physEngineConnectors = new List<SceneToPhysEngineConnector>(); | ||||
|         // the last connector created | ||||
|         private SceneToPhysEngineConnector m_sceneToPhysEngineConnector = null; | ||||
| 
 | ||||
|         //list of idle physics engines that have registered. | ||||
|         private List<IdlePhysEngineInfo> m_idlePhysEngineList = new List<IdlePhysEngineInfo>(); | ||||
| 
 | ||||
|         //List of all quarks, each using the concatenation of x,y values of its left-bottom corners,  | ||||
|         // where the x,y values are the offset position in the scene. | ||||
|         private Dictionary<string, QuarkInfo> m_quarksInScene = new Dictionary<string, QuarkInfo>(); | ||||
| 
 | ||||
|         private string LogHeader = "[SCENE TO PHYS ENGINE SYNC SERVER]"; | ||||
| 
 | ||||
|         //Quark related info | ||||
|         //private int QuarkInfo.SizeX; | ||||
|         //private int QuarkInfo.SizeY; | ||||
| 
 | ||||
|         #region ICommandableModule Members | ||||
|         private readonly Commander m_commander = new Commander("phys"); | ||||
|         public ICommander CommandInterface | ||||
|         { | ||||
|             get { return m_commander; } | ||||
|         } | ||||
| 
 | ||||
|         private void InstallInterfaces() | ||||
|         { | ||||
|             // Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer."); | ||||
|             //cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer"); | ||||
|              | ||||
|             // Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer."); | ||||
|             //cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String"); | ||||
|             //cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer"); | ||||
| 
 | ||||
|             Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status."); | ||||
| 
 | ||||
|             //The following two commands are more for easier debugging purpose | ||||
|             // Command cmdSyncSetQuarks = new Command("quarkSpace", CommandIntentions.COMMAND_HAZARDOUS, SetQuarkList, "Set the set of quarks to subscribe to. For debugging purpose. Should be issued before \"sync start\""); | ||||
|             // cmdSyncSetQuarks.AddArgument("quarkSpace", "The (rectangle) space of quarks to subscribe, represented by x0_y0,x1_y1, the left-bottom and top-right corners of the rectangel space", "String"); | ||||
| 
 | ||||
|             // Command cmdSyncSetQuarkSize = new Command("quarksize", CommandIntentions.COMMAND_HAZARDOUS, SetQuarkSize, "Set the size of each quark. For debugging purpose. Should be issued before \"sync quarks\""); | ||||
|             // cmdSyncSetQuarkSize.AddArgument("quarksizeX", "The size on x axis of each quark", "Integer"); | ||||
|             // cmdSyncSetQuarkSize.AddArgument("quarksizeY", "The size on y axis of each quark", "Integer"); | ||||
| 
 | ||||
|             // m_commander.RegisterCommand("start", cmdSyncStart); | ||||
|             // m_commander.RegisterCommand("stop", cmdSyncStop); | ||||
|             m_commander.RegisterCommand("status", cmdSyncStatus); | ||||
|             // m_commander.RegisterCommand("quarkSpace", cmdSyncSetQuarks); | ||||
| 
 | ||||
|             lock (m_scene) | ||||
|             { | ||||
|                 // Add this to our scene so scripts can call these functions | ||||
|                 m_scene.RegisterModuleCommander(m_commander); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Processes commandline input. Do not call directly. | ||||
|         /// </summary> | ||||
|         /// <param name="args">Commandline arguments</param> | ||||
|         private void EventManager_OnPluginConsole(string[] args) | ||||
|         { | ||||
|             if (args[0] == "phys") | ||||
|             { | ||||
|                 if (args.Length == 1) | ||||
|                 { | ||||
|                     m_commander.ProcessConsoleCommand("help", new string[0]); | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 string[] tmpArgs = new string[args.Length - 2]; | ||||
|                 int i; | ||||
|                 for (i = 2; i < args.Length; i++) | ||||
|                     tmpArgs[i - 2] = args[i]; | ||||
| 
 | ||||
|                 m_commander.ProcessConsoleCommand(args[1], tmpArgs); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void SyncStart(Object[] args) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|         private void SyncStop(Object[] args) | ||||
|         { | ||||
|             return; | ||||
|         } | ||||
|         private void SyncStatus(Object[] args) | ||||
|         { | ||||
|             lock (m_physEngineConnector_lock) | ||||
|             { | ||||
|                 if (m_physEngineConnectors.Count == 0) | ||||
|                 { | ||||
|                     m_log.Warn(LogHeader + " Not currently synchronized"); | ||||
|                     return; | ||||
|                 } | ||||
|                 m_log.Warn(LogHeader + " Synchronized"); | ||||
|                 foreach (SceneToPhysEngineConnector pec in m_physEngineConnectors) | ||||
|                 { | ||||
|                     m_log.Warn(pec.GetStats()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         // Check if any of the client views are in a connected state | ||||
|         public bool IsPhysEngineScene() { return SceneToPhysEngineSyncServer.IsPhysEngineScene2S(); } | ||||
|         public bool IsActivePhysEngineScene() { return SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S(); } | ||||
|         public bool IsPhysEngineActor() { return SceneToPhysEngineSyncServer.IsPhysEngineActorS; } | ||||
| 
 | ||||
|         public bool Synced | ||||
|         { | ||||
|             get { return (m_physEngineConnectors.Count > 0); } | ||||
|         } | ||||
|         public static bool IsPhysEngineSceneS | ||||
|         { | ||||
|             get { return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0); } | ||||
|         } | ||||
|         public static bool IsPhysEngineScene2S() | ||||
|         { | ||||
|             return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0); | ||||
|         } | ||||
|         public static bool IsActivePhysEngineSceneS | ||||
|         { | ||||
|             get { | ||||
|                 System.Console.WriteLine("IsActivePhysEngineScene: si={0} tc={1}",  | ||||
|                     SceneToPhysEngineSyncServer.m_syncServerInitialized,  | ||||
|                     SceneToPhysEngineSyncServer.m_totalConnections); | ||||
|                 return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0  | ||||
|                                 && SceneToPhysEngineSyncServer.m_totalConnections > 0);  | ||||
|             } | ||||
|         } | ||||
|         public static bool IsActivePhysEngineScene2S() | ||||
|         { | ||||
|             return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0  | ||||
|                             && SceneToPhysEngineSyncServer.m_totalConnections > 0);  | ||||
|         } | ||||
|         public static bool IsPhysEngineActorS | ||||
|         { | ||||
|             get { return PhysEngineToSceneConnectorModule.IsPhysEngineActorS; } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The scene is unknown by ODE so we have to look through the scenes to | ||||
|         /// find the one with this PhysicsActor so we can send the update. | ||||
|         /// </summary> | ||||
|         /// <param name="pa"></param> | ||||
|         public static void RouteUpdate(PhysicsActor pa) | ||||
|         { | ||||
|             SceneObjectPart sop = null; | ||||
|             Scene s = null; | ||||
|             foreach (Scene ss in m_allScenes) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     sop = ss.GetSceneObjectPart(pa.LocalID); | ||||
|                 } | ||||
|                 catch | ||||
|                 { | ||||
|                     sop = null; | ||||
|                 } | ||||
|                 if (sop != null) | ||||
|                 { | ||||
|                     s = ss; | ||||
|                     break; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ScenePresence sp = ss.GetScenePresence(pa.LocalID); | ||||
|                     if (sp != null) | ||||
|                     { | ||||
|                         s = ss; | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (s != null) | ||||
|             { | ||||
|                 if (s.SceneToPhysEngineSyncServer != null) | ||||
|                 { | ||||
|                     s.SceneToPhysEngineSyncServer.SendUpdate(pa); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     Console.WriteLine("RouteUpdate: SceneToPhysEngineSyncServer is no available"); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 Console.WriteLine("RouteUpdate: no SOP for update of {0}", pa.LocalID); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         public void SendUpdate(PhysicsActor pa) | ||||
|         { | ||||
|             // m_log.DebugFormat("{0}: SendUpdate for {1}", LogHeader, pa.LocalID); | ||||
|             this.m_sceneToPhysEngineConnector.SendPhysUpdateAttributes(pa); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         // Constructor | ||||
|         public SceneToPhysEngineSyncServer(Scene scene, string addr, int port) | ||||
|         { | ||||
|             if (QuarkInfo.SizeX == -1 || QuarkInfo.SizeY == -1) | ||||
|             { | ||||
|                 m_log.Error(LogHeader + " QuarkInfo.SizeX or QuarkInfo.SizeY has not been configured yet."); | ||||
|                 Environment.Exit(0); ; | ||||
|             } | ||||
| 
 | ||||
|             m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||||
|             //m_log.Warn(LogHeader + "Constructed"); | ||||
|             m_scene = scene; | ||||
|             m_addr = IPAddress.Parse(addr); | ||||
|             m_port = port; | ||||
| 
 | ||||
|             m_scene.RegisterModuleInterface<ISceneToPhysEngineServer>(this); | ||||
| 
 | ||||
|             // remember all the scenes that are configured for connection to physics engine | ||||
|             if (!m_allScenes.Contains(m_scene)) | ||||
|             { | ||||
|                 m_allScenes.Add(m_scene); | ||||
|             } | ||||
| 
 | ||||
|             InitQuarksInScene(); | ||||
|             SubscribeToEvents(); | ||||
|             m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; | ||||
|             InstallInterfaces(); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         private void SubscribeToEvents() | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         private void UnSubscribeToEvents() | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         // Start the server | ||||
|         public void Start() | ||||
|         { | ||||
|             SceneToPhysEngineSyncServer.m_syncServerInitialized++; | ||||
|             m_listenerThread = new Thread(new ThreadStart(Listen)); | ||||
|             m_listenerThread.Name = "SceneToPhysEngineSyncServer Listener"; | ||||
|             m_log.DebugFormat("{0}: Starting {1} thread", LogHeader, m_listenerThread.Name); | ||||
|             m_listenerThread.Start(); | ||||
|             // m_log.DebugFormat("{0}: Started", LogHeader); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         // Stop the server and disconnect all RegionSyncClients | ||||
|         public void Shutdown() | ||||
|         { | ||||
|             m_log.DebugFormat("{0}: Shutdown", LogHeader); | ||||
|             SceneToPhysEngineSyncServer.m_syncServerInitialized--; | ||||
|             // Stop the listener and listening thread so no new clients are accepted | ||||
|             m_listener.Stop(); | ||||
|             m_listenerThread.Abort(); | ||||
|             m_listenerThread = null; | ||||
| 
 | ||||
|             // Stop all existing SceneTOSEConnectors  | ||||
|             //TO FINISH | ||||
|             foreach (SceneToPhysEngineConnector peConnector in m_physEngineConnectors) | ||||
|             { | ||||
|                 peConnector.Shutdown(); | ||||
|             } | ||||
|             m_physEngineConnectors.Clear(); | ||||
| 
 | ||||
|             UnSubscribeToEvents(); | ||||
|         } | ||||
| 
 | ||||
|         private void InitQuarksInScene() | ||||
|         { | ||||
|             List<QuarkInfo> quarkList = RegionSyncUtil.GetAllQuarksInScene(); | ||||
|             foreach (QuarkInfo quark in quarkList) | ||||
|             { | ||||
|                 m_quarksInScene.Add(quark.QuarkStringRepresentation, quark); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public void RegisterQuarkSubscription(List<QuarkInfo> quarkSubscriptions, SceneToPhysEngineConnector peConnector) | ||||
|         { | ||||
|             foreach (QuarkInfo quark in quarkSubscriptions) | ||||
|             { | ||||
|                 string quarkID = quark.QuarkStringRepresentation; | ||||
|                 // TODO: does the physics engine connect to quarks. Next line commented out. | ||||
|                 // m_quarksInScene[quarkID].PEConnector = peConnector; | ||||
|                 m_log.Debug(LogHeader + ": " + quarkID + " subscribed by "+peConnector.Description); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Add a connector to a physics engine | ||||
|         public void AddSyncedPhysEngine(SceneToPhysEngineConnector peConnector) | ||||
|         { | ||||
|             lock (m_physEngineConnector_lock) | ||||
|             { | ||||
|                 m_physEngineConnectors.Add(peConnector); | ||||
|                 m_sceneToPhysEngineConnector = peConnector; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Remove the client view from the list and decrement synced client counter | ||||
|         public void RemoveSyncedPhysEngine(SceneToPhysEngineConnector peConnector) | ||||
|         { | ||||
|             lock (m_physEngineConnector_lock) | ||||
|             { | ||||
|                 //Dictionary<string, SceneToPhysEngineConnector> currentlist = m_physEngineConnectors; | ||||
|                 //Dictionary<string, SceneToPhysEngineConnector> newlist = new Dictionary<string, SceneToPhysEngineConnector>(currentlist); | ||||
|                 m_physEngineConnectors.Remove(peConnector); | ||||
|                 // Threads holding the previous version of the list can keep using it since | ||||
|                 // they will not hold it for long and get a new copy next time they need to iterate | ||||
|                 //m_physEngineConnectors = newlist; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Listen for connections from a new RegionSyncClient | ||||
|         // When connected, start the ReceiveLoop for the new client | ||||
|         private void Listen() | ||||
|         { | ||||
|             m_listener = new TcpListener(m_addr, m_port); | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 // Start listening for clients | ||||
|                 m_listener.Start(); | ||||
|                 while (true) | ||||
|                 { | ||||
|                     // *** Move/Add TRY/CATCH to here, but we don't want to spin loop on the same error | ||||
|                     m_log.WarnFormat(LogHeader + ": Listening for new connections on port {0}...", m_port.ToString()); | ||||
|                     TcpClient tcpclient = m_listener.AcceptTcpClient(); | ||||
|                     IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address; | ||||
|                     int port = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Port; | ||||
|                     SceneToPhysEngineSyncServer.m_totalConnections++; | ||||
|                     // m_log.DebugFormat("{0}: m_totalConnections = {1}", LogHeader, SceneToPhysEngineSyncServer.m_totalConnections); | ||||
| 
 | ||||
|                     ActorStatus actorStatus = GetActorStatus(tcpclient); | ||||
| 
 | ||||
|                     switch (actorStatus) | ||||
|                     { | ||||
|                         case ActorStatus.Sync: | ||||
|                             // Add the SceneToPhysEngineConnector to the list  | ||||
|                             SceneToPhysEngineConnector sceneToPEConnector = new SceneToPhysEngineConnector(++peCounter, m_scene, tcpclient, this); | ||||
|                             AddSyncedPhysEngine(sceneToPEConnector); | ||||
|                             break; | ||||
|                         case ActorStatus.Idle: | ||||
|                             IdlePhysEngineInfo idleSE = new IdlePhysEngineInfo(tcpclient); | ||||
|                             m_log.DebugFormat("{0}: adding an idle SE ({1}:{2})", LogHeader, addr, port); | ||||
|                             m_idlePhysEngineList.Add(idleSE); | ||||
|                             break; | ||||
|                         default: | ||||
|                             m_log.DebugFormat("{0}: Unknown actor status", LogHeader); | ||||
|                             break; | ||||
|                     } | ||||
| 
 | ||||
|                 } | ||||
|             } | ||||
|             catch (SocketException e) | ||||
|             { | ||||
|                 m_log.WarnFormat("{0}: [Listen] SocketException: {1}", LogHeader, e); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /* | ||||
|         public void RegisterSyncedPhysEngine(SceneToPhysEngineConnector sceneToSEConnector) | ||||
|         { | ||||
|             //first, remove it from the idle list | ||||
|             m_idlePhysEngineList.Remove(sceneToSEConnector); | ||||
| 
 | ||||
|             //now, added to the synced SE list | ||||
|             AddSyncedPhysEngine(sceneToSEConnector); | ||||
|         } | ||||
|          * */  | ||||
| 
 | ||||
| 
 | ||||
|         // Broadcast a message to all connected RegionSyncClients | ||||
|         public void SendToAllConnectedPE(RegionSyncMessage msg) | ||||
|         { | ||||
|             if (m_physEngineConnectors.Count > 0) | ||||
|             { | ||||
|                 m_log.Debug(LogHeader + ": region " + m_scene.RegionInfo.RegionName + " Broadcast to PhysEngine, msg " + msg.Type); | ||||
|                 foreach (SceneToPhysEngineConnector peConnector in m_physEngineConnectors) | ||||
|                 { | ||||
|                     peConnector.Send(msg); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         //TO FINISH: Find the right SceneToSEConnector to forward the message | ||||
|         public void SendToPE(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog) | ||||
|         { | ||||
|             SceneToPhysEngineConnector peConnector = GetSceneToPEConnector(sog); | ||||
|             if (peConnector != null) | ||||
|             { | ||||
|                 peConnector.SendObjectUpdate(msgType, sog); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         //This is to send a message, rsm, to phys engine, and the message is about object SOG. E.g. RemovedObject | ||||
|         public void SendToPE(RegionSyncMessage rsm, SceneObjectGroup sog) | ||||
|         { | ||||
|             SceneToPhysEngineConnector peConnector = GetSceneToPEConnector(sog); | ||||
|             if (peConnector != null) | ||||
|             { | ||||
|                 peConnector.Send(rsm); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         private SceneToPhysEngineConnector GetSceneToPEConnector(SceneObjectGroup sog) | ||||
|         { | ||||
|             if (m_physEngineConnectors.Count == 0) | ||||
|                 return null; | ||||
|             if (sog == null) | ||||
|             { | ||||
|                 return m_physEngineConnectors[0]; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 //Find the right SceneToSEConnector by the object's position | ||||
|                 //TO FINISH: Map the object to a quark first, then map the quark to SceneToSEConnector | ||||
|                 string quarkID = RegionSyncUtil.GetQuarkIDByPosition(sog.AbsolutePosition); | ||||
|                 // TODO: connection of physics engine to quarks. Next line commented out | ||||
|                 // SceneToPhysEngineConnector peConnector = m_quarksInScene[quarkID].PEConnector; | ||||
| 
 | ||||
|                 if (PEConnector == null) | ||||
|                 { | ||||
|                     m_log.Warn(LogHeader + sog.AbsolutePosition.ToString() + " not covered by any physics engine"); | ||||
|                 } | ||||
| 
 | ||||
|                 return PEConnector; | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         private ActorStatus GetActorStatus(TcpClient tcpclient) | ||||
|         { | ||||
|             m_log.Debug(LogHeader+ ": Get Actor status"); | ||||
| 
 | ||||
|             RegionSyncMessage msg = new RegionSyncMessage(tcpclient.GetStream()); | ||||
|             ActorStatus actorStatus; | ||||
|             switch (msg.Type) | ||||
|             { | ||||
|                 case RegionSyncMessage.MsgType.ActorStatus: | ||||
|                     { | ||||
|                         string status = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); | ||||
|                         m_log.Debug(LogHeader + ": recv status: " + status); | ||||
|                         actorStatus = (ActorStatus)Convert.ToInt32(status); | ||||
|                         break; | ||||
|                     } | ||||
|                 default: | ||||
|                     { | ||||
|                         m_log.Error(LogHeader + ": Expect Message Type: ActorStatus"); | ||||
|                         RegionSyncMessage.HandleError("[REGION SYNC SERVER]", msg, String.Format("{0} Expect Message Type: ActorType", "[REGION SYNC SERVER]")); | ||||
|                         return ActorStatus.Null; | ||||
|                     } | ||||
|             } | ||||
|             return actorStatus; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         #region Event Handlers | ||||
|        | ||||
|         #endregion Event Handlers | ||||
| 
 | ||||
|         #region Load balancing members and functions | ||||
|         /* | ||||
|         //keep track of idle physics engines that are in the process of load balancing (they are off the idle list, but not a working physics engine yet (not sync'ing with Scene yet)). | ||||
|         private Dictionary<string, IdlePhysEngineInfo> m_loadBalancingIdleSEs = new Dictionary<string,IdlePhysEngineInfo>();  | ||||
|         public void HandleLoadBalanceRequest(SceneToPhysEngineConnector seConnctor) | ||||
|         { | ||||
|             //Let's start a thread to do the job, so that we can return quickly and don't block on ReceiveLoop() | ||||
| 
 | ||||
|             Thread partitionThread = new Thread(new ParameterizedThreadStart(TriggerLoadBalanceProcess)); | ||||
|             partitionThread.Name = "TriggerLoadBalanceProcess"; | ||||
|             partitionThread.Start((object)seConnctor); | ||||
|         } | ||||
| 
 | ||||
|         public void TriggerLoadBalanceProcess(object arg) | ||||
|         { | ||||
|             SceneToPhysEngineConnector seConnctor = (SceneToPhysEngineConnector)arg; | ||||
|             IdlePhysEngineInfo idlePhysEngineInfo = GetIdlePhysEngineConnector(); | ||||
|             if (idlePhysEngineInfo != null) | ||||
|             { | ||||
|                 RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadMigrationNotice); | ||||
|                 Send(idlePhysEngineInfo.TClient, msg.ToBytes()); | ||||
|                 m_log.Debug(LogHeader + ": HandleLoadBalanceRequest from " + seConnctor.Description + ", picked idle SE: " + idlePhysEngineInfo.ID); | ||||
| 
 | ||||
|                 //keep track of which overload physics engine is paired up with which idle physics engine | ||||
|                 idlePhysEngineInfo.AwaitOverloadedSE = seConnctor; | ||||
|                 m_loadBalancingIdleSEs.Add(idlePhysEngineInfo.ID, idlePhysEngineInfo); | ||||
| 
 | ||||
|                 m_log.Debug("ToSEConnector portal: local -" + | ||||
|                     ((IPEndPoint)idlePhysEngineInfo.TClient.Client.LocalEndPoint).Address.ToString() + ":" + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.LocalEndPoint).Port | ||||
|                     + "; remote - " + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.RemoteEndPoint).Address.ToString() + ":" | ||||
|                     + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.RemoteEndPoint).Port); | ||||
| 
 | ||||
|                 //Now we expect the idle physics engine to reply back | ||||
|                 msg = new RegionSyncMessage(idlePhysEngineInfo.TClient.GetStream()); | ||||
|                 if (msg.Type != RegionSyncMessage.MsgType.LoadMigrationListenerInitiated) | ||||
|                 { | ||||
|                     m_log.Warn(LogHeader + ": should receive a message of type LoadMigrationListenerInitiated, but received " + msg.Type.ToString()); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     //Before the load is migrated from overloaded physics engine to the idle engine, sync with the DB to update the state in DB | ||||
|                     List<EntityBase> entities = m_scene.GetEntities(); | ||||
|                     foreach (EntityBase entity in entities) | ||||
|                     { | ||||
|                         if (!entity.IsDeleted && entity is SceneObjectGroup && ((SceneObjectGroup)entity).HasGroupChanged) | ||||
|                         { | ||||
|                             m_scene.ForceSceneObjectBackup((SceneObjectGroup)entity); | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     OSDMap data = DeserializeMessage(msg); | ||||
|                     if (!data.ContainsKey("ip") || !data.ContainsKey("port") ) | ||||
|                     { | ||||
|                         m_log.Warn(LogHeader + ": parameters missing in SceneLocation message from Scene, need to have ip, port"); | ||||
|                         return; | ||||
|                     } | ||||
|                     //echo the information back to the overloaded physics engine | ||||
|                     seConnctor.Send(new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceResponse, OSDParser.SerializeJsonString(data))); | ||||
| 
 | ||||
|                     m_log.Debug(LogHeader + " now remove physics engine " + idlePhysEngineInfo.ID + " from idle SE list, and create SceneToPhysEngineConnector to it"); | ||||
|                     //create a SceneToSEConnector for the idle physics engine, who will be sync'ing with this SyncServer soon | ||||
|                     SceneToPhysEngineConnector sceneToSEConnector = new SceneToPhysEngineConnector(++peCounter, m_scene, idlePhysEngineInfo.TClient, this); | ||||
|                     //Now remove the physics engine from the idle SE list | ||||
|                     m_idlePhysEngineList.Remove(idlePhysEngineInfo); | ||||
|                     //AddSyncedPhysEngine(sceneToSEConnector); | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 seConnctor.SendLoadBalanceRejection("no idle physics engines"); | ||||
|             } | ||||
|         } | ||||
|         */ | ||||
| 
 | ||||
|         HashSet<string> exceptions = new HashSet<string>(); | ||||
|         private OSDMap DeserializeMessage(RegionSyncMessage msg) | ||||
|         { | ||||
|             OSDMap data = null; | ||||
|             try | ||||
|             { | ||||
|                 data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap; | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 lock (exceptions) | ||||
|                     // If this is a new message, then print the underlying data that caused it | ||||
|                     if (!exceptions.Contains(e.Message)) | ||||
|                         m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length)); | ||||
|                 data = null; | ||||
|             } | ||||
|             return data; | ||||
|         } | ||||
| 
 | ||||
|         private void Send(TcpClient tcpclient, byte[] data) | ||||
|         { | ||||
|             if (tcpclient.Connected) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar => | ||||
|                     { | ||||
|                         if (tcpclient.Connected) | ||||
|                         { | ||||
|                             try | ||||
|                             { | ||||
|                                 tcpclient.GetStream().EndWrite(ar); | ||||
|                             } | ||||
|                             catch (Exception) | ||||
|                             { } | ||||
|                         } | ||||
|                     }, null); | ||||
|                 } | ||||
|                 catch (IOException) | ||||
|                 { | ||||
|                     m_log.WarnFormat("{0} physics Engine has disconnected.", LogHeader); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private IdlePhysEngineInfo GetIdlePhysEngineConnector() | ||||
|         { | ||||
|             if (m_idlePhysEngineList.Count == 0) | ||||
|                 return null; | ||||
|             IdlePhysEngineInfo idleSEInfo = m_idlePhysEngineList[0]; | ||||
|             m_idlePhysEngineList.Remove(idleSEInfo); | ||||
|             return idleSEInfo; | ||||
|         } | ||||
| 
 | ||||
|         #endregion Load balancing functions  | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,41 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSim Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| //KittyL: Added to support running script engine actor | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| 
 | ||||
| namespace OpenSim.Region.Framework.Interfaces | ||||
| { | ||||
|     //the interface for Scene to sync with Script Engine | ||||
|     public interface IPhysEngineToSceneConnector | ||||
|     { | ||||
|         // TODO: | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,46 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSim Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| //KittyL: Added to support running script engine actor | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| 
 | ||||
| namespace OpenSim.Region.Framework.Interfaces | ||||
| { | ||||
|     //the interface for Scene to sync with Script Engine | ||||
|     public interface IPhysEngineToSceneConnectorModule | ||||
|     { | ||||
|         bool IsPhysEngineScene(); | ||||
|         bool IsActivePhysEngineScene(); | ||||
|         bool IsPhysEngineActor(); | ||||
|         bool DebugWithViewer { get; } | ||||
|         void SendUpdate(PhysicsActor pa); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,41 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSim Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| //KittyL: Added to support running script engine actor | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| 
 | ||||
| namespace OpenSim.Region.Framework.Interfaces | ||||
| { | ||||
|     //the interface for Scene to sync with Script Engine | ||||
|     public interface ISceneToPhysEngineConnector | ||||
|     { | ||||
|         // TODO: | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,45 @@ | |||
| /* | ||||
|  * Copyright (c) Contributors, http://opensimulator.org/ | ||||
|  * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the OpenSim Project nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| //KittyL: Added to support running script engine actor | ||||
| 
 | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework.Scenes; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| 
 | ||||
| namespace OpenSim.Region.Framework.Interfaces | ||||
| { | ||||
|     //the interface for Scene to sync with Script Engine | ||||
|     public interface ISceneToPhysEngineServer | ||||
|     { | ||||
|         bool IsPhysEngineScene(); | ||||
|         bool IsActivePhysEngineScene(); | ||||
|         bool IsPhysEngineActor(); | ||||
|         void SendUpdate(PhysicsActor pa); | ||||
|     } | ||||
| } | ||||
|  | @ -467,8 +467,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|          | ||||
|         protected IScriptEngineToSceneConnectorModule m_scriptEngineToSceneConnectorModule; | ||||
| 
 | ||||
| 
 | ||||
|         public IScriptEngineToSceneConnectorModule ScriptEngineToSceneConnectorModule | ||||
|         { | ||||
|             get { return m_scriptEngineToSceneConnectorModule; } | ||||
|  | @ -493,6 +491,46 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             return IsSyncedServer(); | ||||
|         } | ||||
| 
 | ||||
|         /////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|         //RA: Physics Engine | ||||
|         /////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|         protected IPhysEngineToSceneConnectorModule m_physEngineToSceneConnectorModule = null; | ||||
|         public IPhysEngineToSceneConnectorModule PhysEngineToSceneConnectorModule | ||||
|         { | ||||
|             get { return m_physEngineToSceneConnectorModule; } | ||||
|             set { m_physEngineToSceneConnectorModule = value; } | ||||
|         } | ||||
| 
 | ||||
|         protected ISceneToPhysEngineServer m_sceneToPhysEngineSyncServer = null; | ||||
|         public ISceneToPhysEngineServer SceneToPhysEngineSyncServer | ||||
|         { | ||||
|             get  | ||||
|             { | ||||
|                 if (m_sceneToPhysEngineSyncServer == null) | ||||
|                 { | ||||
|                     // kludge since this module is loaded in postInitialize | ||||
|                     m_sceneToPhysEngineSyncServer = RequestModuleInterface<ISceneToPhysEngineServer>(); | ||||
|                 } | ||||
|                 return m_sceneToPhysEngineSyncServer;  | ||||
|             } | ||||
|             set { m_sceneToPhysEngineSyncServer = value; } | ||||
|         } | ||||
| 
 | ||||
|         // depending on what mode we're in, the different modules are available | ||||
|         protected bool IsPhysEngineActor() | ||||
|         { | ||||
|             if (PhysEngineToSceneConnectorModule != null) | ||||
|             { | ||||
|                 return this.PhysEngineToSceneConnectorModule.IsPhysEngineActor(); | ||||
|             } | ||||
|             if (SceneToPhysEngineSyncServer != null) | ||||
|             { | ||||
|                 return this.SceneToPhysEngineSyncServer.IsPhysEngineActor(); | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         /////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| 
 | ||||
|         //This function should only be called by an actor who's local Scene is just a cache of the authorative Scene. | ||||
|         //If the object already exists, use the new copy to replace it. | ||||
|  | @ -1368,6 +1406,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             RegionSyncServerModule = RequestModuleInterface<IRegionSyncServerModule>(); | ||||
|             RegionSyncClientModule = RequestModuleInterface<IRegionSyncClientModule>(); | ||||
|             ScriptEngineToSceneConnectorModule = RequestModuleInterface<IScriptEngineToSceneConnectorModule>(); | ||||
|             PhysEngineToSceneConnectorModule = RequestModuleInterface<IPhysEngineToSceneConnectorModule>(); | ||||
|             SceneToPhysEngineSyncServer = RequestModuleInterface<ISceneToPhysEngineServer>(); | ||||
| 
 | ||||
|             ////////////////////////////////////////////////////////////////////// | ||||
|             //SYMMETRIC SYNC (KittyL: started 12/23/2010) | ||||
|  | @ -1576,7 +1616,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                     int tmpPhysicsMS2 = Util.EnvironmentTickCount(); | ||||
|                     // Do not simulate physics locally if this is a synced client | ||||
|                     //if (!IsSyncedClient()) | ||||
|                     if (IsSyncedServer()) | ||||
|                     if (IsSyncedServer() || this.IsPhysEngineActor()) | ||||
|                     { | ||||
|                         if ((m_frame % m_update_physics == 0) && m_physics_enabled) | ||||
|                             m_sceneGraph.UpdatePreparePhysics(); | ||||
|  | @ -1585,7 +1625,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
| 
 | ||||
|                     // Do not simulate physics locally if this is a synced client | ||||
|                     //if (!IsSyncedClient()) | ||||
|                     if (IsSyncedServer()) | ||||
|                     if (IsSyncedServer() || this.IsPhysEngineActor()) | ||||
|                     { | ||||
|                         if (m_frame % m_update_entitymovement == 0) | ||||
|                             m_sceneGraph.UpdateScenePresenceMovement(); | ||||
|  | @ -1596,7 +1636,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
|                     int tmpPhysicsMS = Util.EnvironmentTickCount(); | ||||
|                     // Do not simulate physics locally if this is a synced client | ||||
|                     //if (!IsSyncedClient()) | ||||
|                     if (IsSyncedServer()) | ||||
|                     if (IsSyncedServer() || this.IsPhysEngineActor()) | ||||
|                     { | ||||
|                         if (m_frame % m_update_physics == 0) | ||||
|                         { | ||||
|  |  | |||
|  | @ -457,7 +457,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
|             lock (m_updateList) | ||||
|             { | ||||
|                 m_updateList[obj.UUID] = obj; | ||||
|                 m_log.Debug("added " + obj.UUID + " to m_updateList"); | ||||
|                 // m_log.Debug("added " + obj.UUID + " to m_updateList"); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -115,6 +115,47 @@ namespace OpenSim.Region.Physics.Manager | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// Structure to hold previous values of the PhysicsActor. This is used to see | ||||
|     /// if the values changed before sending updates to the Physics Engine. | ||||
|     /// </summary> | ||||
|     public struct PhysActorLastValues | ||||
|     { | ||||
|         public uint updateTime; | ||||
|         public uint localID; | ||||
|         public Vector3 size; | ||||
|         public Vector3 position; | ||||
|         public Vector3 force; | ||||
|         public Vector3 velocity; | ||||
|         public Vector3 torque; | ||||
|         public Quaternion orientation; | ||||
|         public Boolean isPhysical; | ||||
|         public Boolean flying; | ||||
|         public double buoyancy; | ||||
|         public bool Changed(PhysicsActor pa) | ||||
|         { | ||||
|             bool ret = false; | ||||
|             if (localID != pa.LocalID) { localID = pa.LocalID; ret = true; } | ||||
|             if (size != pa.Size) { size = pa.Size; ret = true; } | ||||
|             if (!AlmostEqual(position, pa.Position)) { position = pa.Position; ret = true; } | ||||
|             if (!AlmostEqual(force, pa.Force)) { force = pa.Force; ret = true; } | ||||
|             if (!AlmostEqual(velocity, pa.Velocity)) { velocity = pa.Velocity; ret = true; } | ||||
|             if (!AlmostEqual(torque, pa.Torque)) { torque = pa.Torque; ret = true; } | ||||
|             if (orientation != pa.Orientation) { orientation = pa.Orientation; ret = true; } | ||||
|             if (isPhysical != pa.IsPhysical) { isPhysical = pa.IsPhysical; ret = true; } | ||||
|             if (flying != pa.Flying) { flying = pa.Flying; ret = true; } | ||||
|             if (buoyancy != pa.Buoyancy) { buoyancy = pa.Buoyancy; ret = true; } | ||||
|             return ret; | ||||
|         } | ||||
|         private bool AlmostEqual(Vector3 a, Vector3 b) | ||||
|         { | ||||
|             if (Math.Abs(a.X - b.X) > 0.001) return false; | ||||
|             if (Math.Abs(a.Y - b.Y) > 0.001) return false; | ||||
|             if (Math.Abs(a.Z - b.Z) > 0.001) return false; | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public abstract class PhysicsActor | ||||
|     { | ||||
|         public delegate void RequestTerseUpdate(); | ||||
|  | @ -142,7 +183,15 @@ namespace OpenSim.Region.Physics.Manager | |||
| 
 | ||||
|         public abstract PrimitiveBaseShape Shape { set; } | ||||
| 
 | ||||
|         public abstract uint LocalID { set; } | ||||
|         // RA: used to be abstract but changed to allow 'get' without changing all the phys engines | ||||
|         uint m_baseLocalID; | ||||
|         public virtual uint LocalID {  | ||||
|             set { m_baseLocalID = value; }  | ||||
|             get { return m_baseLocalID; }  | ||||
|         } | ||||
|         public PhysActorLastValues lastValues; | ||||
|         // ID of actor which last updated the values. Send if I did the change. | ||||
|         public string ChangingActorID = "YY"; | ||||
| 
 | ||||
|         public abstract bool Grabbed { set; } | ||||
| 
 | ||||
|  | @ -280,6 +329,7 @@ namespace OpenSim.Region.Physics.Manager | |||
|         public override uint LocalID | ||||
|         { | ||||
|             set { return; } | ||||
|             get { return 0; } | ||||
|         } | ||||
| 
 | ||||
|         public override bool Grabbed | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ using OpenMetaverse; | |||
| using Ode.NET; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule; | ||||
| using log4net; | ||||
| 
 | ||||
| namespace OpenSim.Region.Physics.OdePlugin | ||||
|  | @ -202,6 +203,23 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|             m_name = avName; | ||||
|         } | ||||
| 
 | ||||
|         public override void RequestPhysicsterseUpdate() | ||||
|         { | ||||
|             if (PhysEngineToSceneConnectorModule.IsPhysEngineActorS) | ||||
|             { | ||||
|                 // m_log.DebugFormat("[ODE CHARACTER]: Sending terse update for {0}", LocalID); | ||||
|                 // if the values have changed and it was I who changed them, send an update | ||||
|                 if (this.lastValues.Changed(this) && ChangingActorID == RegionSyncServerModule.ActorID) | ||||
|                 { | ||||
|                     PhysEngineToSceneConnectorModule.RouteUpdate(this); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 base.RequestPhysicsterseUpdate(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public override int PhysicsActorType | ||||
|         { | ||||
|             get { return (int) ActorTypes.Agent; } | ||||
|  | @ -220,6 +238,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|         public override uint LocalID | ||||
|         { | ||||
|             set { m_localID = value; } | ||||
|             get { return m_localID; } | ||||
|         } | ||||
| 
 | ||||
|         public override bool Grabbed | ||||
|  | @ -408,6 +427,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|             get { return _position; } | ||||
|             set | ||||
|             { | ||||
|                 base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 if (Body == IntPtr.Zero || Shell == IntPtr.Zero) | ||||
|                 { | ||||
|                     if (value.IsFinite()) | ||||
|  | @ -453,6 +473,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|             get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); } | ||||
|             set | ||||
|             { | ||||
|                 base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 if (value.IsFinite()) | ||||
|                 { | ||||
|                     m_pidControllerActive = true; | ||||
|  | @ -774,6 +795,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|                 { | ||||
|                     m_pidControllerActive = true; | ||||
|                     _target_velocity = value; | ||||
|                     base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | @ -830,6 +852,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|         { | ||||
|             if (force.IsFinite()) | ||||
|             { | ||||
|                 base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 if (pushforce) | ||||
|                 { | ||||
|                     m_pidControllerActive = false; | ||||
|  | @ -1144,7 +1167,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|                 if (!m_lastUpdateSent) | ||||
|                 { | ||||
|                     m_lastUpdateSent = true; | ||||
|                     //base.RequestPhysicsterseUpdate(); | ||||
|                     // base.RequestPhysicsterseUpdate(); | ||||
| 
 | ||||
|                 } | ||||
|             } | ||||
|  | @ -1182,6 +1205,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|                     m_hackSentFall = false; | ||||
|                 } | ||||
|             } | ||||
|             if (!m_lastUpdateSent) | ||||
|             { | ||||
|                 this.RequestPhysicsterseUpdate(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | @ -1348,7 +1375,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|                     _position.Z = m_taintPosition.Z; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             Console.WriteLine("ODECharacter: ProcessTaints: doing update"); | ||||
|             this.RequestPhysicsterseUpdate(); | ||||
|         } | ||||
| 
 | ||||
|         internal void AddCollisionFrameTime(int p) | ||||
|  |  | |||
|  | @ -47,7 +47,9 @@ using log4net; | |||
| using OpenMetaverse; | ||||
| using Ode.NET; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Framework; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule; | ||||
| 
 | ||||
| namespace OpenSim.Region.Physics.OdePlugin | ||||
| { | ||||
|  | @ -251,6 +253,23 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|             m_taintadd = true; | ||||
|             _parent_scene.AddPhysicsActorTaint(this); | ||||
|             //  don't do .add() here; old geoms get recycled with the same hash | ||||
|             // m_log.DebugFormat("[PHYSICS] Created ODEPrim: n={0}, m={1}, pbs={2}, phys={3}", | ||||
|             //     primName, mesh == null ? "NULL" : "DEFINED", pbs == null ? "NULL" : "DEFINED", pisPhysical); | ||||
|         } | ||||
| 
 | ||||
|         public override void RequestPhysicsterseUpdate() | ||||
|         { | ||||
|             if (PhysEngineToSceneConnectorModule.IsPhysEngineActorS) | ||||
|             { | ||||
|                 // if the values have changed and it was I who changed them, send an update | ||||
|                 // if (this.lastValues.Changed(this) && ChangingActorID == RegionSyncServerModule.ActorID) | ||||
|                 if (this.lastValues.Changed(this)) | ||||
|                     PhysEngineToSceneConnectorModule.RouteUpdate(this); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 base.RequestPhysicsterseUpdate(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public override int PhysicsActorType | ||||
|  | @ -270,6 +289,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|             set { | ||||
|                 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value); | ||||
|                 m_localID = value; } | ||||
|             get { return m_localID; } | ||||
|         } | ||||
| 
 | ||||
|         public override bool Grabbed | ||||
|  | @ -2280,6 +2300,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|             get { return _position; } | ||||
| 
 | ||||
|             set { _position = value; | ||||
|                 base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 //m_log.Info("[PHYSICS]: " + _position.ToString()); | ||||
|             } | ||||
|         } | ||||
|  | @ -2292,6 +2313,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|                 if (value.IsFinite()) | ||||
|                 { | ||||
|                     _size = value; | ||||
|                     base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | @ -2314,6 +2336,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|                 if (value.IsFinite()) | ||||
|                 { | ||||
|                     m_force = value; | ||||
|                     base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | @ -2372,6 +2395,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|             { | ||||
|                 _pbs = value; | ||||
|                 m_taintshape = true; | ||||
|                 base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -2394,6 +2418,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|             { | ||||
|                 if (value.IsFinite()) | ||||
|                 { | ||||
|                     base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                     _velocity = value; | ||||
| 
 | ||||
|                     m_taintVelocity = value; | ||||
|  | @ -2423,6 +2448,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|                 { | ||||
|                     m_taintTorque = value; | ||||
|                     _parent_scene.AddPhysicsActorTaint(this); | ||||
|                     base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|  | @ -2451,6 +2477,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|                 if (QuaternionIsFinite(value)) | ||||
|                 { | ||||
|                     _orientation = value; | ||||
|                     base.ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|                 } | ||||
|                 else | ||||
|                     m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name); | ||||
|  | @ -2629,7 +2656,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|                             _position = l_position; | ||||
|                             //_parent_scene.remActivePrim(this); | ||||
|                             if (_parent == null) | ||||
|                                 base.RequestPhysicsterseUpdate(); | ||||
|                                 this.RequestPhysicsterseUpdate(); | ||||
|                             return; | ||||
|                         } | ||||
|                         else | ||||
|  | @ -2664,7 +2691,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|                         m_rotationalVelocity.Z = 0; | ||||
| 
 | ||||
|                         if (_parent == null) | ||||
|                             base.RequestPhysicsterseUpdate(); | ||||
|                             this.RequestPhysicsterseUpdate(); | ||||
| 
 | ||||
|                         m_throttleUpdates = false; | ||||
|                         throttleCounter = 0; | ||||
|  | @ -2717,7 +2744,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
| 
 | ||||
|                             if (_parent == null) | ||||
|                             { | ||||
|                                 base.RequestPhysicsterseUpdate(); | ||||
|                                 this.RequestPhysicsterseUpdate(); | ||||
|                             } | ||||
| 
 | ||||
|                             m_lastUpdateSent = true; | ||||
|  | @ -2729,7 +2756,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|                         { | ||||
|                             if (_parent == null) | ||||
|                             { | ||||
|                                 base.RequestPhysicsterseUpdate(); | ||||
|                                 this.RequestPhysicsterseUpdate(); | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|  | @ -2764,7 +2791,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
|                         { | ||||
|                             if (_parent == null) | ||||
|                             { | ||||
|                                 base.RequestPhysicsterseUpdate(); | ||||
|                                 this.RequestPhysicsterseUpdate(); | ||||
|                             } | ||||
|                         } | ||||
|                         else | ||||
|  |  | |||
|  | @ -2769,6 +2769,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|                                         //Watchdog.UpdateThread(); | ||||
|                                     } | ||||
| 
 | ||||
|                                     #region Ninja Joints | ||||
|                                     if (SupportsNINJAJoints) | ||||
|                                     { | ||||
|                                         // Create pending joints, if possible | ||||
|  | @ -2950,6 +2951,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
|                                             } | ||||
|                                         } | ||||
|                                     } | ||||
| #endregion Ninja Joints | ||||
| 
 | ||||
|                                     if (processedtaints) | ||||
| //Console.WriteLine("Simulate calls Clear of _taintedPrim list"); | ||||
|  |  | |||
|  | @ -0,0 +1,278 @@ | |||
| /* | ||||
|  * Copyright (c) Intel Corporation | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the Intel Corporation nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Reflection; | ||||
| using log4net; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| 
 | ||||
| namespace OpenSim.Region.Physics.PEPlugin | ||||
| { | ||||
| public class PECharacter : PhysicsActor | ||||
| { | ||||
|     private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|     private bool _stopped; | ||||
|     private Vector3 _size; | ||||
|     private PrimitiveBaseShape _pbs; | ||||
|     private uint _localID = 0; | ||||
|     private bool _grabbed; | ||||
|     private bool _selected; | ||||
|     private Vector3 _position; | ||||
|     private float _mass; | ||||
|     private Vector3 _force; | ||||
|     private Vector3 _velocity; | ||||
|     private Vector3 _torque; | ||||
|     private float _collisionScore; | ||||
|     private Vector3 _acceleration; | ||||
|     private Quaternion _orientation; | ||||
|     private int _physicsActorType; | ||||
|     private bool _isPhysical; | ||||
|     private bool _flying; | ||||
|     private bool _setAlwaysRun; | ||||
|     private bool _throttleUpdates; | ||||
|     private bool _isColliding; | ||||
|     private bool _collidingGround; | ||||
|     private bool _collidingObj; | ||||
|     private bool _floatOnWater; | ||||
|     private Vector3 _rotationalVelocity; | ||||
|     private bool _kinematic; | ||||
|     private float _buoyancy; | ||||
| 
 | ||||
|     private Vector3 _PIDTarget; | ||||
|     private bool _usePID; | ||||
|     private float _PIDTau; | ||||
|     private bool _useHoverPID; | ||||
|     private float _PIDHoverHeight; | ||||
|     private PIDHoverType _PIDHoverType; | ||||
|     private float _PIDHoverTao; | ||||
| 
 | ||||
|     public PECharacter(String avName, PEScene parent_scene, Vector3 pos,  | ||||
|                     CollisionLocker dode, Vector3 size, float pid_d, float pid_p,  | ||||
|                     float capsule_radius, float tensor, float density, float height_fudge_factor,  | ||||
|                     float walk_divisor, float rundivisor) | ||||
|     { | ||||
|         _position = pos; | ||||
|         _size = size; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     public override bool Stopped {  | ||||
|         get { return _stopped; }  | ||||
|     } | ||||
|     public override Vector3 Size {  | ||||
|         get { return _size; }  | ||||
|         set { _size = value; | ||||
|             Prop.Set(_localID, PropType.Size, _size); | ||||
|         }  | ||||
|     } | ||||
|     public override PrimitiveBaseShape Shape {  | ||||
|         set { _pbs = value;  | ||||
|             Prop.Set(_localID, PropType.Shape, _pbs); | ||||
|         }  | ||||
|     } | ||||
|     public override uint LocalID {  | ||||
|         set { _localID = value;  | ||||
|             Prop.Set(_localID, PropType.LocalID, _localID); | ||||
|         } | ||||
|         get { return _localID; } | ||||
|     } | ||||
|     public override bool Grabbed {  | ||||
|         set { _grabbed = value;  | ||||
|             m_log.Debug("[RPE] PEChar set Grabbed"); | ||||
|             Prop.Set(_localID, PropType.Grabbed, _grabbed); | ||||
|         }  | ||||
|     } | ||||
|     public override bool Selected {  | ||||
|         set { _selected = value;  | ||||
|             m_log.Debug("[RPE] PEChar set Selected"); | ||||
|             Prop.Set(_localID, PropType.Selected, _selected); | ||||
|         }  | ||||
|     } | ||||
|     public override void CrossingFailure() { return; } | ||||
|     public override void link(PhysicsActor obj) { return; } | ||||
|     public override void delink() { return; } | ||||
|     public override void LockAngularMotion(Vector3 axis) { return; } | ||||
| 
 | ||||
|     public override Vector3 Position {  | ||||
|         get { return _position; }  | ||||
|         set { _position = value;  | ||||
|             Prop.Set(_localID, PropType.Position, _position); | ||||
|         }  | ||||
|     } | ||||
|     public override float Mass {  | ||||
|         get { return _mass; }  | ||||
|     } | ||||
|     public override Vector3 Force {  | ||||
|         get { return _force; }  | ||||
|         set { _force = value;  | ||||
|             Prop.Set(_localID, PropType.Force, _force); | ||||
|         }  | ||||
|     } | ||||
| 
 | ||||
|     public override int VehicleType {  | ||||
|         get { return 0; }  | ||||
|         set { return; }  | ||||
|     } | ||||
|     public override void VehicleFloatParam(int param, float value) { } | ||||
|     public override void VehicleVectorParam(int param, Vector3 value) {} | ||||
|     public override void VehicleRotationParam(int param, Quaternion rotation) { } | ||||
|     public override void VehicleFlags(int param, bool remove) { } | ||||
| 
 | ||||
|     // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | ||||
|     public override void SetVolumeDetect(int param) { return; } | ||||
| 
 | ||||
|     public override Vector3 GeometricCenter { get { return Vector3.Zero; } } | ||||
|     public override Vector3 CenterOfMass { get { return Vector3.Zero; } } | ||||
|     public override Vector3 Velocity {  | ||||
|         get { return _velocity; }  | ||||
|         set { _velocity = value;  | ||||
|             Prop.Set(_localID, PropType.Velocity, _velocity); | ||||
|         }  | ||||
|     } | ||||
|     public override Vector3 Torque {  | ||||
|         get { return _torque; }  | ||||
|         set { _torque = value;  | ||||
|             Prop.Set(_localID, PropType.Torque, _torque); | ||||
|         }  | ||||
|     } | ||||
|     public override float CollisionScore {  | ||||
|         get { return _collisionScore; }  | ||||
|         set { _collisionScore = value;  | ||||
|             Prop.Set(_localID, PropType.CollisionScore, _collisionScore); | ||||
|         }  | ||||
|     } | ||||
|     public override Vector3 Acceleration {  | ||||
|         get { return _acceleration; }  | ||||
|     } | ||||
|     public override Quaternion Orientation {  | ||||
|         get { return _orientation; }  | ||||
|         set { _orientation = value;  | ||||
|             Prop.Set(_localID, PropType.Orientation, _orientation); | ||||
|         }  | ||||
|     } | ||||
|     public override int PhysicsActorType {  | ||||
|         get { return _physicsActorType; }  | ||||
|         set { _physicsActorType = value;  | ||||
|         }  | ||||
|     } | ||||
|     public override bool IsPhysical {  | ||||
|         get { return _isPhysical; }  | ||||
|         set { _isPhysical = value;  | ||||
|         }  | ||||
|     } | ||||
|     public override bool Flying {  | ||||
|         get { return _flying; }  | ||||
|         set { _flying = value;  | ||||
|         }  | ||||
|     } | ||||
|     public override bool  | ||||
|         SetAlwaysRun {  | ||||
|         get { return _setAlwaysRun; }  | ||||
|         set { _setAlwaysRun = value; }  | ||||
|     } | ||||
|     public override bool ThrottleUpdates {  | ||||
|         get { return _throttleUpdates; }  | ||||
|         set { _throttleUpdates = value; }  | ||||
|     } | ||||
|     public override bool IsColliding {  | ||||
|         get { return _isColliding; }  | ||||
|         set { _isColliding = value; }  | ||||
|     } | ||||
|     public override bool CollidingGround {  | ||||
|         get { return _collidingGround; }  | ||||
|         set { _collidingGround = value; }  | ||||
|     } | ||||
|     public override bool CollidingObj {  | ||||
|         get { return _collidingObj; }  | ||||
|         set { _collidingObj = value; }  | ||||
|     } | ||||
|     public override bool FloatOnWater {  | ||||
|         set { _floatOnWater = value; }  | ||||
|     } | ||||
|     public override Vector3 RotationalVelocity {  | ||||
|         get { return _rotationalVelocity; }  | ||||
|         set { _rotationalVelocity = value; }  | ||||
|     } | ||||
|     public override bool Kinematic {  | ||||
|         get { return _kinematic; }  | ||||
|         set { _kinematic = value; }  | ||||
|     } | ||||
|     public override float Buoyancy {  | ||||
|         get { return _buoyancy; }  | ||||
|         set { _buoyancy = value; }  | ||||
|     } | ||||
| 
 | ||||
|     // Used for MoveTo | ||||
|     public override Vector3 PIDTarget {  | ||||
|         set { _PIDTarget = value; }  | ||||
|     } | ||||
|     public override bool PIDActive {  | ||||
|         set { _usePID = value; }  | ||||
|     } | ||||
|     public override float PIDTau {  | ||||
|         set { _PIDTau = value; }  | ||||
|     } | ||||
| 
 | ||||
|     // Used for llSetHoverHeight and maybe vehicle height | ||||
|     // Hover Height will override MoveTo target's Z | ||||
|     public override bool PIDHoverActive {  | ||||
|         set { _useHoverPID = value; } | ||||
|     } | ||||
|     public override float PIDHoverHeight {  | ||||
|         set { _PIDHoverHeight = value; } | ||||
|     } | ||||
|     public override PIDHoverType PIDHoverType {  | ||||
|         set { _PIDHoverType = value; } | ||||
|     } | ||||
|     public override float PIDHoverTau {  | ||||
|         set { _PIDHoverTao = value; } | ||||
|     } | ||||
| 
 | ||||
|     // For RotLookAt | ||||
|     public override Quaternion APIDTarget { set { return; } } | ||||
|     public override bool APIDActive { set { return; } } | ||||
|     public override float APIDStrength { set { return; } } | ||||
|     public override float APIDDamping { set { return; } } | ||||
| 
 | ||||
|     public override void AddForce(Vector3 force, bool pushforce) {  | ||||
|     } | ||||
|     public override void AddAngularForce(Vector3 force, bool pushforce) {  | ||||
|     } | ||||
|     public override void SetMomentum(Vector3 momentum) {  | ||||
|     } | ||||
|     public override void SubscribeEvents(int ms) {  | ||||
|     } | ||||
|     public override void UnSubscribeEvents() {  | ||||
|     } | ||||
|     public override bool SubscribedEvents() {  | ||||
|         return false;  | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| } | ||||
|  | @ -0,0 +1,67 @@ | |||
| /* | ||||
|  * Copyright (c) Intel Corporation | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the Intel Corporation nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| using OpenMetaverse; | ||||
| 
 | ||||
| namespace OpenSim.Region.Physics.PEPlugin | ||||
| { | ||||
| public class PEPlugin : IPhysicsPlugin | ||||
| { | ||||
|     //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|     private PEScene _mScene; | ||||
| 
 | ||||
|     public PEPlugin() | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     public bool Init() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     public PhysicsScene GetScene(String sceneIdentifier) | ||||
|     { | ||||
|         if (_mScene == null) | ||||
|         { | ||||
|             _mScene = new PEScene(sceneIdentifier); | ||||
|         } | ||||
|         return (_mScene); | ||||
|     } | ||||
| 
 | ||||
|     public string GetName() | ||||
|     { | ||||
|         return ("RemotePhysicsEngine"); | ||||
|     } | ||||
| 
 | ||||
|     public void Dispose() | ||||
|     { | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -0,0 +1,296 @@ | |||
| /* | ||||
|  * Copyright (c) Intel Corporation | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the Intel Corporation nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| using System; | ||||
| using System.Reflection; | ||||
| using System.Collections.Generic; | ||||
| using System.Xml; | ||||
| using log4net; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule; | ||||
| 
 | ||||
| namespace OpenSim.Region.Physics.PEPlugin | ||||
| { | ||||
|     [Serializable] | ||||
| public sealed class PEPrim : PhysicsActor | ||||
| { | ||||
|     private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|     private bool _stopped; | ||||
|     private Vector3 _size; | ||||
|     private PrimitiveBaseShape _pbs; | ||||
|     private uint _localID = 0; | ||||
|     private bool _grabbed; | ||||
|     private bool _selected; | ||||
|     private Vector3 _position; | ||||
|     private float _mass; | ||||
|     private Vector3 _force; | ||||
|     private Vector3 _velocity; | ||||
|     private Vector3 _torque; | ||||
|     private float _collisionScore; | ||||
|     private Vector3 _acceleration; | ||||
|     private Quaternion _orientation; | ||||
|     private int _physicsActorType; | ||||
|     private bool _isPhysical; | ||||
|     private bool _flying; | ||||
|     private bool _setAlwaysRun; | ||||
|     private bool _throttleUpdates; | ||||
|     private bool _isColliding; | ||||
|     private bool _collidingGround; | ||||
|     private bool _collidingObj; | ||||
|     private bool _floatOnWater; | ||||
|     private Vector3 _rotationalVelocity; | ||||
|     private bool _kinematic; | ||||
|     private float _buoyancy; | ||||
| 
 | ||||
|     private Vector3 _PIDTarget; | ||||
|     private bool _usePID; | ||||
|     private float _PIDTau; | ||||
|     private bool _useHoverPID; | ||||
|     private float _PIDHoverHeight; | ||||
|     private PIDHoverType _PIDHoverType; | ||||
|     private float _PIDHoverTao; | ||||
| 
 | ||||
|     public PEPrim(String primName, PEScene parent_scene, Vector3 pos, Vector3 size, | ||||
|                        Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) | ||||
|     { | ||||
|         _position = pos; | ||||
|         _size = size; | ||||
|         _orientation = rotation; | ||||
|         // m_log.DebugFormat("[REMOTE PRIM ENGINE] PEPrim creation of {0}", primName); | ||||
|     } | ||||
|      | ||||
|     public override bool Stopped {  | ||||
|         get { return _stopped; }  | ||||
|     } | ||||
|     public override Vector3 Size {  | ||||
|         get { return _size; }  | ||||
|         set { _size = value; | ||||
|             // m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Size"); | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             Prop.Set(_localID, PropType.Size, _size); | ||||
|         }  | ||||
|     } | ||||
|     public override PrimitiveBaseShape Shape {  | ||||
|         set { _pbs = value;  | ||||
|             m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Shape"); | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             Prop.Set(_localID, PropType.Shape, _pbs); | ||||
|         }  | ||||
|     } | ||||
|     public override uint LocalID {  | ||||
|         set { _localID = value;  | ||||
|             // m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set LocalID"); | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             Prop.Set(_localID, PropType.LocalID, _localID); | ||||
|         } | ||||
|         get { return _localID; } | ||||
|     } | ||||
|     public override bool Grabbed {  | ||||
|         set { _grabbed = value;  | ||||
|             m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Grabbed"); | ||||
|             Prop.Set(_localID, PropType.Grabbed, _grabbed); | ||||
|         }  | ||||
|     } | ||||
|     public override bool Selected {  | ||||
|         set { _selected = value;  | ||||
|             m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Selected"); | ||||
|             Prop.Set(_localID, PropType.Selected, _selected); | ||||
|         }  | ||||
|     } | ||||
|     public override void CrossingFailure() { return; } | ||||
|     public override void link(PhysicsActor obj) { return; } | ||||
|     public override void delink() { return; } | ||||
|     public override void LockAngularMotion(Vector3 axis) { return; } | ||||
| 
 | ||||
|     public override Vector3 Position {  | ||||
|         get { return _position; }  | ||||
|         set { _position = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             // m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Position"); | ||||
|             Prop.Set(_localID, PropType.Position, _position); | ||||
|         }  | ||||
|     } | ||||
|     public override float Mass {  | ||||
|         get { return _mass; }  | ||||
|     } | ||||
|     public override Vector3 Force {  | ||||
|         get { return _force; }  | ||||
|         set { _force = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             // m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Force"); | ||||
|             Prop.Set(_localID, PropType.Force, _force); | ||||
|         }  | ||||
|     } | ||||
| 
 | ||||
|     public override int VehicleType {  | ||||
|         get { return 0; }  | ||||
|         set { return; }  | ||||
|     } | ||||
|     public override void VehicleFloatParam(int param, float value) { } | ||||
|     public override void VehicleVectorParam(int param, Vector3 value) {} | ||||
|     public override void VehicleRotationParam(int param, Quaternion rotation) { } | ||||
|     public override void VehicleFlags(int param, bool remove) { } | ||||
| 
 | ||||
|     // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | ||||
|     public override void SetVolumeDetect(int param) { return; } | ||||
| 
 | ||||
|     public override Vector3 GeometricCenter { get { return Vector3.Zero; } } | ||||
|     public override Vector3 CenterOfMass { get { return Vector3.Zero; } } | ||||
|     public override Vector3 Velocity {  | ||||
|         get { return _velocity; }  | ||||
|         set { _velocity = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             Prop.Set(_localID, PropType.Velocity, _velocity); | ||||
|         }  | ||||
|     } | ||||
|     public override Vector3 Torque {  | ||||
|         get { return _torque; }  | ||||
|         set { _torque = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             Prop.Set(_localID, PropType.Torque, _torque); | ||||
|         }  | ||||
|     } | ||||
|     public override float CollisionScore {  | ||||
|         get { return _collisionScore; }  | ||||
|         set { _collisionScore = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             Prop.Set(_localID, PropType.CollisionScore, _collisionScore); | ||||
|         }  | ||||
|     } | ||||
|     public override Vector3 Acceleration {  | ||||
|         get { return _acceleration; }  | ||||
|     } | ||||
|     public override Quaternion Orientation {  | ||||
|         get { return _orientation; }  | ||||
|         set { _orientation = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|             Prop.Set(_localID, PropType.Orientation, _orientation); | ||||
|         }  | ||||
|     } | ||||
|     public override int PhysicsActorType {  | ||||
|         get { return _physicsActorType; }  | ||||
|         set { _physicsActorType = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|         }  | ||||
|     } | ||||
|     public override bool IsPhysical {  | ||||
|         get { return _isPhysical; }  | ||||
|         set { _isPhysical = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|         }  | ||||
|     } | ||||
|     public override bool Flying {  | ||||
|         get { return _flying; }  | ||||
|         set { _flying = value;  | ||||
|             ChangingActorID = RegionSyncServerModule.ActorID; | ||||
|         }  | ||||
|     } | ||||
|     public override bool  | ||||
|         SetAlwaysRun {  | ||||
|         get { return _setAlwaysRun; }  | ||||
|         set { _setAlwaysRun = value; }  | ||||
|     } | ||||
|     public override bool ThrottleUpdates {  | ||||
|         get { return _throttleUpdates; }  | ||||
|         set { _throttleUpdates = value; }  | ||||
|     } | ||||
|     public override bool IsColliding {  | ||||
|         get { return _isColliding; }  | ||||
|         set { _isColliding = value; }  | ||||
|     } | ||||
|     public override bool CollidingGround {  | ||||
|         get { return _collidingGround; }  | ||||
|         set { _collidingGround = value; }  | ||||
|     } | ||||
|     public override bool CollidingObj {  | ||||
|         get { return _collidingObj; }  | ||||
|         set { _collidingObj = value; }  | ||||
|     } | ||||
|     public override bool FloatOnWater {  | ||||
|         set { _floatOnWater = value; }  | ||||
|     } | ||||
|     public override Vector3 RotationalVelocity {  | ||||
|         get { return _rotationalVelocity; }  | ||||
|         set { _rotationalVelocity = value; }  | ||||
|     } | ||||
|     public override bool Kinematic {  | ||||
|         get { return _kinematic; }  | ||||
|         set { _kinematic = value; }  | ||||
|     } | ||||
|     public override float Buoyancy {  | ||||
|         get { return _buoyancy; }  | ||||
|         set { _buoyancy = value; }  | ||||
|     } | ||||
| 
 | ||||
|     // Used for MoveTo | ||||
|     public override Vector3 PIDTarget {  | ||||
|         set { _PIDTarget = value; }  | ||||
|     } | ||||
|     public override bool PIDActive {  | ||||
|         set { _usePID = value; }  | ||||
|     } | ||||
|     public override float PIDTau {  | ||||
|         set { _PIDTau = value; }  | ||||
|     } | ||||
| 
 | ||||
|     // Used for llSetHoverHeight and maybe vehicle height | ||||
|     // Hover Height will override MoveTo target's Z | ||||
|     public override bool PIDHoverActive {  | ||||
|         set { _useHoverPID = value; } | ||||
|     } | ||||
|     public override float PIDHoverHeight {  | ||||
|         set { _PIDHoverHeight = value; } | ||||
|     } | ||||
|     public override PIDHoverType PIDHoverType {  | ||||
|         set { _PIDHoverType = value; } | ||||
|     } | ||||
|     public override float PIDHoverTau {  | ||||
|         set { _PIDHoverTao = value; } | ||||
|     } | ||||
| 
 | ||||
|     // For RotLookAt | ||||
|     public override Quaternion APIDTarget { set { return; } } | ||||
|     public override bool APIDActive { set { return; } } | ||||
|     public override float APIDStrength { set { return; } } | ||||
|     public override float APIDDamping { set { return; } } | ||||
| 
 | ||||
|     public override void AddForce(Vector3 force, bool pushforce) {  | ||||
|     } | ||||
|     public override void AddAngularForce(Vector3 force, bool pushforce) {  | ||||
|     } | ||||
|     public override void SetMomentum(Vector3 momentum) {  | ||||
|     } | ||||
|     public override void SubscribeEvents(int ms) {  | ||||
|     } | ||||
|     public override void UnSubscribeEvents() {  | ||||
|     } | ||||
|     public override bool SubscribedEvents() {  | ||||
|         return false;  | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -0,0 +1,203 @@ | |||
| /* | ||||
|  * Copyright (c) Intel Corporation | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions are met: | ||||
|  *     * Redistributions of source code must retain the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer. | ||||
|  *     * Redistributions in binary form must reproduce the above copyright | ||||
|  *       notice, this list of conditions and the following disclaimer in the | ||||
|  *       documentation and/or other materials provided with the distribution. | ||||
|  *     * Neither the name of the Intel Corporation nor the | ||||
|  *       names of its contributors may be used to endorse or promote products | ||||
|  *       derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||||
|  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
|  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||||
|  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
|  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
|  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Nini.Config; | ||||
| using log4net; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Region.Framework; | ||||
| using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule; | ||||
| 
 | ||||
| namespace OpenSim.Region.Physics.PEPlugin | ||||
| { | ||||
| public class PEScene : PhysicsScene | ||||
| { | ||||
|     private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||||
| 
 | ||||
|     private List<PECharacter> m_avatars = new List<PECharacter>(); | ||||
|     private List<PEPrim> m_prims = new List<PEPrim>(); | ||||
|     private float[] m_heightMap; | ||||
| 
 | ||||
|     public PEScene(string identifier) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     public override void Initialise(IMesher meshmerizer, IConfigSource config) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) | ||||
|     { | ||||
|         PECharacter actor = new PECharacter(avName, this, position, null, size, 0f, 0f, .5f, 1f, | ||||
|             1f, 1f, .5f, .5f); | ||||
|         m_avatars.Add(actor); | ||||
|         return actor; | ||||
|     } | ||||
| 
 | ||||
|     public override void RemoveAvatar(PhysicsActor actor) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             m_avatars.Remove((PECharacter)actor); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             m_log.WarnFormat("[RPE]: Attempt to remove avatar that is not in physics scene: {0}", e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public override void RemovePrim(PhysicsActor prim) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             m_prims.Remove((PEPrim)prim); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             m_log.WarnFormat("[RPE]: Attempt to remove prim that is not in physics scene: {0}", e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, | ||||
|                                               Vector3 size, Quaternion rotation)  // deprecated | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
|     public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, | ||||
|                                               Vector3 size, Quaternion rotation, bool isPhysical) | ||||
|     { | ||||
|         PEPrim prim = new PEPrim(primName, this, position, size, rotation, null, pbs, isPhysical, null); | ||||
|         m_prims.Add(prim); | ||||
|         return prim; | ||||
|     } | ||||
| 
 | ||||
|     public override void AddPhysicsActorTaint(PhysicsActor prim) { } | ||||
| 
 | ||||
|     public override float Simulate(float timeStep) | ||||
|     { | ||||
|         // if we are a physics engine server, send update information | ||||
|         if (SceneToPhysEngineSyncServer.IsPhysEngineScene2S()) | ||||
|         { | ||||
|             if (SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S()) | ||||
|             { | ||||
|                 // m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count); | ||||
|                 foreach (PEPrim prim in m_prims) | ||||
|                 { | ||||
|                     // if the values have changed and it was I who changed them, send an update | ||||
|                     if (prim.lastValues.Changed(prim) && prim.ChangingActorID == RegionSyncServerModule.ActorID) | ||||
|                     { | ||||
|                         SceneToPhysEngineSyncServer.RouteUpdate(prim); | ||||
|                     } | ||||
|                 } | ||||
|                 foreach (PECharacter actor in m_avatars) | ||||
|                 { | ||||
|                     // m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count); | ||||
|                     // if the values have changed and it was I who changed them, send an update | ||||
|                     if (actor.lastValues.Changed(actor) && actor.ChangingActorID == RegionSyncServerModule.ActorID) | ||||
|                     { | ||||
|                         SceneToPhysEngineSyncServer.RouteUpdate(actor); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return 60f; | ||||
|         } | ||||
|         /* | ||||
|         // code borrowed from BasicPhysics to do just avatar movement | ||||
|         foreach (PECharacter actor in m_avatars) | ||||
|         { | ||||
|             Vector3 actorPosition = actor.Position; | ||||
|             Vector3 actorVelocity = actor.Velocity; | ||||
| 
 | ||||
|             actorPosition.X += actor.Velocity.X*timeStep; | ||||
|             actorPosition.Y += actor.Velocity.Y*timeStep; | ||||
| 
 | ||||
|             actorPosition.Y = Math.Max(actorPosition.Y, 0.1f); | ||||
|             actorPosition.Y = Math.Min(actorPosition.Y, Constants.RegionSize - 0.1f); | ||||
|             actorPosition.X = Math.Max(actorPosition.X, 0.1f); | ||||
|             actorPosition.X = Math.Min(actorPosition.X, Constants.RegionSize - 0.1f); | ||||
| 
 | ||||
|             float height = 25.0F; | ||||
|             try | ||||
|             { | ||||
|                 height = m_heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z; | ||||
|             } | ||||
|             catch (OverflowException) | ||||
|             { | ||||
|                 m_log.WarnFormat("[RPE]: Actor out of range: {0}", actor.SOPName, actor.Position.ToString()); | ||||
|             } | ||||
| 
 | ||||
|             if (actor.Flying) | ||||
|             { | ||||
|                 if (actor.Position.Z + (actor.Velocity.Z*timeStep) < | ||||
|                     m_heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 2) | ||||
|                 { | ||||
|                     actorPosition.Z = height; | ||||
|                     actorVelocity.Z = 0; | ||||
|                     actor.IsColliding = true; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     actorPosition.Z += actor.Velocity.Z*timeStep; | ||||
|                     actor.IsColliding = false; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 actorPosition.Z = height; | ||||
|                 actorVelocity.Z = 0; | ||||
|                 actor.IsColliding = true; | ||||
|             } | ||||
| 
 | ||||
|             actor.Position = actorPosition; | ||||
|             actor.Velocity = actorVelocity; | ||||
|         } | ||||
|          */ | ||||
|         return 60f; // returns frames per second | ||||
|     } | ||||
| 
 | ||||
|     public override void GetResults() { } | ||||
| 
 | ||||
|     public override void SetTerrain(float[] heightMap) { | ||||
|         m_heightMap = heightMap; | ||||
|     } | ||||
| 
 | ||||
|     public override void SetWaterLevel(float baseheight) { } | ||||
| 
 | ||||
|     public override void DeleteTerrain() { } | ||||
| 
 | ||||
|     public override void Dispose() { } | ||||
| 
 | ||||
|     public override Dictionary<uint, float> GetTopColliders() | ||||
|     { | ||||
|         return new Dictionary<uint, float>(); | ||||
|     } | ||||
| 
 | ||||
|     public override bool IsThreaded { get { return false;  } } | ||||
| 
 | ||||
| } | ||||
| } | ||||
|  | @ -0,0 +1,46 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using OpenMetaverse; | ||||
| using OpenSim.Framework; | ||||
| using OpenSim.Region.Physics.Manager; | ||||
| 
 | ||||
| namespace OpenSim.Region.Physics.PEPlugin | ||||
| { | ||||
|     public enum PropType | ||||
|     { | ||||
|         Size, | ||||
|         Shape, | ||||
|         LocalID, | ||||
|         Grabbed, | ||||
|         Selected, | ||||
|         Position, | ||||
|         Force, | ||||
|         Velocity, | ||||
|         Torque, | ||||
|         CollisionScore, | ||||
|         Orientation | ||||
|     }; | ||||
| 
 | ||||
| public class Prop | ||||
| { | ||||
|     public static void Set(uint localID, PropType type, uint val) | ||||
|     { | ||||
|     } | ||||
|     public static void Set(uint localID, PropType type, Vector3 val) | ||||
|     { | ||||
|     } | ||||
|     public static void Set(uint localID, PropType type, PrimitiveBaseShape val) | ||||
|     { | ||||
|     } | ||||
|     public static void Set(uint localID, PropType type, bool val) | ||||
|     { | ||||
|     } | ||||
|     public static void Set(uint localID, PropType type, float val) | ||||
|     { | ||||
|     } | ||||
|     public static void Set(uint localID, PropType type, Quaternion val) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										36
									
								
								prebuild.xml
								
								
								
								
							
							
						
						
									
										36
									
								
								prebuild.xml
								
								
								
								
							|  | @ -562,6 +562,8 @@ | |||
|       <Reference name="OpenMetaverseTypes" path="../../../../bin/"/> | ||||
|       <Reference name="Nini" path="../../../../bin/"/> | ||||
|       <Reference name="OpenSim.Framework"/> | ||||
|       <Reference name="OpenSim.Region.CoreModules"/> | ||||
|       <Reference name="OpenSim.Region.Framework"/> | ||||
|       <Reference name="OpenSim.Framework.Console"/> | ||||
|       <Reference name="OpenSim.Region.Physics.Manager"/> | ||||
|       <Reference name="Ode.NET" path="../../../../bin/"/> | ||||
|  | @ -574,6 +576,38 @@ | |||
|       </Files> | ||||
|     </Project> | ||||
| 
 | ||||
|     <Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.PEPlugin" path="OpenSim/Region/Physics/PEPlugin" type="Library"> | ||||
|       <Configuration name="Debug"> | ||||
|         <Options> | ||||
|           <OutputPath>../../../../bin/Physics/</OutputPath> | ||||
|         </Options> | ||||
|       </Configuration> | ||||
|       <Configuration name="Release"> | ||||
|         <Options> | ||||
|           <OutputPath>../../../../bin/Physics/</OutputPath> | ||||
|         </Options> | ||||
|       </Configuration> | ||||
| 
 | ||||
|       <ReferencePath>../../../../bin/</ReferencePath> | ||||
|       <Reference name="System"/> | ||||
|       <Reference name="System.Core"/> | ||||
|       <Reference name="System.Xml"/> | ||||
|       <Reference name="OpenMetaverseTypes.dll"/> | ||||
|       <Reference name="Nini.dll" /> | ||||
|       <Reference name="OpenSim.Framework"/> | ||||
|       <Reference name="OpenSim.Region.Framework"/> | ||||
|       <Reference name="OpenSim.Region.CoreModules"/> | ||||
|       <Reference name="OpenSim.Framework.Console"/> | ||||
|       <Reference name="OpenSim.Region.Physics.Manager"/> | ||||
|       <Reference name="log4net.dll"/> | ||||
| 
 | ||||
|       <Files> | ||||
|         <Match pattern="*.cs" recurse="true"> | ||||
|           <Exclude name="Tests" pattern="Tests"/> | ||||
|         </Match> | ||||
|       </Files> | ||||
|     </Project> | ||||
| 
 | ||||
|     <Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.BulletXPlugin" path="OpenSim/Region/Physics/BulletXPlugin" type="Library"> | ||||
|       <Configuration name="Debug"> | ||||
|         <Options> | ||||
|  | @ -3192,6 +3226,8 @@ | |||
|       <Reference name="Nini" path="../../../../bin/"/> | ||||
|       <Reference name="OpenSim.Framework"/> | ||||
|       <Reference name="OpenSim.Framework.Console"/> | ||||
|       <Reference name="OpenSim.Region.CoreModules"/> | ||||
|       <Reference name="OpenSim.Region.Framework"/> | ||||
|       <Reference name="OpenSim.Region.Physics.Manager"/> | ||||
|       <Reference name="Ode.NET" path="../../../../bin/"/> | ||||
|       <Reference name="nunit.framework" path="../../../../bin/"/> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Dan Lake
						Dan Lake