Merge branch 'physics' into dev
commit
ce4b095a1a
|
@ -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)
|
if(!m_symSync)
|
||||||
{
|
{
|
||||||
m_scene.Heightmap.LoadFromXmlString(Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
|
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");
|
RegionSyncMessage.HandleSuccess(LogHeader(), msg, "Synchronized terrain");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -369,6 +370,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
UUID agentID = data["agentID"].AsUUID();
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
string first = data["first"].AsString();
|
string first = data["first"].AsString();
|
||||||
string last = data["last"].AsString();
|
string last = data["last"].AsString();
|
||||||
|
uint localID = data["localID"].AsUInteger();
|
||||||
Vector3 startPos = data["startPos"].AsVector3();
|
Vector3 startPos = data["startPos"].AsVector3();
|
||||||
if (agentID == null || agentID == UUID.Zero || first == null || last == null || startPos == null)
|
if (agentID == null || agentID == UUID.Zero || first == null || last == null || startPos == null)
|
||||||
{
|
{
|
||||||
|
@ -402,6 +404,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp.IsSyncedAvatar = true;
|
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.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));
|
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)
|
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);
|
OSDMap data = new OSDMap(3);
|
||||||
data["agentID"] = OSD.FromUUID(agentID);
|
data["agentID"] = OSD.FromUUID(agentID);
|
||||||
data["targetID"] = OSD.FromUUID(targetID);
|
data["targetID"] = OSD.FromUUID(targetID);
|
||||||
|
@ -978,7 +986,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
|
||||||
public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
|
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);
|
OSDMap data = new OSDMap(1);
|
||||||
data["agentID"] = OSD.FromUUID(agentID);
|
data["agentID"] = OSD.FromUUID(agentID);
|
||||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.AgentSit, OSDParser.SerializeJsonString(data)));
|
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)
|
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);
|
OSDMap data = new OSDMap(4);
|
||||||
data["agentID"] = OSD.FromUUID(remoteClient.AgentId);
|
data["agentID"] = OSD.FromUUID(remoteClient.AgentId);
|
||||||
data["localID"] = OSD.FromUInteger(localID);
|
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)
|
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);
|
OSDMap data = new OSDMap(5);
|
||||||
data["agentID"] = OSD.FromUUID(remoteClient.AgentId);
|
data["agentID"] = OSD.FromUUID(remoteClient.AgentId);
|
||||||
data["objectID"] = OSD.FromUUID(objectID);
|
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)
|
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);
|
OSDMap data = new OSDMap(3);
|
||||||
data["agentID"] = OSD.FromUUID(remoteClient.AgentId);
|
data["agentID"] = OSD.FromUUID(remoteClient.AgentId);
|
||||||
data["localID"] = OSD.FromUInteger(localID);
|
data["localID"] = OSD.FromUInteger(localID);
|
||||||
|
|
|
@ -339,6 +339,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
// Let the client managers know about this avatar
|
// Let the client managers know about this avatar
|
||||||
OSDMap data = new OSDMap(1);
|
OSDMap data = new OSDMap(1);
|
||||||
data["agentID"] = OSD.FromUUID(presence.ControllingClient.AgentId);
|
data["agentID"] = OSD.FromUUID(presence.ControllingClient.AgentId);
|
||||||
|
data["localID"] = OSD.FromUInteger(presence.LocalId);
|
||||||
data["first"] = OSD.FromString(presence.ControllingClient.FirstName);
|
data["first"] = OSD.FromString(presence.ControllingClient.FirstName);
|
||||||
data["last"] = OSD.FromString(presence.ControllingClient.LastName);
|
data["last"] = OSD.FromString(presence.ControllingClient.LastName);
|
||||||
data["startPos"] = OSD.FromVector3(presence.ControllingClient.StartPos);
|
data["startPos"] = OSD.FromVector3(presence.ControllingClient.StartPos);
|
||||||
|
@ -612,8 +613,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
}
|
}
|
||||||
UUID agentID = data["agentID"].AsUUID();
|
UUID agentID = data["agentID"].AsUUID();
|
||||||
UUID objectID = data["objectID"].AsUUID();
|
UUID objectID = data["objectID"].AsUUID();
|
||||||
m_log.DebugFormat("{0} GrabUpdate for {1}. ObjectID={2}",
|
// m_log.DebugFormat("{0} GrabUpdate for {1}. ObjectID={2}",
|
||||||
LogHeader, agentID.ToString(), objectID.ToString());
|
// LogHeader, agentID.ToString(), objectID.ToString());
|
||||||
Vector3 offset = data["offset"].AsVector3();
|
Vector3 offset = data["offset"].AsVector3();
|
||||||
Vector3 pos = data["pos"].AsVector3();
|
Vector3 pos = data["pos"].AsVector3();
|
||||||
OSDArray surfaceArray = (OSDArray)data["surfaceArgs"];
|
OSDArray surfaceArray = (OSDArray)data["surfaceArgs"];
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
@ -10,7 +11,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
{
|
{
|
||||||
Null,
|
Null,
|
||||||
ClientManager,
|
ClientManager,
|
||||||
ScriptEngine
|
ScriptEngine,
|
||||||
|
PhysicsEngine
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -107,6 +109,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
ScriptStateSyncEnd,
|
ScriptStateSyncEnd,
|
||||||
//Idle script engine overloaded -> overloaded script engine
|
//Idle script engine overloaded -> overloaded script engine
|
||||||
ScriptStateSyncRequest,
|
ScriptStateSyncRequest,
|
||||||
|
// Physics Engine -> Scene
|
||||||
|
PhysTerseUpdate,
|
||||||
|
PhysOutOfBounds,
|
||||||
|
PhysCollisionUpdate,
|
||||||
|
// Scene -> Physics Engine
|
||||||
|
PhysUpdateAttributes,
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -198,6 +206,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
{
|
{
|
||||||
return String.Format("{0} ({1} bytes)", m_type.ToString(), m_data.Length.ToString());
|
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
|
#endregion
|
||||||
|
|
||||||
public static void HandleSuccess(string header, RegionSyncMessage msg, string message)
|
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
|
public class RegionSyncServerModule : IRegionModule, IRegionSyncServerModule, ICommandableModule
|
||||||
{
|
{
|
||||||
private static int DefaultPort = 13000;
|
private static int DefaultPort = 13000;
|
||||||
|
public static string ActorID = "XX";
|
||||||
private static int PortUnknown = -1;
|
private static int PortUnknown = -1;
|
||||||
private static string IPAddrUnknown = "";
|
private static string IPAddrUnknown = "";
|
||||||
|
|
||||||
|
@ -76,6 +77,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
return;
|
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
|
// If syncConfig does not indicate "server", do not start up server mode
|
||||||
//string mode = syncConfig.GetString("Mode", "server").ToLower();
|
//string mode = syncConfig.GetString("Mode", "server").ToLower();
|
||||||
string mode = syncConfig.GetString("Mode", "").ToLower();
|
string mode = syncConfig.GetString("Mode", "").ToLower();
|
||||||
|
@ -112,6 +116,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
m_seSyncServerport = syncConfig.GetInt(seServerPort, PortUnknown);
|
m_seSyncServerport = syncConfig.GetInt(seServerPort, PortUnknown);
|
||||||
DefaultPort++;
|
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);
|
m_symsync = syncConfig.GetBoolean("SymSync", false);
|
||||||
|
|
||||||
//Get quark information
|
//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 = new SceneToScriptEngineSyncServer(m_scene, m_seSyncServeraddr, m_seSyncServerport);
|
||||||
m_sceneToSESyncServer.Start();
|
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");
|
//m_log.Warn("[REGION SYNC SERVER MODULE] Post-Initialised");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,6 +504,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
private string m_seSyncServeraddr;
|
private string m_seSyncServeraddr;
|
||||||
private int m_seSyncServerport;
|
private int m_seSyncServerport;
|
||||||
private SceneToScriptEngineSyncServer m_sceneToSESyncServer = null;
|
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
|
//a boolean variable to indicate in symmetric sync is configured
|
||||||
private bool m_symsync = false;
|
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
|
// Let the client managers know that a new agent has connected
|
||||||
OSDMap data = new OSDMap(1);
|
OSDMap data = new OSDMap(1);
|
||||||
data["agentID"] = OSD.FromUUID(client.AgentId);
|
data["agentID"] = OSD.FromUUID(client.AgentId);
|
||||||
|
data["localID"] = OSD.FromUInteger(m_scene.GetScenePresence(client.AgentId).LocalId);
|
||||||
data["first"] = OSD.FromString(client.FirstName);
|
data["first"] = OSD.FromString(client.FirstName);
|
||||||
data["last"] = OSD.FromString(client.LastName);
|
data["last"] = OSD.FromString(client.LastName);
|
||||||
data["startPos"] = OSD.FromVector3(client.StartPos);
|
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;
|
protected IScriptEngineToSceneConnectorModule m_scriptEngineToSceneConnectorModule;
|
||||||
|
|
||||||
|
|
||||||
public IScriptEngineToSceneConnectorModule ScriptEngineToSceneConnectorModule
|
public IScriptEngineToSceneConnectorModule ScriptEngineToSceneConnectorModule
|
||||||
{
|
{
|
||||||
get { return m_scriptEngineToSceneConnectorModule; }
|
get { return m_scriptEngineToSceneConnectorModule; }
|
||||||
|
@ -493,6 +491,46 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return IsSyncedServer();
|
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.
|
//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.
|
//If the object already exists, use the new copy to replace it.
|
||||||
|
@ -1368,6 +1406,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
RegionSyncServerModule = RequestModuleInterface<IRegionSyncServerModule>();
|
RegionSyncServerModule = RequestModuleInterface<IRegionSyncServerModule>();
|
||||||
RegionSyncClientModule = RequestModuleInterface<IRegionSyncClientModule>();
|
RegionSyncClientModule = RequestModuleInterface<IRegionSyncClientModule>();
|
||||||
ScriptEngineToSceneConnectorModule = RequestModuleInterface<IScriptEngineToSceneConnectorModule>();
|
ScriptEngineToSceneConnectorModule = RequestModuleInterface<IScriptEngineToSceneConnectorModule>();
|
||||||
|
PhysEngineToSceneConnectorModule = RequestModuleInterface<IPhysEngineToSceneConnectorModule>();
|
||||||
|
SceneToPhysEngineSyncServer = RequestModuleInterface<ISceneToPhysEngineServer>();
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//SYMMETRIC SYNC (KittyL: started 12/23/2010)
|
//SYMMETRIC SYNC (KittyL: started 12/23/2010)
|
||||||
|
@ -1576,7 +1616,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
int tmpPhysicsMS2 = Util.EnvironmentTickCount();
|
int tmpPhysicsMS2 = Util.EnvironmentTickCount();
|
||||||
// Do not simulate physics locally if this is a synced client
|
// Do not simulate physics locally if this is a synced client
|
||||||
//if (!IsSyncedClient())
|
//if (!IsSyncedClient())
|
||||||
if (IsSyncedServer())
|
if (IsSyncedServer() || this.IsPhysEngineActor())
|
||||||
{
|
{
|
||||||
if ((m_frame % m_update_physics == 0) && m_physics_enabled)
|
if ((m_frame % m_update_physics == 0) && m_physics_enabled)
|
||||||
m_sceneGraph.UpdatePreparePhysics();
|
m_sceneGraph.UpdatePreparePhysics();
|
||||||
|
@ -1585,7 +1625,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
// Do not simulate physics locally if this is a synced client
|
// Do not simulate physics locally if this is a synced client
|
||||||
//if (!IsSyncedClient())
|
//if (!IsSyncedClient())
|
||||||
if (IsSyncedServer())
|
if (IsSyncedServer() || this.IsPhysEngineActor())
|
||||||
{
|
{
|
||||||
if (m_frame % m_update_entitymovement == 0)
|
if (m_frame % m_update_entitymovement == 0)
|
||||||
m_sceneGraph.UpdateScenePresenceMovement();
|
m_sceneGraph.UpdateScenePresenceMovement();
|
||||||
|
@ -1596,7 +1636,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
int tmpPhysicsMS = Util.EnvironmentTickCount();
|
int tmpPhysicsMS = Util.EnvironmentTickCount();
|
||||||
// Do not simulate physics locally if this is a synced client
|
// Do not simulate physics locally if this is a synced client
|
||||||
//if (!IsSyncedClient())
|
//if (!IsSyncedClient())
|
||||||
if (IsSyncedServer())
|
if (IsSyncedServer() || this.IsPhysEngineActor())
|
||||||
{
|
{
|
||||||
if (m_frame % m_update_physics == 0)
|
if (m_frame % m_update_physics == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -457,7 +457,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
lock (m_updateList)
|
lock (m_updateList)
|
||||||
{
|
{
|
||||||
m_updateList[obj.UUID] = obj;
|
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 abstract class PhysicsActor
|
||||||
{
|
{
|
||||||
public delegate void RequestTerseUpdate();
|
public delegate void RequestTerseUpdate();
|
||||||
|
@ -142,7 +183,15 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
|
|
||||||
public abstract PrimitiveBaseShape Shape { set; }
|
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; }
|
public abstract bool Grabbed { set; }
|
||||||
|
|
||||||
|
@ -280,6 +329,7 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
public override uint LocalID
|
public override uint LocalID
|
||||||
{
|
{
|
||||||
set { return; }
|
set { return; }
|
||||||
|
get { return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Grabbed
|
public override bool Grabbed
|
||||||
|
|
|
@ -32,6 +32,7 @@ using OpenMetaverse;
|
||||||
using Ode.NET;
|
using Ode.NET;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.OdePlugin
|
namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
@ -202,6 +203,23 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
m_name = avName;
|
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
|
public override int PhysicsActorType
|
||||||
{
|
{
|
||||||
get { return (int) ActorTypes.Agent; }
|
get { return (int) ActorTypes.Agent; }
|
||||||
|
@ -220,6 +238,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public override uint LocalID
|
public override uint LocalID
|
||||||
{
|
{
|
||||||
set { m_localID = value; }
|
set { m_localID = value; }
|
||||||
|
get { return m_localID; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Grabbed
|
public override bool Grabbed
|
||||||
|
@ -408,6 +427,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
get { return _position; }
|
get { return _position; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
|
if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
if (value.IsFinite())
|
if (value.IsFinite())
|
||||||
|
@ -453,6 +473,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
|
get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
if (value.IsFinite())
|
if (value.IsFinite())
|
||||||
{
|
{
|
||||||
m_pidControllerActive = true;
|
m_pidControllerActive = true;
|
||||||
|
@ -774,6 +795,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
m_pidControllerActive = true;
|
m_pidControllerActive = true;
|
||||||
_target_velocity = value;
|
_target_velocity = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -830,6 +852,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
if (force.IsFinite())
|
if (force.IsFinite())
|
||||||
{
|
{
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
if (pushforce)
|
if (pushforce)
|
||||||
{
|
{
|
||||||
m_pidControllerActive = false;
|
m_pidControllerActive = false;
|
||||||
|
@ -1144,7 +1167,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
if (!m_lastUpdateSent)
|
if (!m_lastUpdateSent)
|
||||||
{
|
{
|
||||||
m_lastUpdateSent = true;
|
m_lastUpdateSent = true;
|
||||||
//base.RequestPhysicsterseUpdate();
|
// base.RequestPhysicsterseUpdate();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1182,6 +1205,10 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
m_hackSentFall = false;
|
m_hackSentFall = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!m_lastUpdateSent)
|
||||||
|
{
|
||||||
|
this.RequestPhysicsterseUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1348,7 +1375,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
_position.Z = m_taintPosition.Z;
|
_position.Z = m_taintPosition.Z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Console.WriteLine("ODECharacter: ProcessTaints: doing update");
|
||||||
|
this.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddCollisionFrameTime(int p)
|
internal void AddCollisionFrameTime(int p)
|
||||||
|
|
|
@ -47,7 +47,9 @@ using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using Ode.NET;
|
using Ode.NET;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
using OpenSim.Region.CoreModules.RegionSync.RegionSyncModule;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.OdePlugin
|
namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
|
@ -251,6 +253,23 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
m_taintadd = true;
|
m_taintadd = true;
|
||||||
_parent_scene.AddPhysicsActorTaint(this);
|
_parent_scene.AddPhysicsActorTaint(this);
|
||||||
// don't do .add() here; old geoms get recycled with the same hash
|
// 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
|
public override int PhysicsActorType
|
||||||
|
@ -270,6 +289,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
set {
|
set {
|
||||||
//m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
|
//m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
|
||||||
m_localID = value; }
|
m_localID = value; }
|
||||||
|
get { return m_localID; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Grabbed
|
public override bool Grabbed
|
||||||
|
@ -2280,6 +2300,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
get { return _position; }
|
get { return _position; }
|
||||||
|
|
||||||
set { _position = value;
|
set { _position = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
//m_log.Info("[PHYSICS]: " + _position.ToString());
|
//m_log.Info("[PHYSICS]: " + _position.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2292,6 +2313,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
if (value.IsFinite())
|
if (value.IsFinite())
|
||||||
{
|
{
|
||||||
_size = value;
|
_size = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2314,6 +2336,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
if (value.IsFinite())
|
if (value.IsFinite())
|
||||||
{
|
{
|
||||||
m_force = value;
|
m_force = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2372,6 +2395,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
_pbs = value;
|
_pbs = value;
|
||||||
m_taintshape = true;
|
m_taintshape = true;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2394,6 +2418,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
if (value.IsFinite())
|
if (value.IsFinite())
|
||||||
{
|
{
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
_velocity = value;
|
_velocity = value;
|
||||||
|
|
||||||
m_taintVelocity = value;
|
m_taintVelocity = value;
|
||||||
|
@ -2423,6 +2448,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
m_taintTorque = value;
|
m_taintTorque = value;
|
||||||
_parent_scene.AddPhysicsActorTaint(this);
|
_parent_scene.AddPhysicsActorTaint(this);
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2451,6 +2477,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
if (QuaternionIsFinite(value))
|
if (QuaternionIsFinite(value))
|
||||||
{
|
{
|
||||||
_orientation = value;
|
_orientation = value;
|
||||||
|
base.ChangingActorID = RegionSyncServerModule.ActorID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
|
m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
|
||||||
|
@ -2629,7 +2656,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
_position = l_position;
|
_position = l_position;
|
||||||
//_parent_scene.remActivePrim(this);
|
//_parent_scene.remActivePrim(this);
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2664,7 +2691,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
m_rotationalVelocity.Z = 0;
|
m_rotationalVelocity.Z = 0;
|
||||||
|
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
|
|
||||||
m_throttleUpdates = false;
|
m_throttleUpdates = false;
|
||||||
throttleCounter = 0;
|
throttleCounter = 0;
|
||||||
|
@ -2717,7 +2744,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
|
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
{
|
{
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastUpdateSent = true;
|
m_lastUpdateSent = true;
|
||||||
|
@ -2729,7 +2756,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
{
|
{
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2764,7 +2791,7 @@ Console.WriteLine(" JointCreateFixed");
|
||||||
{
|
{
|
||||||
if (_parent == null)
|
if (_parent == null)
|
||||||
{
|
{
|
||||||
base.RequestPhysicsterseUpdate();
|
this.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -2769,6 +2769,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
//Watchdog.UpdateThread();
|
//Watchdog.UpdateThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Ninja Joints
|
||||||
if (SupportsNINJAJoints)
|
if (SupportsNINJAJoints)
|
||||||
{
|
{
|
||||||
// Create pending joints, if possible
|
// Create pending joints, if possible
|
||||||
|
@ -2950,6 +2951,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion Ninja Joints
|
||||||
|
|
||||||
if (processedtaints)
|
if (processedtaints)
|
||||||
//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
|
//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="OpenMetaverseTypes" path="../../../../bin/"/>
|
||||||
<Reference name="Nini" path="../../../../bin/"/>
|
<Reference name="Nini" path="../../../../bin/"/>
|
||||||
<Reference name="OpenSim.Framework"/>
|
<Reference name="OpenSim.Framework"/>
|
||||||
|
<Reference name="OpenSim.Region.CoreModules"/>
|
||||||
|
<Reference name="OpenSim.Region.Framework"/>
|
||||||
<Reference name="OpenSim.Framework.Console"/>
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
<Reference name="OpenSim.Region.Physics.Manager"/>
|
<Reference name="OpenSim.Region.Physics.Manager"/>
|
||||||
<Reference name="Ode.NET" path="../../../../bin/"/>
|
<Reference name="Ode.NET" path="../../../../bin/"/>
|
||||||
|
@ -574,6 +576,38 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</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">
|
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.BulletXPlugin" path="OpenSim/Region/Physics/BulletXPlugin" type="Library">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
<Options>
|
<Options>
|
||||||
|
@ -3192,6 +3226,8 @@
|
||||||
<Reference name="Nini" path="../../../../bin/"/>
|
<Reference name="Nini" path="../../../../bin/"/>
|
||||||
<Reference name="OpenSim.Framework"/>
|
<Reference name="OpenSim.Framework"/>
|
||||||
<Reference name="OpenSim.Framework.Console"/>
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="OpenSim.Region.CoreModules"/>
|
||||||
|
<Reference name="OpenSim.Region.Framework"/>
|
||||||
<Reference name="OpenSim.Region.Physics.Manager"/>
|
<Reference name="OpenSim.Region.Physics.Manager"/>
|
||||||
<Reference name="Ode.NET" path="../../../../bin/"/>
|
<Reference name="Ode.NET" path="../../../../bin/"/>
|
||||||
<Reference name="nunit.framework" path="../../../../bin/"/>
|
<Reference name="nunit.framework" path="../../../../bin/"/>
|
||||||
|
|
Loading…
Reference in New Issue