Removed ScriptEngine to Scene asymmetric sync code, and LocX,LocY in SOG.
Also, removed QuickInfo related code from RegionSyncUtil.cs.dsg
parent
9b955d8e95
commit
a7d7ca9b0f
|
@ -97,16 +97,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
private long m_messagesSent = 0;
|
private long m_messagesSent = 0;
|
||||||
private long m_messagesReceived = 0;
|
private long m_messagesReceived = 0;
|
||||||
|
|
||||||
private QuarkSubsriptionInfo m_subscribedQuarks;
|
//private QuarkSubsriptionInfo m_subscribedQuarks;
|
||||||
|
|
||||||
|
|
||||||
private IConfig m_sysConfig;
|
private IConfig m_sysConfig;
|
||||||
|
|
||||||
//members for load balancing purpose
|
//members for load balancing purpose
|
||||||
//private TcpClient m_loadMigrationSouceEnd = null;
|
//private TcpClient m_loadMigrationSouceEnd = null;
|
||||||
private LoadMigrationEndPoint m_loadMigrationSouceEnd = null;
|
//private LoadMigrationEndPoint m_loadMigrationSouceEnd = null;
|
||||||
private Thread m_loadMigrationSrcRcvLoop;
|
private Thread m_loadMigrationSrcRcvLoop;
|
||||||
private LoadMigrationListener m_loadMigrationListener = null;
|
//private LoadMigrationListener m_loadMigrationListener = null;
|
||||||
|
|
||||||
//List of queued messages, when the space that the updated object is located is being migrated
|
//List of queued messages, when the space that the updated object is located is being migrated
|
||||||
private List<RegionSyncMessage> m_updateMsgQueue = new List<RegionSyncMessage>();
|
private List<RegionSyncMessage> m_updateMsgQueue = new List<RegionSyncMessage>();
|
||||||
|
@ -130,17 +130,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
SceneToPhysEngineSyncServer.logDir = m_sysConfig.GetString("PhysLogDir", ".");
|
SceneToPhysEngineSyncServer.logDir = m_sysConfig.GetString("PhysLogDir", ".");
|
||||||
|
|
||||||
//assume we are connecting to the whole scene as one big quark
|
//assume we are connecting to the whole scene as one big quark
|
||||||
m_subscribedQuarks = new QuarkSubsriptionInfo(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize);
|
//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
|
// Start the RegionSyncPhysEngine client thread
|
||||||
|
@ -195,21 +185,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
public void SetQuarkSubscription(QuarkSubsriptionInfo quarks)
|
||||||
{
|
{
|
||||||
m_subscribedQuarks = quarks;
|
m_subscribedQuarks = quarks;
|
||||||
}
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
public void RegisterIdle()
|
public void RegisterIdle()
|
||||||
{
|
{
|
||||||
|
@ -246,8 +227,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
|
||||||
//stop the migration connections
|
//stop the migration connections
|
||||||
//ShutdownClient(m_loadMigrationSouceEnd);
|
//ShutdownClient(m_loadMigrationSouceEnd);
|
||||||
if (m_loadMigrationListener != null)
|
//if (m_loadMigrationListener != null)
|
||||||
m_loadMigrationListener.Shutdown();
|
// m_loadMigrationListener.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReportStatus()
|
public void ReportStatus()
|
||||||
|
|
|
@ -107,17 +107,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
m_syncConfig = syncConfig;
|
m_syncConfig = syncConfig;
|
||||||
m_debugWithViewer = syncConfig.GetBoolean("PhysEngineDebugWithViewer", false);
|
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");
|
m_subscriptionSpaceString = syncConfig.GetString("InitSubscriptionSpace", "0_0,256_256");
|
||||||
|
|
||||||
|
|
||||||
|
@ -317,14 +306,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
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\"");
|
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");
|
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\"");
|
//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("quarksizeX", "The size on x axis of each quark", "Integer");
|
||||||
cmdSyncSetQuarkSize.AddArgument("quarksizeY", "The size on y 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("start", cmdSyncStart);
|
||||||
m_commander.RegisterCommand("stop", cmdSyncStop);
|
m_commander.RegisterCommand("stop", cmdSyncStop);
|
||||||
m_commander.RegisterCommand("status", cmdSyncStatus);
|
m_commander.RegisterCommand("status", cmdSyncStatus);
|
||||||
m_commander.RegisterCommand("quarkSpace", cmdSyncSetQuarks);
|
//m_commander.RegisterCommand("quarkSpace", cmdSyncSetQuarks);
|
||||||
|
|
||||||
lock (m_scene)
|
lock (m_scene)
|
||||||
{
|
{
|
||||||
|
@ -386,12 +375,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
InitPhysEngineToSceneConnector(m_subscriptionSpaceString);
|
InitPhysEngineToSceneConnector(m_subscriptionSpaceString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetQuarkSize(Object[] args)
|
|
||||||
{
|
|
||||||
QuarkInfo.SizeX = (int)args[0];
|
|
||||||
QuarkInfo.SizeY = (int)args[1];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitPhysEngineToSceneConnector(string space)
|
private void InitPhysEngineToSceneConnector(string space)
|
||||||
{
|
{
|
||||||
|
|
|
@ -119,12 +119,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
string peServerPort = scene.RegionInfo.RegionName + "_SceneToPESyncServerPort";
|
string peServerPort = scene.RegionInfo.RegionName + "_SceneToPESyncServerPort";
|
||||||
m_peSyncServerport = syncConfig.GetInt(peServerPort, DefaultPort);
|
m_peSyncServerport = syncConfig.GetInt(peServerPort, DefaultPort);
|
||||||
DefaultPort++;
|
DefaultPort++;
|
||||||
|
|
||||||
// m_symsync = syncConfig.GetBoolean("SymSync", false);
|
|
||||||
|
|
||||||
//Get quark information
|
|
||||||
QuarkInfo.SizeX = syncConfig.GetInt("QuarkSizeX", (int)Constants.RegionSize);
|
|
||||||
QuarkInfo.SizeY = syncConfig.GetInt("QuarkSizeY", (int)Constants.RegionSize);
|
|
||||||
|
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
m_scene.RegisterModuleInterface<IRegionSyncServerModule>(this);
|
m_scene.RegisterModuleInterface<IRegionSyncServerModule>(this);
|
||||||
|
@ -178,14 +172,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
m_statsTimer.Start();
|
m_statsTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_seSyncServeraddr.Equals(IPAddrUnknown) && m_seSyncServerport != PortUnknown)
|
|
||||||
{
|
|
||||||
m_log.Warn("[REGION SYNC SERVER MODULE] Starting SceneToScriptEngineSyncServer");
|
|
||||||
//Start the sync server for script engines
|
|
||||||
m_sceneToSESyncServer = new SceneToScriptEngineSyncServer(m_scene, m_seSyncServeraddr, m_seSyncServerport);
|
|
||||||
m_sceneToSESyncServer.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_peSyncServeraddr = m_scene.RegionInfo.PhysicsSyncServerAddress;
|
m_peSyncServeraddr = m_scene.RegionInfo.PhysicsSyncServerAddress;
|
||||||
m_peSyncServerport = m_scene.RegionInfo.PhysicsSyncServerPort;
|
m_peSyncServerport = m_scene.RegionInfo.PhysicsSyncServerPort;
|
||||||
if (!m_peSyncServeraddr.Equals(IPAddrUnknown) && m_peSyncServerport != PortUnknown)
|
if (!m_peSyncServeraddr.Equals(IPAddrUnknown) && m_peSyncServerport != PortUnknown)
|
||||||
|
@ -422,8 +408,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
//when an object is deleted, this function (DeleteObject) could be triggered more than once. So we check
|
//when an object is deleted, this function (DeleteObject) could be triggered more than once. So we check
|
||||||
//if the object part is already removed is the scene (part==null)
|
//if the object part is already removed is the scene (part==null)
|
||||||
//m_log.Debug("Inform script engine about the deleted object");
|
//m_log.Debug("Inform script engine about the deleted object");
|
||||||
if(m_sceneToSESyncServer!=null)
|
//if(m_sceneToSESyncServer!=null)
|
||||||
m_sceneToSESyncServer.SendToSE(rsm, part.ParentGroup);
|
// m_sceneToSESyncServer.SendToSE(rsm, part.ParentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -438,8 +424,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
//if (m_server == null || !m_server.Synced)
|
if (m_server == null || !m_server.Synced)
|
||||||
if((m_server == null || !m_server.Synced) && (m_sceneToSESyncServer==null || !m_sceneToSESyncServer.Synced))
|
//if((m_server == null || !m_server.Synced) && (m_sceneToSESyncServer==null || !m_sceneToSESyncServer.Synced))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -450,9 +436,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString());
|
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString());
|
||||||
if(m_server!=null)
|
if(m_server!=null)
|
||||||
m_server.Broadcast(msg);
|
m_server.Broadcast(msg);
|
||||||
//KittyL: added for SE
|
|
||||||
if(m_sceneToSESyncServer!=null)
|
|
||||||
m_sceneToSESyncServer.SendToAllConnectedSE(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region cruft
|
#region cruft
|
||||||
|
@ -514,7 +497,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
//Sync-server for script engines
|
//Sync-server for script engines
|
||||||
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 engines
|
//Sync-server for physics engines
|
||||||
private string m_peSyncServeraddr;
|
private string m_peSyncServeraddr;
|
||||||
|
@ -561,7 +544,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
SceneObjectGroup sog = (SceneObjectGroup)entity;
|
SceneObjectGroup sog = (SceneObjectGroup)entity;
|
||||||
m_server.BroadcastToCM(RegionSyncMessage.MsgType.NewObject, sog);
|
m_server.BroadcastToCM(RegionSyncMessage.MsgType.NewObject, sog);
|
||||||
|
|
||||||
m_sceneToSESyncServer.SendToSE(RegionSyncMessage.MsgType.NewObject, sog);
|
//m_sceneToSESyncServer.SendToSE(RegionSyncMessage.MsgType.NewObject, sog);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -582,7 +565,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
//m_server.Broadcast(rsm);
|
//m_server.Broadcast(rsm);
|
||||||
SceneObjectGroup sog = (SceneObjectGroup)copy;
|
SceneObjectGroup sog = (SceneObjectGroup)copy;
|
||||||
m_server.BroadcastToCM(RegionSyncMessage.MsgType.NewObject, sog);
|
m_server.BroadcastToCM(RegionSyncMessage.MsgType.NewObject, sog);
|
||||||
m_sceneToSESyncServer.SendToSE(RegionSyncMessage.MsgType.NewObject, sog);
|
//m_sceneToSESyncServer.SendToSE(RegionSyncMessage.MsgType.NewObject, sog);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -611,7 +594,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
//when an object is deleted, this function (DeleteObject) could be triggered more than once. So we check
|
//when an object is deleted, this function (DeleteObject) could be triggered more than once. So we check
|
||||||
//if the object part is already removed is the scene (part==null)
|
//if the object part is already removed is the scene (part==null)
|
||||||
//m_log.Debug("Inform script engine about the deleted object");
|
//m_log.Debug("Inform script engine about the deleted object");
|
||||||
m_sceneToSESyncServer.SendToSE(rsm, part.ParentGroup);
|
//m_sceneToSESyncServer.SendToSE(rsm, part.ParentGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -53,256 +53,5 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Quark operations
|
|
||||||
|
|
||||||
//Convert a list of quarks, each identified by "x_y", where (x,y) are the offset position (in a 256x256 scene) of the left-bottom corner, to a single string
|
|
||||||
public static string QuarkStringListToString(List<string> quarks)
|
|
||||||
{
|
|
||||||
string quarkString = "";
|
|
||||||
foreach (string quark in quarks)
|
|
||||||
{
|
|
||||||
quarkString += quark + ",";
|
|
||||||
}
|
|
||||||
//trim the last ','
|
|
||||||
char[] trimChar = {','};
|
|
||||||
return quarkString.TrimEnd(trimChar);
|
|
||||||
//return quarkString;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Convert a list of quarks, each identified by a QuarkInfo data structure, to a single string
|
|
||||||
public static string QuarkInfoToString(List<QuarkInfo> quarks)
|
|
||||||
{
|
|
||||||
string quarkString = "";
|
|
||||||
foreach (QuarkInfo quark in quarks)
|
|
||||||
{
|
|
||||||
quarkString += quark.QuarkStringRepresentation + ",";
|
|
||||||
}
|
|
||||||
//trim the last ','
|
|
||||||
char[] trimChar = { ',' };
|
|
||||||
return quarkString.TrimEnd(trimChar);
|
|
||||||
//return quarkString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<string> QuarkStringToStringList(string quarkString)
|
|
||||||
{
|
|
||||||
string[] data = quarkString.Split(new char[] { ',' });
|
|
||||||
List<string> quarkList = new List<string>(data);
|
|
||||||
|
|
||||||
return quarkList;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public static List<QuarkInfo> GetQuarkInfoList(List<string> quarkStringList, int quarkSizeX, int quarkSizeY)
|
|
||||||
public static List<QuarkInfo> GetQuarkInfoList(List<string> quarkStringList)
|
|
||||||
{
|
|
||||||
List<QuarkInfo> quarkInfoList = new List<QuarkInfo>();
|
|
||||||
foreach (string quarkString in quarkStringList)
|
|
||||||
{
|
|
||||||
QuarkInfo quark = new QuarkInfo(quarkString);
|
|
||||||
quarkInfoList.Add(quark);
|
|
||||||
}
|
|
||||||
return quarkInfoList;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public static List<QuarkInfo> GetAllQuarksInScene(int QuarkInfo.SizeX, int QuarkInfo.SizeY)
|
|
||||||
public static List<QuarkInfo> GetAllQuarksInScene()
|
|
||||||
{
|
|
||||||
List<QuarkInfo> quarkList = new List<QuarkInfo>();
|
|
||||||
int xSlots =(int) Constants.RegionSize / QuarkInfo.SizeX;
|
|
||||||
int ySlots = (int) Constants.RegionSize / QuarkInfo.SizeY;
|
|
||||||
|
|
||||||
for (int i = 0; i < xSlots; i++)
|
|
||||||
{
|
|
||||||
int posX = i * QuarkInfo.SizeX;
|
|
||||||
for (int j = 0; j < ySlots; j++)
|
|
||||||
{
|
|
||||||
int posY = j * QuarkInfo.SizeY;
|
|
||||||
QuarkInfo quark = new QuarkInfo(posX, posY);
|
|
||||||
quarkList.Add(quark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return quarkList;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public static List<string> GetAllQuarkStringInScene(int QuarkInfo.SizeX, int QuarkInfo.SizeY)
|
|
||||||
public static List<string> GetAllQuarkStringInScene()
|
|
||||||
{
|
|
||||||
List<string> quarkStringList = new List<string>();
|
|
||||||
int xSlots = (int)Constants.RegionSize / QuarkInfo.SizeX;
|
|
||||||
int ySlots = (int)Constants.RegionSize / QuarkInfo.SizeY;
|
|
||||||
|
|
||||||
for (int i = 0; i < xSlots; i++)
|
|
||||||
{
|
|
||||||
int posX = i * QuarkInfo.SizeX;
|
|
||||||
for (int j = 0; j < ySlots; j++)
|
|
||||||
{
|
|
||||||
int posY = j * QuarkInfo.SizeY;
|
|
||||||
string quarkString = "";
|
|
||||||
quarkString += posX + "_" + posY;
|
|
||||||
quarkStringList.Add(quarkString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return quarkStringList;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public static string GetQuarkIDByPosition(Vector3 pos, int QuarkInfo.SizeX, int QuarkInfo.SizeY)
|
|
||||||
public static string GetQuarkIDByPosition(Vector3 pos)
|
|
||||||
{
|
|
||||||
float x, y;
|
|
||||||
if (pos.X < 0)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
else if (pos.X >= Constants.RegionSize)
|
|
||||||
{
|
|
||||||
x = (int)Constants.RegionSize - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
x = pos.X;
|
|
||||||
|
|
||||||
if (pos.Y < 0)
|
|
||||||
{
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
else if (pos.Y >= Constants.RegionSize)
|
|
||||||
{
|
|
||||||
y = (int)Constants.RegionSize - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
y = pos.Y;
|
|
||||||
|
|
||||||
int xRange = (int) x / QuarkInfo.SizeX;
|
|
||||||
int yRange = (int) y / QuarkInfo.SizeY;
|
|
||||||
|
|
||||||
int quarkPosX = xRange * QuarkInfo.SizeX;
|
|
||||||
int quarkPosY = yRange * QuarkInfo.SizeY;
|
|
||||||
|
|
||||||
string qID = quarkPosX + "_" + quarkPosX;
|
|
||||||
return qID;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public static List<QuarkInfo> GetQuarkSubscriptions(int QuarkInfo.SizeX, int QuarkInfo.SizeY, int xmin, int ymin, int xmax, int ymax)
|
|
||||||
public static List<QuarkInfo> GetQuarkSubscriptions(int xmin, int ymin, int xmax, int ymax)
|
|
||||||
{
|
|
||||||
List<QuarkInfo> quarkList = new List<QuarkInfo>();
|
|
||||||
int xStart = (int)xmin / QuarkInfo.SizeX;
|
|
||||||
int yStart = (int)ymin / QuarkInfo.SizeY;
|
|
||||||
int xEnd = (int)xmax / QuarkInfo.SizeX;
|
|
||||||
int yEnd = (int)ymax / QuarkInfo.SizeY;
|
|
||||||
|
|
||||||
for (int i = xStart; i < xEnd; i++)
|
|
||||||
{
|
|
||||||
int posX = i * QuarkInfo.SizeX;
|
|
||||||
for (int j = yStart; j < yEnd; j++)
|
|
||||||
{
|
|
||||||
int posY = j * QuarkInfo.SizeY;
|
|
||||||
QuarkInfo quark = new QuarkInfo(posX, posY);
|
|
||||||
quarkList.Add(quark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return quarkList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int[] GetCornerCoordinates(string space)
|
|
||||||
{
|
|
||||||
if (space == "") return null;
|
|
||||||
string[] corners = space.Split(new char[] { ',' });
|
|
||||||
string leftBottom = corners[0];
|
|
||||||
string rightTop = corners[1];
|
|
||||||
string[] coordinates = leftBottom.Split(new char[] { '_' });
|
|
||||||
|
|
||||||
int [] results = new int[4];
|
|
||||||
results[0] = Convert.ToInt32(coordinates[0]);
|
|
||||||
results[1] = Convert.ToInt32(coordinates[1]);
|
|
||||||
coordinates = rightTop.Split(new char[] { '_' });
|
|
||||||
results[2] = Convert.ToInt32(coordinates[0]);
|
|
||||||
results[3] = Convert.ToInt32(coordinates[1]);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetSpaceStringRepresentationByCorners(int minX, int minY, int maxX, int maxY)
|
|
||||||
{
|
|
||||||
string spaceString = minX + "_" + minY+","+maxX+"_"+maxY;
|
|
||||||
return spaceString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Dictionary<string, int[]> BinarySpaceParition(int minX, int minY, int maxX, int maxY)
|
|
||||||
{
|
|
||||||
int xLen = maxX - minX;
|
|
||||||
int yLen = maxY - minY;
|
|
||||||
|
|
||||||
//We always return the half space that share the same right-top corner, (maxX, maxY), with the original space.
|
|
||||||
int upperPlainStartX, upperPlainStartY;
|
|
||||||
int upperPlainEndX = maxX, upperPlainEndY = maxY;
|
|
||||||
|
|
||||||
bool partitionOnX;
|
|
||||||
if (xLen >= yLen)
|
|
||||||
{
|
|
||||||
//partition along x axis
|
|
||||||
partitionOnX = true;
|
|
||||||
int partXLen = xLen / 2;
|
|
||||||
upperPlainStartX = minX + partXLen;
|
|
||||||
upperPlainStartY = minY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//partition along y axis
|
|
||||||
partitionOnX = false;
|
|
||||||
int partYLen = yLen / 2;
|
|
||||||
upperPlainStartY = minY + partYLen;
|
|
||||||
upperPlainStartX = minX;
|
|
||||||
}
|
|
||||||
Dictionary<string, int[]> partitionedSpace = new Dictionary<string, int[]>();
|
|
||||||
|
|
||||||
//upper plain refers to the right (if partition along x) or top (if partition along y) part
|
|
||||||
int[] upperPlain = new int[4];
|
|
||||||
upperPlain[0] = upperPlainStartX;
|
|
||||||
upperPlain[1] = upperPlainStartY;
|
|
||||||
upperPlain[2] = upperPlainEndX;
|
|
||||||
upperPlain[3] = upperPlainEndY;
|
|
||||||
|
|
||||||
int[] lowerPlain = new int[4];
|
|
||||||
if (partitionOnX)
|
|
||||||
{
|
|
||||||
lowerPlain[0] = minX;
|
|
||||||
lowerPlain[1] = minY;
|
|
||||||
lowerPlain[2] = upperPlainStartX;
|
|
||||||
lowerPlain[3] = maxY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lowerPlain[0] = minX;
|
|
||||||
lowerPlain[1] = minY;
|
|
||||||
lowerPlain[2] = maxX;
|
|
||||||
lowerPlain[3] = upperPlainStartY;
|
|
||||||
}
|
|
||||||
|
|
||||||
partitionedSpace.Add("lower", lowerPlain);
|
|
||||||
partitionedSpace.Add("upper", upperPlain);
|
|
||||||
|
|
||||||
return partitionedSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int[] RemoveSpace(int originMinX, int originMinY, int originMaxX, int originMaxY, int toRemoveMinX, int toRemoveMinY, int toRemoveMaxX, int toRemoveMaxY)
|
|
||||||
{
|
|
||||||
int[] remainingBox = new int[4];
|
|
||||||
remainingBox[0] = originMinX;
|
|
||||||
remainingBox[1] = originMinY;
|
|
||||||
if (originMinX == toRemoveMinX)
|
|
||||||
{
|
|
||||||
//partitioned along Y
|
|
||||||
remainingBox[2] = originMaxX;
|
|
||||||
remainingBox[3] = toRemoveMinY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//partitioned along X
|
|
||||||
remainingBox[2] = toRemoveMinX;
|
|
||||||
remainingBox[3] = originMaxY;
|
|
||||||
}
|
|
||||||
return remainingBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Quark operations
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,12 +147,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
//private int QuarkInfo.SizeX;
|
//private int QuarkInfo.SizeX;
|
||||||
//private int QuarkInfo.SizeY;
|
//private int QuarkInfo.SizeY;
|
||||||
//private List<QuarkInfo> m_quarkSubscriptions;
|
//private List<QuarkInfo> m_quarkSubscriptions;
|
||||||
|
/*
|
||||||
Dictionary<string, QuarkInfo> m_quarkSubscriptions;
|
Dictionary<string, QuarkInfo> m_quarkSubscriptions;
|
||||||
public Dictionary<string, QuarkInfo> QuarkSubscriptionList
|
public Dictionary<string, QuarkInfo> QuarkSubscriptionList
|
||||||
{
|
{
|
||||||
get { return m_quarkSubscriptions; }
|
get { return m_quarkSubscriptions; }
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -453,6 +454,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
//For simplicity, we assume the subscription sent by PhysEngine is legistimate (no overlapping with other script engines, etc)
|
//For simplicity, we assume the subscription sent by PhysEngine is legistimate (no overlapping with other script engines, etc)
|
||||||
private void HandleQuarkSubscription(RegionSyncMessage msg)
|
private void HandleQuarkSubscription(RegionSyncMessage msg)
|
||||||
{
|
{
|
||||||
|
@ -470,6 +472,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
m_quarkSubscriptions.Add(quark.QuarkStringRepresentation, quark);
|
m_quarkSubscriptions.Add(quark.QuarkStringRepresentation, quark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
private RegionSyncMessage PrepareObjectUpdateMessage(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
|
private RegionSyncMessage PrepareObjectUpdateMessage(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
|
||||||
{
|
{
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
|
|
||||||
//List of all quarks, each using the concatenation of x,y values of its left-bottom corners,
|
//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.
|
// where the x,y values are the offset position in the scene.
|
||||||
private Dictionary<string, QuarkInfo> m_quarksInScene = new Dictionary<string, QuarkInfo>();
|
//private Dictionary<string, QuarkInfo> m_quarksInScene = new Dictionary<string, QuarkInfo>();
|
||||||
|
|
||||||
private string LogHeader = "[SCENE TO PHYS ENGINE SYNC SERVER]";
|
private string LogHeader = "[SCENE TO PHYS ENGINE SYNC SERVER]";
|
||||||
|
|
||||||
|
@ -307,11 +307,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
// Constructor
|
// Constructor
|
||||||
public SceneToPhysEngineSyncServer(Scene scene, string addr, int port)
|
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 = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
//m_log.Warn(LogHeader + "Constructed");
|
//m_log.Warn(LogHeader + "Constructed");
|
||||||
|
@ -327,7 +322,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
m_allScenes.Add(m_scene);
|
m_allScenes.Add(m_scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
InitQuarksInScene();
|
//InitQuarksInScene();
|
||||||
SubscribeToEvents();
|
SubscribeToEvents();
|
||||||
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||||
InstallInterfaces();
|
InstallInterfaces();
|
||||||
|
@ -376,15 +371,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
UnSubscribeToEvents();
|
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)
|
public void RegisterQuarkSubscription(List<QuarkInfo> quarkSubscriptions, SceneToPhysEngineConnector peConnector)
|
||||||
{
|
{
|
||||||
foreach (QuarkInfo quark in quarkSubscriptions)
|
foreach (QuarkInfo quark in quarkSubscriptions)
|
||||||
|
@ -395,6 +382,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
m_log.Debug(LogHeader + ": " + quarkID + " subscribed by "+peConnector.Description);
|
m_log.Debug(LogHeader + ": " + quarkID + " subscribed by "+peConnector.Description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
* */
|
||||||
|
|
||||||
// Add a connector to a physics engine
|
// Add a connector to a physics engine
|
||||||
public void AddSyncedPhysEngine(SceneToPhysEngineConnector peConnector)
|
public void AddSyncedPhysEngine(SceneToPhysEngineConnector peConnector)
|
||||||
|
@ -524,9 +512,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||||
}
|
}
|
||||||
else
|
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
|
// TODO: connection of physics engine to quarks. Next line commented out
|
||||||
// SceneToPhysEngineConnector peConnector = m_quarksInScene[quarkID].PEConnector;
|
// SceneToPhysEngineConnector peConnector = m_quarksInScene[quarkID].PEConnector;
|
||||||
|
|
||||||
|
|
|
@ -1,662 +0,0 @@
|
||||||
/* Copyright 2011 (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.
|
|
||||||
* * The name of the copyright holder may not 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.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 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 SceneToScriptEngineConnector acts as a thread on the RegionSyncServer to handle incoming
|
|
||||||
// messages from ScriptEngineToSceneConnectors that run on Script Engines. It connects the
|
|
||||||
// authoratative Scene with remote script engines.
|
|
||||||
public class SceneToScriptEngineConnector
|
|
||||||
{
|
|
||||||
#region SceneToScriptEngineConnector 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 SceneToScriptEngineSyncServer 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("[SceneToScriptEngineConnector #{0}]", m_connection_number);
|
|
||||||
return String.Format("[SceneToScriptEngineConnector #{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("RegionSyncScriptAPI #{0}", m_connection_number);
|
|
||||||
return String.Format("RegionSyncScriptAPI #{0} ({1:10})", m_connection_number, m_regionName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ConnectionNum
|
|
||||||
{
|
|
||||||
get { return m_connection_number; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetStats()
|
|
||||||
{
|
|
||||||
int syncedAvCount;
|
|
||||||
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}]",
|
|
||||||
//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 SceneToScriptEngineConnector(int num, Scene scene, TcpClient client, SceneToScriptEngineSyncServer 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop the listening thread, disconnecting the RegionSyncScriptEngine
|
|
||||||
public void Shutdown()
|
|
||||||
{
|
|
||||||
m_syncServer.RemoveSyncedScriptEngine(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 Script Engine
|
|
||||||
|
|
||||||
// Listen for messages from a RegionSyncClient
|
|
||||||
// *** This is the main thread loop for each connected client
|
|
||||||
private void ReceiveLoop()
|
|
||||||
{
|
|
||||||
// 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.QuarkSubscription:
|
|
||||||
HandleQuarkSubscription(msg);
|
|
||||||
return;
|
|
||||||
case RegionSyncMessage.MsgType.RegionName:
|
|
||||||
{
|
|
||||||
m_regionName = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
|
|
||||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.RegionName, m_scene.RegionInfo.RegionName));
|
|
||||||
RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Syncing to region \"{0}\"", m_regionName));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case RegionSyncMessage.MsgType.GetTerrain:
|
|
||||||
{
|
|
||||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString()));
|
|
||||||
RegionSyncMessage.HandleSuccess(LogHeader, msg, "Terrain sent");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case RegionSyncMessage.MsgType.GetObjects:
|
|
||||||
{
|
|
||||||
//List<EntityBase> entities = m_scene.GetEntities();
|
|
||||||
|
|
||||||
//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.
|
|
||||||
List<SceneObjectGroup> objectsInSpace = GetObjectsInGivenSpace(m_scene, m_quarkSubscriptions);
|
|
||||||
foreach (SceneObjectGroup sog in objectsInSpace)
|
|
||||||
{
|
|
||||||
Send(PrepareObjectUpdateMessage(RegionSyncMessage.MsgType.NewObject, sog));
|
|
||||||
}
|
|
||||||
RegionSyncMessage.HandleSuccess(LogHeader, msg, "Sent all scene objects");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case RegionSyncMessage.MsgType.SetObjectProperty:
|
|
||||||
{
|
|
||||||
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
|
|
||||||
if (!data.ContainsKey("UUID") || !data.ContainsKey("name"))
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("{0} Parameters missing in SetObjectProperty request, need \"UUID\", \"name\" (property-name), and \"valParams\" (property-value)", LogHeader);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UUID objID = data["UUID"].AsUUID();
|
|
||||||
string pName = data["name"].AsString();
|
|
||||||
//valParams
|
|
||||||
SetObjectProperty(objID, pName, data);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
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.AddSyncedScriptEngine(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": not supposed to received RegionSyncMessage.MsgType.ActorStatus==" + status.ToString());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("{0} Unable to handle unsupported message type", LogHeader);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//For simplicity, we assume the subscription sent by ScriptEngine 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)
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
}
|
|
||||||
catch (IOException)
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("{0} Script Engine has disconnected.", LogHeader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SendObjectUpdate(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
|
|
||||||
{
|
|
||||||
Send(PrepareObjectUpdateMessage(msgType, sog));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Send/Receive messages to/from the remote Script Engine
|
|
||||||
|
|
||||||
#region stub functions for remote actors to set object properties
|
|
||||||
|
|
||||||
//NOTE: the current implementation of setting various object properties is mimicking the way script engine sets object properties
|
|
||||||
// (i.e. as implemented in LSL_Api.cs. But the function calls are meant to be generic for all actors. We may need to change
|
|
||||||
// the implementation details later to accomdate more actors, and move it to the Scene implementation.
|
|
||||||
|
|
||||||
//TODO: These functions should eventually be part of DSG interface, rather than part of SceneToScriptEngineConnector.
|
|
||||||
|
|
||||||
private void SetObjectProperty(UUID primID, string pName, OSDMap valParams)
|
|
||||||
{
|
|
||||||
//m_log.Debug(LogHeader + " received SetObjectProperty request, " + primID + ", " + pName);
|
|
||||||
switch (pName)
|
|
||||||
{
|
|
||||||
case "object_rez":
|
|
||||||
//rez a new object, rather than update an existing object's property
|
|
||||||
RezObjectOnScene(primID, valParams);
|
|
||||||
break;
|
|
||||||
case "color":
|
|
||||||
SetPrimColor(primID, valParams);
|
|
||||||
break;
|
|
||||||
case "pos":
|
|
||||||
SetPrimPos(primID, valParams);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Triggered when an object is rez'ed by script. Followed the implementation in LSL_Api.llRezAtRoot().
|
|
||||||
//TODO: the real rez object part should be executed by Scene class, not here
|
|
||||||
private void RezObjectOnScene(UUID primID, OSDMap data)
|
|
||||||
{
|
|
||||||
if(data["inventory"] == null || data["pos"]==null || data["vel"] == null || data["rot"]==null || data["param"]==null){
|
|
||||||
m_log.Warn(LogHeader + ": not enough parameters for setting color on " + primID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
string inventory = data["inventory"].AsString();
|
|
||||||
Vector3 pos = data["pos"].AsVector3();
|
|
||||||
Vector3 vel = data["vel"].AsVector3();
|
|
||||||
Quaternion rot = data["rot"].AsQuaternion();
|
|
||||||
int param = data["param"].AsInteger();
|
|
||||||
SceneObjectPart primToFetchObject = m_scene.GetSceneObjectPart(primID);
|
|
||||||
|
|
||||||
if (primToFetchObject == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TaskInventoryDictionary partInventory = (TaskInventoryDictionary)primToFetchObject.TaskInventory.Clone();
|
|
||||||
|
|
||||||
foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
|
|
||||||
{
|
|
||||||
if (inv.Value.Name == inventory)
|
|
||||||
{
|
|
||||||
// make sure we're an object.
|
|
||||||
if (inv.Value.InvType != (int)InventoryType.Object)
|
|
||||||
{
|
|
||||||
//llSay(0, "Unable to create requested object. Object is missing from database.");
|
|
||||||
m_log.Warn(LogHeader + ": Unable to create requested object. Object is missing from database.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 llpos = pos;
|
|
||||||
Vector3 llvel = vel;
|
|
||||||
|
|
||||||
// need the magnitude later
|
|
||||||
float velmag = (float)Util.GetMagnitude(llvel);
|
|
||||||
|
|
||||||
SceneObjectGroup new_group = m_scene.RezObject(primToFetchObject, inv.Value, llpos, rot, llvel, param);
|
|
||||||
|
|
||||||
// If either of these are null, then there was an unknown error.
|
|
||||||
if (new_group == null)
|
|
||||||
continue;
|
|
||||||
if (new_group.RootPart == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// objects rezzed with this method are die_at_edge by default.
|
|
||||||
new_group.RootPart.SetDieAtEdge(true);
|
|
||||||
|
|
||||||
/*
|
|
||||||
m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
|
|
||||||
"object_rez", new Object[] {
|
|
||||||
new LSL_String(
|
|
||||||
new_group.RootPart.UUID.ToString()) },
|
|
||||||
new DetectParams[0]));
|
|
||||||
* */
|
|
||||||
//NOTE: should replace the above code with the following and implement TriggerRezObject. However, since
|
|
||||||
// nothing is really doen with "object_rez" in XEngine, we ignore posting the event for now.
|
|
||||||
//m_scene.EventManager.TriggerRezObject();
|
|
||||||
|
|
||||||
float groupmass = new_group.GetMass();
|
|
||||||
|
|
||||||
if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero)
|
|
||||||
{
|
|
||||||
//Recoil.
|
|
||||||
//llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
|
|
||||||
//copy the implementation of llApplyImpulse here.
|
|
||||||
Vector3 v = new Vector3(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass);
|
|
||||||
if (v.Length() > 20000.0f)
|
|
||||||
{
|
|
||||||
v.Normalize();
|
|
||||||
v = v * 20000.0f;
|
|
||||||
}
|
|
||||||
new_group.RootPart.ApplyImpulse(v, false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetPrimColor(UUID primID, OSDMap data)
|
|
||||||
{
|
|
||||||
if (!data.ContainsKey("color") || !data.ContainsKey("face"))
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": not enough parameters for setting color on " + primID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SceneObjectPart primToUpdate = m_scene.GetSceneObjectPart(primID);
|
|
||||||
if (primToUpdate == null)
|
|
||||||
return;
|
|
||||||
Vector3 color = data["color"].AsVector3();
|
|
||||||
int face = data["face"].AsInteger();
|
|
||||||
|
|
||||||
//m_log.DebugFormat("{0}: Set Color request, to set ({1}) on face {2}", LogHeader, color.ToString(), face);
|
|
||||||
|
|
||||||
primToUpdate.SetFaceColor(color, face);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Whichever actor that triggers this function call shall have already checked the legitimacy of the position.
|
|
||||||
private void SetPrimPos(UUID primID, OSDMap data)
|
|
||||||
{
|
|
||||||
if (!data.ContainsKey("pos"))
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": not enough parameters for setting pos on " + primID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Vector3 pos = data["pos"].AsVector3();
|
|
||||||
SceneObjectPart primToUpdate = m_scene.GetSceneObjectPart(primID);
|
|
||||||
|
|
||||||
if (primToUpdate == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SceneObjectGroup parent = primToUpdate.ParentGroup;
|
|
||||||
|
|
||||||
if (parent.RootPart == primToUpdate)
|
|
||||||
{
|
|
||||||
//the prim is the root-part of the object group, set the position of the whole group
|
|
||||||
parent.UpdateGroupPosition(pos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//the prim is not the root-part, set the offset position
|
|
||||||
primToUpdate.OffsetPosition = pos;
|
|
||||||
parent.HasGroupChanged = true;
|
|
||||||
//parent.ScheduleGroupForTerseUpdate();
|
|
||||||
parent.ScheduleGroupForTerseUpdate(new List<SceneObjectPartSyncProperties>(){SceneObjectPartSyncProperties.OffsetPosition});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Event Handlers
|
|
||||||
//calling by SceneToSESyncServer
|
|
||||||
public void SEConnectorOnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource)
|
|
||||||
{
|
|
||||||
m_log.Debug(LogHeader + ": Caught event OnRezScript, send message to Script Engine");
|
|
||||||
|
|
||||||
OSDMap data = new OSDMap(7);
|
|
||||||
data["localID"] = OSD.FromUInteger(localID);
|
|
||||||
data["itemID"] = OSD.FromUUID(itemID);
|
|
||||||
data["script"] = OSD.FromString(script);
|
|
||||||
data["startParam"] = OSD.FromInteger(startParam);
|
|
||||||
data["postOnRez"] = OSD.FromBoolean(postOnRez);
|
|
||||||
data["engine"] = OSD.FromString(engine);
|
|
||||||
data["stateSource"] = OSD.FromInteger(stateSource);
|
|
||||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.OnRezScript, OSDParser.SerializeJsonString(data)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SEConnectorOnScriptReset(uint localID, UUID itemID)
|
|
||||||
{
|
|
||||||
m_log.Debug(LogHeader + ": Caught event OnScriptReset, send message to Script Engine");
|
|
||||||
|
|
||||||
OSDMap data = new OSDMap(2);
|
|
||||||
data["localID"] = OSD.FromUInteger(localID);
|
|
||||||
data["itemID"] = OSD.FromUUID(itemID);
|
|
||||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.OnScriptReset, OSDParser.SerializeJsonString(data)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SEConnectorOnUpdateScript(UUID agentID, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
|
|
||||||
{
|
|
||||||
m_log.Debug(LogHeader + ": Caught event OnUpdateScript, send message to Script Engine");
|
|
||||||
|
|
||||||
OSDMap data = new OSDMap(5);
|
|
||||||
data["agentID"] = OSD.FromUUID(agentID);
|
|
||||||
data["itemID"] = OSD.FromUUID(itemId);
|
|
||||||
data["primID"] = OSD.FromUUID(primId);
|
|
||||||
data["running"] = OSD.FromBoolean(isScriptRunning);
|
|
||||||
data["assetID"] = OSD.FromUUID(newAssetID);
|
|
||||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.OnUpdateScript, OSDParser.SerializeJsonString(data)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Event Handlers
|
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,628 +0,0 @@
|
||||||
/* Copyright 2011 (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.
|
|
||||||
* * The name of the copyright holder may not 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.IO;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Text;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using OpenSim.Framework;
|
|
||||||
using OpenSim.Region.Framework.Scenes;
|
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
|
||||||
using log4net;
|
|
||||||
|
|
||||||
using OpenMetaverse;
|
|
||||||
using OpenMetaverse.StructuredData;
|
|
||||||
using OpenSim.Region.Framework.Scenes.Serialization;
|
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|
||||||
{
|
|
||||||
public class QuarkInfo
|
|
||||||
{
|
|
||||||
public static int SizeX = -1; //the length along X axis, should be same for all quarks, need to be set by either the SyncServer on Scene, or by an ActorToSceneConnectorModule.
|
|
||||||
public static int SizeY = -1; //the length along Y axis, should be same for all quarks
|
|
||||||
|
|
||||||
public int PosX = 0; //the offset position of the left-bottom corner (0~255)
|
|
||||||
public int PosY = 0;
|
|
||||||
|
|
||||||
private ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
||||||
private int maxX, maxY;
|
|
||||||
|
|
||||||
//this field is only meaning for the QuarkInfo records on the Scene side
|
|
||||||
private SceneToScriptEngineConnector m_seConnector=null;
|
|
||||||
public SceneToScriptEngineConnector SEConnector
|
|
||||||
{
|
|
||||||
get { return m_seConnector; }
|
|
||||||
set { m_seConnector = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private string m_quarkString = "";
|
|
||||||
public string QuarkStringRepresentation
|
|
||||||
{
|
|
||||||
get { return m_quarkString;}
|
|
||||||
}
|
|
||||||
|
|
||||||
//public QuarkInfo(int x, int y, int sizeX, int sizeY)
|
|
||||||
public QuarkInfo(int x, int y)
|
|
||||||
{
|
|
||||||
PosX = x;
|
|
||||||
PosY = y;
|
|
||||||
//SizeX = sizeX;
|
|
||||||
//SizeY = sizeY;
|
|
||||||
maxX = PosX + SizeX;
|
|
||||||
maxY = PosY + SizeY;
|
|
||||||
m_quarkString = PosX + "_" + PosY;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public QuarkInfo(string xy, int sizeX, int sizeY)
|
|
||||||
public QuarkInfo(string xy)
|
|
||||||
{
|
|
||||||
string[] coordinate = xy.Split(new char[] { '_' });
|
|
||||||
if (coordinate.Length < 2)
|
|
||||||
{
|
|
||||||
m_log.Warn("[QUARK INFO] QuarkInfo Constructor: missing x or y value, format expected x_y: " + xy);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PosX = Convert.ToInt32(coordinate[0]);
|
|
||||||
PosY = Convert.ToInt32(coordinate[1]);
|
|
||||||
//SizeX = sizeX;
|
|
||||||
//SizeY = sizeY;
|
|
||||||
maxX = PosX + SizeX;
|
|
||||||
maxY = PosY + SizeY;
|
|
||||||
m_quarkString = PosX + "_" + PosY;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public void SetPartitionedSceneInfo(int x, int y, int sizeX, int sizeY)
|
|
||||||
public void SetPartitionedSceneInfo(int x, int y)
|
|
||||||
{
|
|
||||||
PosX = x;
|
|
||||||
PosY = y;
|
|
||||||
//SizeX = sizeX;
|
|
||||||
//SizeY = sizeY;
|
|
||||||
maxX = PosX + SizeX;
|
|
||||||
maxY = PosY + SizeY;
|
|
||||||
m_quarkString = PosX + "_" + PosY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsPositionInQuarkSpace(Vector3 pos)
|
|
||||||
{
|
|
||||||
if (pos.X >= PosX && pos.X <= maxX && pos.Y >= PosY && pos.Y <= maxY)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Information of a registered idle script engine.
|
|
||||||
//Note, this is a temporary solution to inlcude idle script engines here.
|
|
||||||
//In the future, there might be a independent load balaner that keeps track
|
|
||||||
//of available idle hardware.
|
|
||||||
public class IdleScriptEngineInfo
|
|
||||||
{
|
|
||||||
public TcpClient TClient;
|
|
||||||
//public IPAddress ScriptEngineIPAddr;
|
|
||||||
//public int ScriptEnginePort;
|
|
||||||
public string ID;
|
|
||||||
|
|
||||||
//Will be used to store the overloaded SE that has send LB request and paired with this idle SE
|
|
||||||
public SceneToScriptEngineConnector AwaitOverloadedSE=null;
|
|
||||||
|
|
||||||
public IdleScriptEngineInfo(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 Script Engines.
|
|
||||||
public class SceneToScriptEngineSyncServer
|
|
||||||
{
|
|
||||||
#region SceneToScriptEngineSyncServer members
|
|
||||||
// Set the addr and port for TcpListener
|
|
||||||
private IPAddress m_addr;
|
|
||||||
private Int32 m_port;
|
|
||||||
|
|
||||||
private int seCounter;
|
|
||||||
|
|
||||||
// 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_scriptEngineConnector_lock = new object();
|
|
||||||
//private Dictionary<string, SceneToScriptEngineConnector> m_scriptEngineConnectors = new Dictionary<string, SceneToScriptEngineConnector>();
|
|
||||||
private List<SceneToScriptEngineConnector> m_scriptEngineConnectors = new List<SceneToScriptEngineConnector>();
|
|
||||||
|
|
||||||
//list of idle script engines that have registered.
|
|
||||||
private List<IdleScriptEngineInfo> m_idleScriptEngineList = new List<IdleScriptEngineInfo>();
|
|
||||||
|
|
||||||
//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 SCRIPT ENGINE SYNC SERVER]";
|
|
||||||
|
|
||||||
//Quark related info
|
|
||||||
//private int QuarkInfo.SizeX;
|
|
||||||
//private int QuarkInfo.SizeY;
|
|
||||||
|
|
||||||
// Check if any of the client views are in a connected state
|
|
||||||
public bool Synced
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (m_scriptEngineConnectors.Count > 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
public SceneToScriptEngineSyncServer(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;
|
|
||||||
|
|
||||||
InitQuarksInScene();
|
|
||||||
SubscribeToEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void SubscribeToEvents()
|
|
||||||
{
|
|
||||||
m_scene.EventManager.OnRezScript += SESyncServerOnRezScript;
|
|
||||||
m_scene.EventManager.OnScriptReset += SESyncServerOnScriptReset;
|
|
||||||
m_scene.EventManager.OnUpdateScript += SESyncServerOnUpdateScript;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UnSubscribeToEvents()
|
|
||||||
{
|
|
||||||
m_scene.EventManager.OnRezScript -= SESyncServerOnRezScript;
|
|
||||||
m_scene.EventManager.OnScriptReset -= SESyncServerOnScriptReset;
|
|
||||||
m_scene.EventManager.OnUpdateScript -= SESyncServerOnUpdateScript;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the server
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
m_listenerThread = new Thread(new ThreadStart(Listen));
|
|
||||||
m_listenerThread.Name = "SceneToScriptEngineSyncServer Listener";
|
|
||||||
m_log.WarnFormat(LogHeader + ": Starting {0} thread", m_listenerThread.Name);
|
|
||||||
m_listenerThread.Start();
|
|
||||||
//m_log.Warn("[REGION SYNC SERVER] Started");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Stop the server and disconnect all RegionSyncClients
|
|
||||||
public void Shutdown()
|
|
||||||
{
|
|
||||||
// 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 (SceneToScriptEngineConnector seConnector in m_scriptEngineConnectors)
|
|
||||||
{
|
|
||||||
seConnector.Shutdown();
|
|
||||||
}
|
|
||||||
m_scriptEngineConnectors.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, SceneToScriptEngineConnector seConnector)
|
|
||||||
{
|
|
||||||
foreach (QuarkInfo quark in quarkSubscriptions)
|
|
||||||
{
|
|
||||||
string quarkID = quark.QuarkStringRepresentation;
|
|
||||||
m_quarksInScene[quarkID].SEConnector = seConnector;
|
|
||||||
m_log.Debug(LogHeader + ": " + quarkID + " subscribed by "+seConnector.Description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a connector to a script engine
|
|
||||||
public void AddSyncedScriptEngine(SceneToScriptEngineConnector seConnector)
|
|
||||||
{
|
|
||||||
lock (m_scriptEngineConnector_lock)
|
|
||||||
{
|
|
||||||
//Dictionary<string, SceneToScriptEngineConnector> currentlist = m_scriptEngineConnectors;
|
|
||||||
//Dictionary<string, SceneToScriptEngineConnector> newlist = new Dictionary<string, SceneToScriptEngineConnector>(currentlist);
|
|
||||||
m_scriptEngineConnectors.Add(seConnector);
|
|
||||||
// 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_scriptEngineConnectors = newlist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the client view from the list and decrement synced client counter
|
|
||||||
public void RemoveSyncedScriptEngine(SceneToScriptEngineConnector seConnector)
|
|
||||||
{
|
|
||||||
lock (m_scriptEngineConnector_lock)
|
|
||||||
{
|
|
||||||
//Dictionary<string, SceneToScriptEngineConnector> currentlist = m_scriptEngineConnectors;
|
|
||||||
//Dictionary<string, SceneToScriptEngineConnector> newlist = new Dictionary<string, SceneToScriptEngineConnector>(currentlist);
|
|
||||||
m_scriptEngineConnectors.Remove(seConnector);
|
|
||||||
// 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_scriptEngineConnectors = 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;
|
|
||||||
|
|
||||||
ActorStatus actorStatus = GetActorStatus(tcpclient);
|
|
||||||
|
|
||||||
switch (actorStatus)
|
|
||||||
{
|
|
||||||
case ActorStatus.Sync:
|
|
||||||
// Add the SceneToScriptEngineConnector to the list
|
|
||||||
SceneToScriptEngineConnector sceneToSEConnector = new SceneToScriptEngineConnector(++seCounter, m_scene, tcpclient, this);
|
|
||||||
AddSyncedScriptEngine(sceneToSEConnector);
|
|
||||||
break;
|
|
||||||
case ActorStatus.Idle:
|
|
||||||
IdleScriptEngineInfo idleSE = new IdleScriptEngineInfo(tcpclient);
|
|
||||||
m_log.Debug(": adding an idle SE ("+addr+","+port+")");
|
|
||||||
m_idleScriptEngineList.Add(idleSE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SocketException e)
|
|
||||||
{
|
|
||||||
m_log.WarnFormat(LogHeader + " [Listen] SocketException: {0}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
public void RegisterSyncedScriptEngine(SceneToScriptEngineConnector sceneToSEConnector)
|
|
||||||
{
|
|
||||||
//first, remove it from the idle list
|
|
||||||
m_idleScriptEngineList.Remove(sceneToSEConnector);
|
|
||||||
|
|
||||||
//now, added to the synced SE list
|
|
||||||
AddSyncedScriptEngine(sceneToSEConnector);
|
|
||||||
}
|
|
||||||
* */
|
|
||||||
|
|
||||||
|
|
||||||
// Broadcast a message to all connected RegionSyncClients
|
|
||||||
public void SendToAllConnectedSE(RegionSyncMessage msg)
|
|
||||||
{
|
|
||||||
if (m_scriptEngineConnectors.Count > 0)
|
|
||||||
{
|
|
||||||
m_log.Debug(LogHeader + ": region " + m_scene.RegionInfo.RegionName + " Broadcast to ScriptEngine, msg " + msg.Type);
|
|
||||||
foreach (SceneToScriptEngineConnector seConnector in m_scriptEngineConnectors)
|
|
||||||
{
|
|
||||||
seConnector.Send(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//TO FINISH: Find the right SceneToSEConnector to forward the message
|
|
||||||
public void SendToSE(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
|
|
||||||
{
|
|
||||||
SceneToScriptEngineConnector seConnector = GetSceneToSEConnector(sog);
|
|
||||||
if (seConnector != null)
|
|
||||||
{
|
|
||||||
seConnector.SendObjectUpdate(msgType, sog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is to send a message, rsm, to script engine, and the message is about object SOG. E.g. RemovedObject
|
|
||||||
public void SendToSE(RegionSyncMessage rsm, SceneObjectGroup sog)
|
|
||||||
{
|
|
||||||
SceneToScriptEngineConnector seConnector = GetSceneToSEConnector(sog);
|
|
||||||
if (seConnector != null)
|
|
||||||
{
|
|
||||||
seConnector.Send(rsm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private SceneToScriptEngineConnector GetSceneToSEConnector(SceneObjectGroup sog)
|
|
||||||
{
|
|
||||||
if (m_scriptEngineConnectors.Count == 0)
|
|
||||||
return null;
|
|
||||||
if (sog == null)
|
|
||||||
{
|
|
||||||
return m_scriptEngineConnectors[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);
|
|
||||||
SceneToScriptEngineConnector seConnector = m_quarksInScene[quarkID].SEConnector;
|
|
||||||
|
|
||||||
if (seConnector == null)
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + sog.AbsolutePosition.ToString() + " not covered by any script engine");
|
|
||||||
}
|
|
||||||
|
|
||||||
return seConnector;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
private void SESyncServerOnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource)
|
|
||||||
{
|
|
||||||
SceneObjectGroup sog = m_scene.GetSceneObjectPart(localID).ParentGroup;
|
|
||||||
if (sog != null)
|
|
||||||
{
|
|
||||||
//First, figure out which script engine to forward the event
|
|
||||||
SceneToScriptEngineConnector seConnector = GetSceneToSEConnector(sog);
|
|
||||||
if (seConnector != null)
|
|
||||||
{
|
|
||||||
m_log.Debug(LogHeader + ": Caught event OnRezScript, send message to Script Engine " + seConnector.Description);
|
|
||||||
|
|
||||||
seConnector.SEConnectorOnRezScript(localID, itemID, script, startParam, postOnRez, engine, stateSource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SESyncServerOnScriptReset(uint localID, UUID itemID)
|
|
||||||
{
|
|
||||||
|
|
||||||
SceneObjectGroup sog = m_scene.GetSceneObjectPart(localID).ParentGroup;
|
|
||||||
if (sog != null)
|
|
||||||
{
|
|
||||||
//First, figure out which script engine to forward the event
|
|
||||||
SceneToScriptEngineConnector seConnector = GetSceneToSEConnector(sog);
|
|
||||||
if (seConnector != null)
|
|
||||||
{
|
|
||||||
m_log.Debug(LogHeader + ": Caught event OnScriptReset, send message to Script Engine " + seConnector.Description);
|
|
||||||
|
|
||||||
seConnector.SEConnectorOnScriptReset(localID, itemID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SESyncServerOnUpdateScript(UUID agentID, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
|
|
||||||
{
|
|
||||||
SceneObjectGroup sog = m_scene.GetSceneObjectPart(primId).ParentGroup;
|
|
||||||
if (sog != null)
|
|
||||||
{
|
|
||||||
//First, figure out which script engine to forward the event
|
|
||||||
SceneToScriptEngineConnector seConnector = GetSceneToSEConnector(sog);
|
|
||||||
if (seConnector != null)
|
|
||||||
{
|
|
||||||
m_log.Debug(LogHeader + ": Caught event OnScriptReset, send message to Script Engine " + seConnector.Description);
|
|
||||||
|
|
||||||
seConnector.SEConnectorOnUpdateScript(agentID, itemId, primId, isScriptRunning, newAssetID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Event Handlers
|
|
||||||
|
|
||||||
#region Load balancing members and functions
|
|
||||||
//keep track of idle script engines that are in the process of load balancing (they are off the idle list, but not a working script engine yet (not sync'ing with Scene yet)).
|
|
||||||
private Dictionary<string, IdleScriptEngineInfo> m_loadBalancingIdleSEs = new Dictionary<string,IdleScriptEngineInfo>();
|
|
||||||
public void HandleLoadBalanceRequest(SceneToScriptEngineConnector 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)
|
|
||||||
{
|
|
||||||
SceneToScriptEngineConnector seConnctor = (SceneToScriptEngineConnector)arg;
|
|
||||||
IdleScriptEngineInfo idleScriptEngineInfo = GetIdleScriptEngineConnector();
|
|
||||||
if (idleScriptEngineInfo != null)
|
|
||||||
{
|
|
||||||
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadMigrationNotice);
|
|
||||||
Send(idleScriptEngineInfo.TClient, msg.ToBytes());
|
|
||||||
m_log.Debug(LogHeader + ": HandleLoadBalanceRequest from " + seConnctor.Description + ", picked idle SE: " + idleScriptEngineInfo.ID);
|
|
||||||
|
|
||||||
//keep track of which overload script engine is paired up with which idle script engine
|
|
||||||
idleScriptEngineInfo.AwaitOverloadedSE = seConnctor;
|
|
||||||
m_loadBalancingIdleSEs.Add(idleScriptEngineInfo.ID, idleScriptEngineInfo);
|
|
||||||
|
|
||||||
m_log.Debug("ToSEConnector portal: local -" +
|
|
||||||
((IPEndPoint)idleScriptEngineInfo.TClient.Client.LocalEndPoint).Address.ToString() + ":" + ((IPEndPoint)idleScriptEngineInfo.TClient.Client.LocalEndPoint).Port
|
|
||||||
+ "; remote - " + ((IPEndPoint)idleScriptEngineInfo.TClient.Client.RemoteEndPoint).Address.ToString() + ":"
|
|
||||||
+ ((IPEndPoint)idleScriptEngineInfo.TClient.Client.RemoteEndPoint).Port);
|
|
||||||
|
|
||||||
//Now we expect the idle script engine to reply back
|
|
||||||
msg = new RegionSyncMessage(idleScriptEngineInfo.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 script engine to the idle engine, sync with the DB to update the state in DB
|
|
||||||
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 script engine
|
|
||||||
seConnctor.Send(new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceResponse, OSDParser.SerializeJsonString(data)));
|
|
||||||
|
|
||||||
m_log.Debug(LogHeader + " now remove script engine " + idleScriptEngineInfo.ID + " from idle SE list, and create SceneToScriptEngineConnector to it");
|
|
||||||
//create a SceneToSEConnector for the idle script engine, who will be sync'ing with this SyncServer soon
|
|
||||||
SceneToScriptEngineConnector sceneToSEConnector = new SceneToScriptEngineConnector(++seCounter, m_scene, idleScriptEngineInfo.TClient, this);
|
|
||||||
//Now remove the script engine from the idle SE list
|
|
||||||
m_idleScriptEngineList.Remove(idleScriptEngineInfo);
|
|
||||||
//AddSyncedScriptEngine(sceneToSEConnector);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
seConnctor.SendLoadBalanceRejection("no idle script 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} Script Engine has disconnected.", LogHeader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IdleScriptEngineInfo GetIdleScriptEngineConnector()
|
|
||||||
{
|
|
||||||
if (m_idleScriptEngineList.Count == 0)
|
|
||||||
return null;
|
|
||||||
IdleScriptEngineInfo idleSEInfo = m_idleScriptEngineList[0];
|
|
||||||
m_idleScriptEngineList.Remove(idleSEInfo);
|
|
||||||
return idleSEInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Load balancing functions
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,840 +0,0 @@
|
||||||
/* Copyright 2011 (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.
|
|
||||||
* * The name of the copyright holder may not 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 log4net;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|
||||||
{
|
|
||||||
//The information of the authoratative copy of a scene
|
|
||||||
public class AuthSceneInfo
|
|
||||||
{
|
|
||||||
public string Name;
|
|
||||||
public string Addr;
|
|
||||||
public int Port;
|
|
||||||
public int LocX=-1;
|
|
||||||
public int LocY=-1;
|
|
||||||
|
|
||||||
public AuthSceneInfo(string name, string addr, int port)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Addr = addr;
|
|
||||||
Port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthSceneInfo(string name, string addr, int port, int locX, int locY)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Addr = addr;
|
|
||||||
Port = port;
|
|
||||||
LocX = locX;
|
|
||||||
LocY = locY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//The connector that connects the local Scene (cache) and remote authoratative Scene
|
|
||||||
public class ScriptEngineToSceneConnectorModule : IRegionModule, IScriptEngineToSceneConnectorModule, ICommandableModule
|
|
||||||
{
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
m_log.Warn("[REGION SYNC SCRIPT ENGINE MODULE] No RegionSyncModule config section found. Shutting down.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!syncConfig.GetBoolean("Enabled", false))
|
|
||||||
{
|
|
||||||
m_log.Warn("[REGION SYNC SCRIPT ENGINE MODULE] RegionSyncModule is not enabled. Shutting down.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scene.RegionSyncEnabled = true;
|
|
||||||
m_regionSyncMode = syncConfig.GetString("Mode", "");
|
|
||||||
if (m_regionSyncMode == null || m_regionSyncMode.ToLower() != "script_engine")
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("[REGION SYNC SCRIPT ENGINE MODULE] RegionSyncModule is not in script_engine mode. Shutting down.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (syncConfig != null && syncConfig.GetString("Enabled", "").ToLower() == "true")
|
|
||||||
{
|
|
||||||
scene.RegionSyncEnabled = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scene.RegionSyncEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_regionSyncMode = syncConfig.GetString("Mode", "");
|
|
||||||
if (syncConfig == null || m_regionSyncMode == null || m_regionSyncMode.ToLower() != "script_engine")
|
|
||||||
{
|
|
||||||
m_log.Warn("[REGION SYNC SCRIPT ENGINE MODULE] Not in script_engine mode. Shutting down.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
* */
|
|
||||||
|
|
||||||
//get the name of the valid region for script engine, i.e., that region that will holds all objects and scripts
|
|
||||||
//if not matching m_scene's name, simply return
|
|
||||||
string validLocalScene = syncConfig.GetString("ValidScriptEngineScene", "");
|
|
||||||
if (!validLocalScene.Equals(scene.RegionInfo.RegionName))
|
|
||||||
{
|
|
||||||
m_log.Warn("Not the valid local scene, shutting down");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_active = true;
|
|
||||||
m_validLocalScene = validLocalScene;
|
|
||||||
|
|
||||||
m_log.Debug("Init SEToSceneConnectorModule, for local scene " + scene.RegionInfo.RegionName);
|
|
||||||
|
|
||||||
//get the number of regions this script engine subscribes
|
|
||||||
m_sceneNum = syncConfig.GetInt("SceneNumber", 1);
|
|
||||||
|
|
||||||
//get the mapping of local scenes to auth. scenes
|
|
||||||
List<string> authScenes = new List<string>();
|
|
||||||
for (int i = 0; i < m_sceneNum; i++)
|
|
||||||
{
|
|
||||||
string localScene = "LocalScene" + i;
|
|
||||||
string localSceneName = syncConfig.GetString(localScene, "");
|
|
||||||
string masterScene = localScene + "Master";
|
|
||||||
string masterSceneName = syncConfig.GetString(masterScene, "");
|
|
||||||
|
|
||||||
if (localSceneName.Equals("") || masterSceneName.Equals(""))
|
|
||||||
{
|
|
||||||
m_log.Warn(localScene + " or " + masterScene+ " has not been assigned a value in configuration. Shutting down.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//m_localToAuthSceneMapping.Add(localSceneName, masterSceneName);
|
|
||||||
RecordLocalAuthSceneMappings(localSceneName, masterSceneName);
|
|
||||||
authScenes.Add(masterSceneName);
|
|
||||||
m_localScenesByName.Add(localSceneName, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
int defaultPort = 13000;
|
|
||||||
//get the addr:port info of the authoritative scenes
|
|
||||||
for (int i = 0; i < m_sceneNum; i++)
|
|
||||||
{
|
|
||||||
string authSceneName = authScenes[i];
|
|
||||||
//string serverAddr = authSceneName + "_ServerIPAddress";
|
|
||||||
//string serverPort = authSceneName + "_ServerPort";
|
|
||||||
string serverAddr = authSceneName + "_SceneToSESyncServerIP";
|
|
||||||
string addr = syncConfig.GetString(serverAddr, "127.0.0.1");
|
|
||||||
string serverPort = authSceneName + "_SceneToSESyncServerPort";
|
|
||||||
int port = syncConfig.GetInt(serverPort, defaultPort);
|
|
||||||
defaultPort++;
|
|
||||||
|
|
||||||
AuthSceneInfo authSceneInfo = new AuthSceneInfo(authSceneName, addr, port);
|
|
||||||
m_authScenesInfoByName.Add(authSceneName, authSceneInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_scene = scene;
|
|
||||||
m_scene.RegisterModuleInterface<IScriptEngineToSceneConnectorModule>(this);
|
|
||||||
m_syncConfig = syncConfig;
|
|
||||||
m_debugWithViewer = syncConfig.GetBoolean("ScriptEngineDebugWithViewer", 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();
|
|
||||||
|
|
||||||
m_log.Warn("[REGION SYNC SCRIPT ENGINE MODULE] Initialised");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PostInitialise()
|
|
||||||
{
|
|
||||||
if (!m_active)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//m_log.Warn("[REGION SYNC CLIENT MODULE] Post-Initialised");
|
|
||||||
m_scene.EventManager.OnPopulateLocalSceneList += OnPopulateLocalSceneList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
if (m_active)
|
|
||||||
{
|
|
||||||
m_scene.EventManager.OnPopulateLocalSceneList -= OnPopulateLocalSceneList;
|
|
||||||
}
|
|
||||||
m_scene = null;
|
|
||||||
m_active = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get { return "RegionSyncScriptEngineModule"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSharedModule
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ICommandableModule Members
|
|
||||||
private readonly Commander m_commander = new Commander("sync");
|
|
||||||
public ICommander CommandInterface
|
|
||||||
{
|
|
||||||
get { return m_commander; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region IScriptEngineToSceneConnectorModule members
|
|
||||||
|
|
||||||
|
|
||||||
public bool Active
|
|
||||||
{
|
|
||||||
get { return m_active; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Synced
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
lock(m_client_lock)
|
|
||||||
{
|
|
||||||
//return (m_scriptEngineToSceneConnector != null);
|
|
||||||
return (m_SEToSceneConnectors.Count > 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ScriptEngineToSceneConnectorModule members and functions
|
|
||||||
|
|
||||||
private bool m_active = false;
|
|
||||||
private string m_serveraddr;
|
|
||||||
private int m_serverport;
|
|
||||||
private Scene m_scene;
|
|
||||||
private ILog m_log;
|
|
||||||
private Object m_client_lock = new Object();
|
|
||||||
//private ScriptEngineToSceneConnector m_scriptEngineToSceneConnector = null;
|
|
||||||
private IConfig m_syncConfig = null;
|
|
||||||
private bool m_debugWithViewer = false;
|
|
||||||
private string m_regionSyncMode = "";
|
|
||||||
|
|
||||||
//Variables relavant for multi-scene subscription.
|
|
||||||
private int m_sceneNum = 0;
|
|
||||||
private string m_validLocalScene = "";
|
|
||||||
private Dictionary<string, string> m_localToAuthSceneMapping = new Dictionary<string,string>(); //1-1 mapping from local shadow scene to authoratative scene
|
|
||||||
private Dictionary<string, string> m_authToLocalSceneMapping = new Dictionary<string, string>(); //1-1 mapping from authoratative scene to local shadow scene
|
|
||||||
private Dictionary<string, Scene> m_localScenesByName = new Dictionary<string,Scene>(); //name and references to local scenes
|
|
||||||
private Dictionary<string, AuthSceneInfo> m_authScenesInfoByName = new Dictionary<string,AuthSceneInfo>(); //info of each auth. scene's connector port, stored by each scene's name
|
|
||||||
private Dictionary<string, ScriptEngineToSceneConnector> m_SEToSceneConnectors = new Dictionary<string, ScriptEngineToSceneConnector>(); //connector for each auth. scene
|
|
||||||
private Dictionary<string, AuthSceneInfo> m_authScenesInfoByLoc = new Dictionary<string,AuthSceneInfo>(); //IP and port number of each auth. scene's connector port
|
|
||||||
private string LogHeader = "[ScriptEngineToSceneConnectorModule]";
|
|
||||||
private ScriptEngineToSceneConnector m_idleSEToSceneConnector = null;
|
|
||||||
|
|
||||||
//quark information
|
|
||||||
//private int QuarkInfo.SizeX;
|
|
||||||
//private int QuarkInfo.SizeY;
|
|
||||||
//private string m_quarkListString;
|
|
||||||
private string m_subscriptionSpaceString;
|
|
||||||
|
|
||||||
public IConfig SyncConfig
|
|
||||||
{
|
|
||||||
get { return m_syncConfig; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DebugWithViewer
|
|
||||||
{
|
|
||||||
get { return m_debugWithViewer; }
|
|
||||||
}
|
|
||||||
|
|
||||||
//Record the locX and locY of one auth. scene (identified by addr:port) this ScriptEngine connects to
|
|
||||||
public void RecordSceneLocation(string addr, int port, uint locX, uint locY)
|
|
||||||
{
|
|
||||||
string loc = SceneLocToString(locX, locY);
|
|
||||||
if (m_authScenesInfoByLoc.ContainsKey(loc))
|
|
||||||
{
|
|
||||||
m_log.Warn(": have already registered info for Scene at " + loc);
|
|
||||||
m_authScenesInfoByLoc.Remove(loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, AuthSceneInfo> valPair in m_authScenesInfoByName)
|
|
||||||
{
|
|
||||||
AuthSceneInfo authSceneInfo = valPair.Value;
|
|
||||||
if (authSceneInfo.Addr == addr && authSceneInfo.Port == port)
|
|
||||||
{
|
|
||||||
authSceneInfo.LocX = (int)locX;
|
|
||||||
authSceneInfo.LocY = (int)locY;
|
|
||||||
m_authScenesInfoByLoc.Add(loc, authSceneInfo);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the property of a prim located in the given scene (identified by locX, locY)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="locX"></param>
|
|
||||||
/// <param name="locY"></param>
|
|
||||||
/// <param name="primID"></param>
|
|
||||||
/// <param name="pName"></param>
|
|
||||||
/// <param name="pValue"></param>
|
|
||||||
public void SendSetPrimProperties(uint locX, uint locY, UUID primID, string pName, object pValue)
|
|
||||||
{
|
|
||||||
if (!Active || !Synced)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ScriptEngineToSceneConnector connector = GetSEToSceneConnector(locX, locY);
|
|
||||||
connector.SendSetPrimProperties(primID, pName, pValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Scene GetLocalScene(string authSceneName)
|
|
||||||
{
|
|
||||||
if (!m_authToLocalSceneMapping.ContainsKey(authSceneName))
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": no authoritative scene with name "+authSceneName+" recorded");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
string localSceneName = m_authToLocalSceneMapping[authSceneName];
|
|
||||||
if (m_localScenesByName.ContainsKey(localSceneName))
|
|
||||||
{
|
|
||||||
return m_localScenesByName[localSceneName];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string SceneLocToString(uint locX, uint locY)
|
|
||||||
{
|
|
||||||
string loc = locX + "-" + locY;
|
|
||||||
return loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get the right instance of ScriptEngineToSceneConnector, given the location of the authoritative scene
|
|
||||||
private ScriptEngineToSceneConnector GetSEToSceneConnector(uint locX, uint locY)
|
|
||||||
{
|
|
||||||
string loc = SceneLocToString(locX, locY);
|
|
||||||
if (!m_authScenesInfoByLoc.ContainsKey(loc))
|
|
||||||
return null;
|
|
||||||
string authSceneName = m_authScenesInfoByLoc[loc].Name;
|
|
||||||
if (!m_SEToSceneConnectors.ContainsKey(authSceneName))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return m_SEToSceneConnectors[authSceneName];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void RecordLocalAuthSceneMappings(string localSceneName, string authSceneName)
|
|
||||||
{
|
|
||||||
if (m_localToAuthSceneMapping.ContainsKey(localSceneName))
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": already registered " + localSceneName+", authScene was recorded as "+ m_localToAuthSceneMapping[localSceneName]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_localToAuthSceneMapping.Add(localSceneName, authSceneName);
|
|
||||||
}
|
|
||||||
if (m_authToLocalSceneMapping.ContainsKey(authSceneName))
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": already registered " + authSceneName + ", authScene was recorded as " + m_authToLocalSceneMapping[authSceneName]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_authToLocalSceneMapping.Add(authSceneName, localSceneName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get the name of the authoritative scene the given local scene maps to. Return null if not found.
|
|
||||||
private string GetAuthSceneName(string localSceneName)
|
|
||||||
{
|
|
||||||
if (m_localToAuthSceneMapping.ContainsKey(localSceneName))
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": " + localSceneName + " not registered in m_localToAuthSceneMapping");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return m_localToAuthSceneMapping[localSceneName];
|
|
||||||
}
|
|
||||||
|
|
||||||
//get the name of the local scene the given authoritative scene maps to. Return null if not found.
|
|
||||||
private string GetLocalSceneName(string authSceneName)
|
|
||||||
{
|
|
||||||
if (!m_authToLocalSceneMapping.ContainsKey(authSceneName))
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": " + authSceneName + " not registered in m_authToLocalSceneMapping");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return m_authToLocalSceneMapping[authSceneName];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Event Handlers
|
|
||||||
|
|
||||||
public void OnPopulateLocalSceneList(List<Scene> localScenes)
|
|
||||||
//public void OnPopulateLocalSceneList(List<Scene> localScenes, string[] cmdparams)
|
|
||||||
{
|
|
||||||
if (!Active)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//populate the dictionary m_localScenes
|
|
||||||
foreach (Scene lScene in localScenes)
|
|
||||||
{
|
|
||||||
string name = lScene.RegionInfo.RegionName;
|
|
||||||
if(!m_localScenesByName.ContainsKey(name)){
|
|
||||||
m_log.Warn(LogHeader+": has not reigstered a local scene named "+name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
m_localScenesByName[name] = lScene;
|
|
||||||
|
|
||||||
//lScene.RegionSyncMode = m_regionSyncMode;
|
|
||||||
lScene.IsOutsideScenes = IsOutSideSceneSubscriptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
//test position conversion
|
|
||||||
/*
|
|
||||||
//Vector3 pos = new Vector3(290, 100, 10);
|
|
||||||
uint preLocX = Convert.ToUInt32(cmdparams[2]);
|
|
||||||
uint preLocY = Convert.ToUInt32(cmdparams[3]);
|
|
||||||
float posX = (float)Convert.ToDouble(cmdparams[4]);
|
|
||||||
float posY = (float)Convert.ToDouble(cmdparams[5]);
|
|
||||||
float posZ = (float)Convert.ToDouble(cmdparams[6]);
|
|
||||||
Vector3 pos = new Vector3(posX, posY, posZ);
|
|
||||||
uint locX, locY;
|
|
||||||
Vector3 newPos;
|
|
||||||
ConvertPosition(1000, 1000, pos, out locX, out locY, out newPos);
|
|
||||||
* */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private string GetAllSceneNames()
|
|
||||||
{
|
|
||||||
string scenes = "";
|
|
||||||
foreach (KeyValuePair<string, Scene> valPair in m_localScenesByName)
|
|
||||||
{
|
|
||||||
Scene lScene = valPair.Value;
|
|
||||||
string authScene = m_localToAuthSceneMapping[lScene.RegionInfo.RegionName];
|
|
||||||
scenes += authScene + ",";
|
|
||||||
|
|
||||||
}
|
|
||||||
return scenes;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public bool IsOutSideSceneSubscriptions(Scene currentScene, Vector3 pos)
|
|
||||||
public bool IsOutSideSceneSubscriptions(uint locX, uint locY, Vector3 pos)
|
|
||||||
{
|
|
||||||
string sceneNames = GetAllSceneNames();
|
|
||||||
m_log.Debug(LogHeader + ": IsOutSideSceneSubscriptions called. Conceptually, we are checking inside scene-subscriptions: " + sceneNames);
|
|
||||||
|
|
||||||
//First, convert the position to a scene s.t. the attempting position is contained withing that scene
|
|
||||||
uint curLocX, curLocY;
|
|
||||||
Vector3 curPos;
|
|
||||||
bool converted = ConvertPosition(locX, locY, pos, out curLocX, out curLocY, out curPos);
|
|
||||||
|
|
||||||
if (!converted)
|
|
||||||
{
|
|
||||||
m_log.Warn("("+locX+","+locY+","+pos+")"+" converts to scenes with negative coordinates.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//See of the quark identified by (curLocX,curLocY) is one we subscribed to
|
|
||||||
string sceneLoc = SceneLocToString(curLocX, curLocY);
|
|
||||||
if (m_authScenesInfoByLoc.ContainsKey(sceneLoc))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//When the offset position is outside the range of current scene, convert it to the offset position in the right quark.
|
|
||||||
//Return null if the new scene's left-bottom corner X or Y value is negative.
|
|
||||||
//Assumption: A position is uniquely identified by (locX, locY, offsetPos).
|
|
||||||
private bool ConvertPosition(uint preLocX, uint preLocY, Vector3 prePos, out uint curLocX, out uint curLocY, out Vector3 curPos)
|
|
||||||
{
|
|
||||||
Vector3 newPos;
|
|
||||||
int newLocX;
|
|
||||||
int newLocY;
|
|
||||||
//code copied from EntityTransferModule.Cross()
|
|
||||||
|
|
||||||
newPos = prePos;
|
|
||||||
newLocX = (int)preLocX;
|
|
||||||
newLocY = (int)preLocY;
|
|
||||||
|
|
||||||
int changeX = 1;
|
|
||||||
int changeY = 1;
|
|
||||||
|
|
||||||
//Adjust the X values, if going east, changeX is positive, otherwise, it is negative
|
|
||||||
if (prePos.X >= 0)
|
|
||||||
{
|
|
||||||
changeX = (int)(prePos.X / (int)Constants.RegionSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
changeX = (int)(prePos.X / (int)Constants.RegionSize) - 1 ;
|
|
||||||
}
|
|
||||||
newLocX = (int)preLocX + changeX;
|
|
||||||
newPos.X = prePos.X - (changeX * Constants.RegionSize);
|
|
||||||
|
|
||||||
if (prePos.Y >= 0)
|
|
||||||
{
|
|
||||||
changeY = (int)(prePos.Y / (int)Constants.RegionSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
changeY = (int)(prePos.Y / (int)Constants.RegionSize) - 1;
|
|
||||||
}
|
|
||||||
changeY = (int)(prePos.Y / (int)Constants.RegionSize);
|
|
||||||
newLocY = (int)preLocY + changeY;
|
|
||||||
newPos.Y = prePos.Y - (changeY * Constants.RegionSize);
|
|
||||||
|
|
||||||
curLocX = (uint)newLocX;
|
|
||||||
curLocY = (uint)newLocY;
|
|
||||||
curPos = newPos;
|
|
||||||
|
|
||||||
if (newLocX < 0 || newLocY < 0)
|
|
||||||
{
|
|
||||||
//reset the position
|
|
||||||
curLocX = preLocX;
|
|
||||||
curLocY = preLocY;
|
|
||||||
if (newLocX < 0)
|
|
||||||
{
|
|
||||||
curPos.X = 2;
|
|
||||||
}
|
|
||||||
if(newLocY<0)
|
|
||||||
{
|
|
||||||
curPos.Y = 2;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void DebugSceneStats()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
/*
|
|
||||||
List<ScenePresence> avatars = m_scene.GetAvatars();
|
|
||||||
List<EntityBase> entities = m_scene.GetEntities();
|
|
||||||
m_log.WarnFormat("There are {0} avatars and {1} entities in the scene", avatars.Count, entities.Count);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Console Command Interface
|
|
||||||
//IMPORTANT: these functions should only be actived for the ScriptEngineToSceneConnectorModule 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");
|
|
||||||
|
|
||||||
Command cmdSyncRegister = new Command("register", CommandIntentions.COMMAND_HAZARDOUS, SyncRegister, "Register as an idle script engine. Sync'ing with Scene won't start until \"sync start\". ");
|
|
||||||
|
|
||||||
//For debugging load balancing and migration process
|
|
||||||
Command cmdSyncStartLB = new Command("startLB", CommandIntentions.COMMAND_HAZARDOUS, SyncStartLB, "Register as an idle script engine. Sync'ing with Scene won't start until \"sync start\". ");
|
|
||||||
|
|
||||||
m_commander.RegisterCommand("start", cmdSyncStart);
|
|
||||||
m_commander.RegisterCommand("stop", cmdSyncStop);
|
|
||||||
m_commander.RegisterCommand("status", cmdSyncStatus);
|
|
||||||
m_commander.RegisterCommand("quarkSpace", cmdSyncSetQuarks);
|
|
||||||
m_commander.RegisterCommand("register", cmdSyncRegister);
|
|
||||||
m_commander.RegisterCommand("startLB", cmdSyncStartLB);
|
|
||||||
|
|
||||||
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] == "sync")
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
//if (m_scriptEngineToSceneConnector != null)
|
|
||||||
if(m_SEToSceneConnectors.Count>0)
|
|
||||||
{
|
|
||||||
string authScenes = "";
|
|
||||||
foreach (KeyValuePair<string, ScriptEngineToSceneConnector> valPair in m_SEToSceneConnectors)
|
|
||||||
{
|
|
||||||
authScenes += valPair.Key + ", ";
|
|
||||||
}
|
|
||||||
m_log.WarnFormat(LogHeader+": Already synchronized to "+authScenes);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//m_log.Warn("[REGION SYNC CLIENT MODULE] Starting synchronization");
|
|
||||||
m_log.Warn(LogHeader + ": Starting RegionSyncScriptEngine");
|
|
||||||
|
|
||||||
if (m_sceneNum > 1)
|
|
||||||
{
|
|
||||||
//If there is no arguments following "sync start", then be default we will connect to one or more scenes.
|
|
||||||
//we need to create a connector to each authoritative scene
|
|
||||||
foreach (KeyValuePair<string, AuthSceneInfo> valPair in m_authScenesInfoByName)
|
|
||||||
{
|
|
||||||
string authSceneName = valPair.Key;
|
|
||||||
AuthSceneInfo authSceneInfo = valPair.Value;
|
|
||||||
|
|
||||||
//create a new connector, the local end of each connector, however, is linked to the ValidScene only,
|
|
||||||
//since all objects will be contained in this scene only
|
|
||||||
ScriptEngineToSceneConnector scriptEngineToSceneConnector = new ScriptEngineToSceneConnector(m_scene, authSceneInfo.Addr, authSceneInfo.Port, m_debugWithViewer, authSceneName, m_syncConfig);
|
|
||||||
if (scriptEngineToSceneConnector.Start())
|
|
||||||
{
|
|
||||||
m_SEToSceneConnectors.Add(authSceneName, scriptEngineToSceneConnector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Only one remote scene to connect to. Subscribe to whatever specified in the config file.
|
|
||||||
//List<string> quarkStringList = RegionSyncUtil.QuarkStringToStringList(m_quarkListString);
|
|
||||||
//InitScriptEngineToSceneConnector(quarkStringList);
|
|
||||||
InitScriptEngineToSceneConnector(m_subscriptionSpaceString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SyncRegister(Object[] args)
|
|
||||||
{
|
|
||||||
//This should not happen. No-validLocalScene should not have register handlers for the command
|
|
||||||
//if (m_scene.RegionInfo.RegionName != m_validLocalScene)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
//Registration only, no state sync'ing yet. So only start the connector for the validLocalScene. (For now, we only test this with one scene, and
|
|
||||||
//quarks are smaller than a 256x256 scene.
|
|
||||||
string authSceneName = m_localToAuthSceneMapping[m_validLocalScene];
|
|
||||||
AuthSceneInfo authSceneInfo = m_authScenesInfoByName[authSceneName];
|
|
||||||
m_idleSEToSceneConnector = new ScriptEngineToSceneConnector(m_scene, authSceneInfo.Addr, authSceneInfo.Port, m_debugWithViewer, authSceneName, m_syncConfig);
|
|
||||||
m_idleSEToSceneConnector.RegisterIdle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The given ScriptEngineToSceneConnector, after having connected to the Scene (called its Start()), will
|
|
||||||
/// call this function to remove it self as an idle connector, and to be recorded as one working connector.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="seToSceneConnector"></param>
|
|
||||||
public void RecordSyncStartAfterLoadMigration(ScriptEngineToSceneConnector seToSceneConnector)
|
|
||||||
{
|
|
||||||
foreach (KeyValuePair<string, AuthSceneInfo> valPair in m_authScenesInfoByName)
|
|
||||||
{
|
|
||||||
string authSceneName = valPair.Key;
|
|
||||||
AuthSceneInfo authSceneInfo = valPair.Value;
|
|
||||||
|
|
||||||
string localScene = m_authToLocalSceneMapping[authSceneName];
|
|
||||||
|
|
||||||
if (localScene != m_scene.RegionInfo.RegionName)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_SEToSceneConnectors.ContainsKey(authSceneName))
|
|
||||||
{
|
|
||||||
m_log.Warn(LogHeader + ": Connector to " + authSceneName + " is already considered connected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_SEToSceneConnectors.Add(authSceneName, seToSceneConnector);
|
|
||||||
//there should only be one element in the dictionary if we reach this loop, anyway, we break from it.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_idleSEToSceneConnector = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SyncStartLB(Object[] args)
|
|
||||||
{
|
|
||||||
string authSceneName = m_localToAuthSceneMapping[m_validLocalScene];
|
|
||||||
ScriptEngineToSceneConnector sceneConnector = m_SEToSceneConnectors[authSceneName];
|
|
||||||
sceneConnector.SendLoadBalanceRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetQuarkList(Object[] args)
|
|
||||||
{
|
|
||||||
m_subscriptionSpaceString = (string)args[0];
|
|
||||||
|
|
||||||
InitScriptEngineToSceneConnector(m_subscriptionSpaceString);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetQuarkSize(Object[] args)
|
|
||||||
{
|
|
||||||
QuarkInfo.SizeX = (int)args[0];
|
|
||||||
QuarkInfo.SizeY = (int)args[1];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitScriptEngineToSceneConnector(string space)
|
|
||||||
{
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, AuthSceneInfo> valPair in m_authScenesInfoByName)
|
|
||||||
{
|
|
||||||
string authSceneName = valPair.Key;
|
|
||||||
AuthSceneInfo authSceneInfo = valPair.Value;
|
|
||||||
|
|
||||||
string localScene = m_authToLocalSceneMapping[authSceneName];
|
|
||||||
|
|
||||||
if (localScene != m_scene.RegionInfo.RegionName)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//create a new connector, the local end of each connector, however, is set of the ValidScene only,
|
|
||||||
//since all objects will be contained in this scene only
|
|
||||||
ScriptEngineToSceneConnector scriptEngineToSceneConnector = new ScriptEngineToSceneConnector(m_scene, authSceneInfo.Addr, authSceneInfo.Port,
|
|
||||||
m_debugWithViewer, authSceneName, space, m_syncConfig);
|
|
||||||
if (scriptEngineToSceneConnector.Start())
|
|
||||||
{
|
|
||||||
m_SEToSceneConnectors.Add(authSceneName, scriptEngineToSceneConnector);
|
|
||||||
}
|
|
||||||
|
|
||||||
break; //there should only be one element in the dictionary if we reach this loop, anyway, we break from it.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SyncStop(Object[] args)
|
|
||||||
{
|
|
||||||
lock (m_client_lock)
|
|
||||||
{
|
|
||||||
//if (m_scriptEngineToSceneConnector == null)
|
|
||||||
if(m_SEToSceneConnectors.Count==0 && m_idleSEToSceneConnector==null)
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("[REGION SYNC SCRIPT ENGINE MODULE] Already stopped");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_SEToSceneConnectors.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (KeyValuePair<string, ScriptEngineToSceneConnector> valPair in m_SEToSceneConnectors)
|
|
||||||
{
|
|
||||||
ScriptEngineToSceneConnector connector = valPair.Value;
|
|
||||||
if (connector == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
connector.Stop();
|
|
||||||
}
|
|
||||||
m_SEToSceneConnectors.Clear();
|
|
||||||
}
|
|
||||||
else if (m_idleSEToSceneConnector != null)
|
|
||||||
{
|
|
||||||
m_idleSEToSceneConnector.Stop();
|
|
||||||
m_idleSEToSceneConnector = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//m_scriptEngineToSceneConnector.Stop();
|
|
||||||
//m_scriptEngineToSceneConnector = null;
|
|
||||||
m_log.Warn(LogHeader+": Stopping synchronization");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_authScenesInfoByLoc.Clear();
|
|
||||||
|
|
||||||
//save script state and stop script instances
|
|
||||||
m_scene.EventManager.TriggerScriptEngineSyncStop();
|
|
||||||
//remove all objects
|
|
||||||
m_scene.DeleteAllSceneObjects();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SyncStatus(Object[] args)
|
|
||||||
{
|
|
||||||
lock (m_client_lock)
|
|
||||||
{
|
|
||||||
if (m_SEToSceneConnectors.Count == 0)
|
|
||||||
{
|
|
||||||
m_log.WarnFormat("[REGION SYNC SCRIPT ENGINE MODULE] Not currently synchronized");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_log.WarnFormat("[REGION SYNC SCRIPT ENGINE MODULE] Synchronized");
|
|
||||||
foreach (KeyValuePair<string, ScriptEngineToSceneConnector> pair in m_SEToSceneConnectors)
|
|
||||||
{
|
|
||||||
ScriptEngineToSceneConnector sceneConnector = pair.Value;
|
|
||||||
sceneConnector.ReportStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -285,7 +285,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
|
return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The absolute position of this scene object in the scene
|
/// The absolute position of this scene object in the scene
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -299,22 +299,23 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (Scene != null)
|
if (Scene != null)
|
||||||
{
|
{
|
||||||
if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
|
if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
|
||||||
|| Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
|
|| Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
|
||||||
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
|
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
|
||||||
{
|
{
|
||||||
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
|
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RootPart.GetStatusSandbox())
|
if (RootPart.GetStatusSandbox())
|
||||||
{
|
{
|
||||||
if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
|
if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
|
||||||
{
|
{
|
||||||
RootPart.ScriptSetPhysicsStatus(false);
|
RootPart.ScriptSetPhysicsStatus(false);
|
||||||
|
|
||||||
if (Scene != null)
|
if (Scene != null)
|
||||||
Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
|
Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
|
||||||
ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
|
ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,43 +331,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//m_rootPart.GroupPosition.Z);
|
//m_rootPart.GroupPosition.Z);
|
||||||
//m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
|
//m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (Scene != null)
|
if (Scene != null)
|
||||||
Scene.EventManager.TriggerParcelPrimCountTainted();
|
Scene.EventManager.TriggerParcelPrimCountTainted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void SetAbsolutePosition(Vector3 value)
|
|
||||||
{
|
|
||||||
Vector3 val = value;
|
|
||||||
|
|
||||||
//REGION SYNC touched
|
|
||||||
|
|
||||||
//if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
|
|
||||||
// || m_scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || m_scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
|
|
||||||
// && !IsAttachmentCheckFull())
|
|
||||||
if (m_scene.IsBorderCrossing(LocX, LocY, val) && !IsAttachmentCheckFull() && (!m_scene.LoadingPrims))
|
|
||||||
{
|
|
||||||
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
|
|
||||||
}
|
|
||||||
//end REGION SYNC touched
|
|
||||||
if (RootPart.GetStatusSandbox())
|
|
||||||
{
|
|
||||||
if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
|
|
||||||
{
|
|
||||||
RootPart.ScriptSetPhysicsStatus(false);
|
|
||||||
Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
|
|
||||||
ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneObjectPart[] parts = m_parts.GetArray();
|
|
||||||
for (int i = 0; i < parts.Length; i++)
|
|
||||||
{
|
|
||||||
parts[i].GroupPosition = val;
|
|
||||||
//parts[i].SetGroupPosition(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override uint LocalId
|
public override uint LocalId
|
||||||
{
|
{
|
||||||
|
@ -3531,24 +3500,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region REGION SYNC
|
|
||||||
|
|
||||||
//the LocX and LocY of the authoritative scene that this object is located
|
|
||||||
|
|
||||||
private uint m_locX;
|
|
||||||
private uint m_locY;
|
|
||||||
public uint LocX
|
|
||||||
{
|
|
||||||
get { return m_locX; }
|
|
||||||
set { m_locX = value; }
|
|
||||||
}
|
|
||||||
public uint LocY
|
|
||||||
{
|
|
||||||
get { return m_locY; }
|
|
||||||
set { m_locY = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region DSG SYNC
|
#region DSG SYNC
|
||||||
|
|
||||||
|
@ -3966,11 +3917,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
|
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
|
||||||
// position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
|
// position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
|
||||||
// unmoved prims!
|
// unmoved prims!
|
||||||
//ResetChildPrimPhysicsPositions();
|
ResetChildPrimPhysicsPositions();
|
||||||
//EntityBase sogBase = (EntityBase)this;
|
|
||||||
//sogBase.AbsolutePosition = AbsolutePosition;
|
|
||||||
SetAbsolutePosition(AbsolutePosition);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LinkNonRootPartBySync(SceneObjectPart linkPart, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum)
|
private void LinkNonRootPartBySync(SceneObjectPart linkPart, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum)
|
||||||
|
|
Loading…
Reference in New Issue