Some updates for client manager
parent
79327a6299
commit
2283b85bcf
|
@ -4901,33 +4901,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
int i = 0;
|
||||
x.ToBytes(xb, ref i);
|
||||
|
||||
// If there was a previous update and this update is exactly the same, skip it
|
||||
if (m_lastAgentUpdate != null && Enumerable.SequenceEqual(xb, m_lastAgentUpdate))
|
||||
return true;
|
||||
|
||||
/*
|
||||
// If there was a previous update and this update is exactly the same, skip it
|
||||
if (m_scene.IsSyncedClient() && m_lastAgentUpdate != null && Enumerable.SequenceEqual(xb, m_lastAgentUpdate))
|
||||
{
|
||||
//m_log.Warn("LLClientView: HandleAgentUpdate (IDENTICAL TO LAST)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// What is different?? (only interesting for client managers)
|
||||
/*
|
||||
if(m_scene.IsSyncedClient() && m_lastAgentUpdate != null)
|
||||
{
|
||||
AgentUpdatePacket.AgentDataBlock lastarg = new AgentUpdatePacket.AgentDataBlock();
|
||||
i = 0;
|
||||
lastarg.FromBytes(m_lastAgentUpdate, ref i);
|
||||
|
||||
if(x.BodyRotation != lastarg.BodyRotation) m_log.Warn("BodyRotation");
|
||||
if(x.CameraAtAxis != lastarg.CameraAtAxis) m_log.Warn("CameraAtAxis");
|
||||
if(x.CameraCenter != lastarg.CameraCenter) m_log.Warn("CameraCenter");
|
||||
if(x.CameraLeftAxis != lastarg.CameraLeftAxis) m_log.Warn("CameraLeftAxis");
|
||||
if(x.CameraUpAxis != lastarg.CameraUpAxis) m_log.Warn("CameraUpAxis");
|
||||
if(x.ControlFlags != lastarg.ControlFlags) m_log.Warn("ControlFlags");
|
||||
if(x.Far != lastarg.Far) m_log.Warn("Far");
|
||||
if(x.Flags != lastarg.Flags) m_log.Warn("Flags");
|
||||
if(x.State != lastarg.State) m_log.Warn("State");
|
||||
if(x.HeadRotation != lastarg.HeadRotation) m_log.Warn("HeadRotation");
|
||||
if(x.SessionID != lastarg.SessionID) m_log.Warn("SessionID");
|
||||
if(x.AgentID != lastarg.AgentID) m_log.Warn("AgentID");
|
||||
m_log.WarnFormat("LLClientView: HandleAgentUpdate |{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}|",
|
||||
(x.BodyRotation != lastarg.BodyRotation) ? "X" : " ",
|
||||
(x.CameraAtAxis != lastarg.CameraAtAxis) ? "X" : " ",
|
||||
(x.CameraCenter != lastarg.CameraCenter) ? "X" : " ",
|
||||
(x.CameraLeftAxis != lastarg.CameraLeftAxis) ? "X" : " ",
|
||||
(x.CameraUpAxis != lastarg.CameraUpAxis) ? "X" : " ",
|
||||
(x.ControlFlags != lastarg.ControlFlags) ? "X" : " ",
|
||||
(x.Far != lastarg.Far) ? "X" : " ",
|
||||
(x.Flags != lastarg.Flags) ? "X" : " ",
|
||||
(x.State != lastarg.State) ? "X" : " ",
|
||||
(x.HeadRotation != lastarg.HeadRotation) ? "X" : " ",
|
||||
(x.SessionID != lastarg.SessionID) ? "X" : " ",
|
||||
(x.AgentID != lastarg.AgentID) ? "X" : " ");
|
||||
}
|
||||
* */
|
||||
|
||||
|
||||
|
||||
// save this set of arguments for next time
|
||||
m_lastAgentUpdate = xb;
|
||||
|
||||
|
|
|
@ -130,6 +130,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
public event Action<UUID> OnRemoveAvatar;
|
||||
|
||||
public event CreateNewInventoryItem OnCreateNewInventoryItem;
|
||||
public event LinkInventoryItem OnLinkInventoryItem;
|
||||
public event CreateInventoryFolder OnCreateNewInventoryFolder;
|
||||
public event UpdateInventoryFolder OnUpdateInventoryFolder;
|
||||
public event MoveInventoryFolder OnMoveInventoryFolder;
|
||||
|
|
|
@ -20,6 +20,16 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
// The RegionSyncClient has a receive thread to process messages from the RegionSyncServer.
|
||||
public class RegionSyncClient
|
||||
{
|
||||
#region MsgHandlerStatus Enum
|
||||
public enum MsgHandlerStatus
|
||||
{
|
||||
Success, // Everything went as expected
|
||||
Trivial, // Minor issue, nothing to worry about
|
||||
Warning, // Something went wrong, we can continue
|
||||
Error // This should certainly not have happened! (A bug)
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RegionSyncClient members
|
||||
|
||||
// Set the addr and port of RegionSyncServer
|
||||
|
@ -29,9 +39,15 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
// A reference to the local scene
|
||||
private Scene m_scene;
|
||||
|
||||
// The avatars added to this client manager for clients on other client managers
|
||||
Dictionary<UUID, RegionSyncAvatar> m_remoteAvatars = new Dictionary<UUID, RegionSyncAvatar>();
|
||||
Dictionary<UUID, IClientAPI> m_localAvatars = new Dictionary<UUID, IClientAPI>();
|
||||
|
||||
// The logfile
|
||||
private ILog m_log;
|
||||
|
||||
private string LogHeader = "[REGION SYNC CLIENT]";
|
||||
|
||||
// The listener and the thread which listens for connections from client managers
|
||||
private Thread m_rcvLoop;
|
||||
|
||||
|
@ -46,7 +62,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
public RegionSyncClient(Scene scene, string addr, int port)
|
||||
{
|
||||
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
m_log.Warn("[REGION SYNC CLIENT] Constructed");
|
||||
m_log.WarnFormat("{0} Constructed", LogHeader);
|
||||
m_scene = scene;
|
||||
m_addr = IPAddress.Parse(addr);
|
||||
m_port = port;
|
||||
|
@ -61,40 +77,63 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC CLIENT] [Start] Could not connect to RegionSyncServer at {0}:{1}", m_addr, m_port);
|
||||
m_log.WarnFormat("{0} [Start] Could not connect to RegionSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
|
||||
m_log.Warn(e.Message);
|
||||
}
|
||||
|
||||
m_log.WarnFormat("[REGION SYNC CLIENT] Connected to RegionSyncServer at {0}:{1}", m_addr, m_port);
|
||||
m_log.WarnFormat("{0} Connected to RegionSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
|
||||
|
||||
m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop));
|
||||
m_rcvLoop.Name = "RegionSyncClient ReceiveLoop";
|
||||
m_log.WarnFormat("[REGION SYNC CLIENT] Starting {0} thread", m_rcvLoop.Name);
|
||||
m_log.WarnFormat("{0} Starting {1} thread", LogHeader, m_rcvLoop.Name);
|
||||
m_rcvLoop.Start();
|
||||
m_log.Warn("[REGION SYNC CLIENT] Started");
|
||||
m_log.WarnFormat("{0} Started", LogHeader);
|
||||
DoInitialSync();
|
||||
}
|
||||
|
||||
// Disconnect from the RegionSyncServer and close the RegionSyncClient
|
||||
public void Stop()
|
||||
{
|
||||
// Can't abort the TCP connection until we let the remote scene know we are going away.
|
||||
// Or, the remote scene will remove the CM's avatars automatically when it disconnects
|
||||
m_rcvLoop.Abort();
|
||||
ShutdownClient();
|
||||
}
|
||||
|
||||
private void ShutdownClient()
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC CLIENT] Disconnected from RegionSyncServer. Shutting down.");
|
||||
m_scene.ForEachClient(delegate(IClientAPI client) { client.OnAgentUpdateRaw -= HandleAgentUpdateRaw; });
|
||||
m_log.WarnFormat("{0} Disconnected from RegionSyncServer. Shutting down.", LogHeader);
|
||||
|
||||
// Remove remote avatars from local scene
|
||||
lock (m_remoteAvatars)
|
||||
{
|
||||
foreach (UUID id in m_remoteAvatars.Keys)
|
||||
{
|
||||
m_scene.RemoveClient(id);
|
||||
}
|
||||
}
|
||||
// Remove local avatars from remote scene
|
||||
lock (m_localAvatars)
|
||||
{
|
||||
foreach (KeyValuePair<UUID, IClientAPI> kvp in m_localAvatars)
|
||||
{
|
||||
// Tell the remote scene to remove this client
|
||||
RemoveLocalClient(kvp.Key, m_scene);
|
||||
// Remove the agent update handler from the client
|
||||
kvp.Value.OnAgentUpdateRaw -= HandleAgentUpdateRaw;
|
||||
}
|
||||
}
|
||||
// Close the connection
|
||||
m_client.Client.Close();
|
||||
m_client.Close();
|
||||
|
||||
}
|
||||
|
||||
// Listen for messages from a RegionSyncClient
|
||||
// *** This is the main thread loop for each connected client
|
||||
private void ReceiveLoop()
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC CLIENT] Thread running: {0}", m_rcvLoop.Name);
|
||||
m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name);
|
||||
while (true && m_client.Connected)
|
||||
{
|
||||
RegionSyncMessage msg;
|
||||
|
@ -102,7 +141,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
try
|
||||
{
|
||||
msg = new RegionSyncMessage(m_client.GetStream());
|
||||
//m_log.WarnFormat("[REGION SYNC CLIENT] Received: {0}", msg.ToString());
|
||||
//m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString());
|
||||
}
|
||||
// If there is a problem reading from the client, shut 'er down.
|
||||
catch
|
||||
|
@ -113,16 +152,32 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
// Try handling the message
|
||||
try
|
||||
{
|
||||
HandleMessage(msg);
|
||||
string message;
|
||||
MsgHandlerStatus status = HandleMessage(msg, out message);
|
||||
switch (status)
|
||||
{
|
||||
case MsgHandlerStatus.Success:
|
||||
//m_log.WarnFormat("{0} Handled {1}: {2}", LogHeader, msg.ToString(), message);
|
||||
break;
|
||||
case MsgHandlerStatus.Trivial:
|
||||
m_log.WarnFormat("{0} Issue handling {1}: {2}", LogHeader, msg.ToString(), message);
|
||||
break;
|
||||
case MsgHandlerStatus.Warning:
|
||||
m_log.WarnFormat("{0} Warning handling {1}: {2}", LogHeader, msg.ToString(), message);
|
||||
break;
|
||||
case MsgHandlerStatus.Error:
|
||||
m_log.WarnFormat("{0} Error handling {1}: {2}", LogHeader, msg.ToString(), message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC CLIENT] Encountered an exception: {0}", e.Message);
|
||||
m_log.WarnFormat("{0} Encountered an exception: {1}", LogHeader, e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Send
|
||||
#region SEND
|
||||
// Send a message to a single connected RegionSyncClient
|
||||
private void Send(string msg)
|
||||
{
|
||||
|
@ -133,7 +188,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
private void Send(RegionSyncMessage msg)
|
||||
{
|
||||
Send(msg.ToBytes());
|
||||
//m_log.WarnFormat("[REGION SYNC CLIENT] Sent {0}", msg.ToString());
|
||||
//m_log.WarnFormat("{0} Sent {1}", LogHeader, msg.ToString());
|
||||
}
|
||||
|
||||
private void Send(byte[] data)
|
||||
|
@ -154,58 +209,71 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
}
|
||||
#endregion
|
||||
|
||||
// Send coarse locations to locally connected clients
|
||||
// This is a highly optimized version for lots of local and remote clients
|
||||
// 99.9% faster for 1000 clients!
|
||||
public void SendCoarseLocations()
|
||||
{
|
||||
List<UUID> ids = new List<UUID>();
|
||||
List<Vector3> locations = new List<Vector3>();
|
||||
m_scene.GetCoarseLocations(out ids, out locations);
|
||||
lock (m_localAvatars)
|
||||
{
|
||||
foreach (IClientAPI client in m_localAvatars.Values)
|
||||
{
|
||||
client.SendCoarseLocationUpdate(ids, locations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<string> exceptions = new HashSet<string>();
|
||||
private OSDMap DeserializeMessage(RegionSyncMessage msg)
|
||||
{
|
||||
OSDMap data = null;
|
||||
try
|
||||
{
|
||||
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data)) 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));
|
||||
data = null;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// Handle an incoming message
|
||||
// Returns true if the message was processed
|
||||
// TODO: This should not be synchronous with the receive!
|
||||
// Instead, handle messages from the incoming Queue
|
||||
private bool HandleMessage(RegionSyncMessage msg)
|
||||
private MsgHandlerStatus HandleMessage(RegionSyncMessage msg, out string result)
|
||||
{
|
||||
switch (msg.Type)
|
||||
{
|
||||
case RegionSyncMessage.MsgType.Terrain:
|
||||
{
|
||||
m_scene.Heightmap.LoadFromXmlString(Encoding.ASCII.GetString(msg.Data));
|
||||
return HandlerSuccess(msg, "Syncrhonized terrain");
|
||||
result = "Synchronized terrain";
|
||||
return MsgHandlerStatus.Success;
|
||||
}
|
||||
case RegionSyncMessage.MsgType.AddObject:
|
||||
case RegionSyncMessage.MsgType.UpdateObject:
|
||||
case RegionSyncMessage.MsgType.NewObject:
|
||||
case RegionSyncMessage.MsgType.UpdatedObject:
|
||||
{
|
||||
SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(Encoding.ASCII.GetString(msg.Data));
|
||||
if(sog.IsDeleted)
|
||||
return HandlerFailure(msg, String.Format("Ignoring update on deleted LocalId {0}.", sog.LocalId.ToString()));
|
||||
if (sog.IsDeleted)
|
||||
{
|
||||
result = String.Format("Ignoring update on deleted LocalId {0}.", sog.LocalId.ToString());
|
||||
return MsgHandlerStatus.Trivial;
|
||||
}
|
||||
if (m_scene.AddNewSceneObject(sog, true))
|
||||
{
|
||||
result = String.Format("Object \"{0}\" ({1}) ({1}) updated.", sog.Name, sog.UUID.ToString(), sog.LocalId.ToString());
|
||||
else
|
||||
result = String.Format("Object \"{0}\" ({1}) ({1}) added.", sog.Name, sog.UUID.ToString(), sog.LocalId.ToString());
|
||||
sog.ScheduleGroupForFullUpdate();
|
||||
return HandlerSuccess(msg, String.Format("LocalId {0} added or updated.", sog.LocalId.ToString()));
|
||||
}
|
||||
return HandlerFailure(msg, String.Format("Could not add or update LocalId {0}.", sog.LocalId.ToString()));
|
||||
}
|
||||
case RegionSyncMessage.MsgType.UpdateAvatarTerse:
|
||||
{
|
||||
|
||||
OSDMap data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data)) as OSDMap;
|
||||
if( data != null )
|
||||
{
|
||||
UUID agentID = data["id"].AsUUID();
|
||||
Vector3 pos = data["pos"].AsVector3();
|
||||
Vector3 vel = data["vel"].AsVector3();
|
||||
Quaternion rot = data["rot"].AsQuaternion();
|
||||
|
||||
// We get the UUID of the avatar to be updated, find it in the scene
|
||||
if (agentID != UUID.Zero)
|
||||
{
|
||||
ScenePresence presence = m_scene.GetScenePresence(agentID);
|
||||
if (presence != null)
|
||||
{
|
||||
presence.AbsolutePosition = pos;
|
||||
presence.Velocity = vel;
|
||||
presence.Rotation = rot;
|
||||
presence.SendTerseUpdateToAllClients();
|
||||
return HandlerSuccess(msg, String.Format("agentID {0} updated", agentID.ToString()));
|
||||
}
|
||||
}
|
||||
return HandlerFailure(msg, String.Format("agentID {0} not found.", agentID.ToString()));
|
||||
}
|
||||
return HandlerFailure(msg, "Could not parse AgentUpdate parameters");
|
||||
return MsgHandlerStatus.Success;
|
||||
}
|
||||
// return HandlerSuccess(msg, "Updated avatar");
|
||||
/*
|
||||
|
@ -228,9 +296,9 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
}
|
||||
}
|
||||
* */
|
||||
case RegionSyncMessage.MsgType.RemoveObject:
|
||||
case RegionSyncMessage.MsgType.RemovedObject:
|
||||
{
|
||||
OSDMap data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data)) as OSDMap;
|
||||
OSDMap data = DeserializeMessage(msg);
|
||||
if( data != null )
|
||||
{
|
||||
ulong regionHandle = data["regionHandle"].AsULong();
|
||||
|
@ -245,15 +313,130 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
if (sog != null)
|
||||
{
|
||||
m_scene.DeleteSceneObject(sog, false);
|
||||
return HandlerSuccess(msg, String.Format("localID {0} deleted.", localID.ToString()));
|
||||
result = String.Format("localID {0} deleted.", localID.ToString());
|
||||
return MsgHandlerStatus.Success;
|
||||
}
|
||||
}
|
||||
return HandlerFailure(msg, String.Format("ignoring delete request for non-local regionHandle {0}.", regionHandle.ToString()));
|
||||
result = String.Format("ignoring delete request for non-local regionHandle {0}.", regionHandle.ToString());
|
||||
return MsgHandlerStatus.Trivial;
|
||||
}
|
||||
return HandlerFailure(msg, String.Format("localID {0} not found.", localID.ToString()));
|
||||
result = String.Format("localID {0} not found.", localID.ToString());
|
||||
return MsgHandlerStatus.Warning;
|
||||
}
|
||||
return HandlerFailure(msg, "Could not parse DeleteObject parameters");
|
||||
result = "Could not deserialize JSON data.";
|
||||
return MsgHandlerStatus.Error;
|
||||
}
|
||||
case RegionSyncMessage.MsgType.NewAvatar:
|
||||
{
|
||||
OSDMap data = DeserializeMessage(msg);
|
||||
if (data != null)
|
||||
{
|
||||
UUID agentID = data["agentID"].AsUUID();
|
||||
string first = data["first"].AsString();
|
||||
string last = data["last"].AsString();
|
||||
Vector3 startPos = data["startPos"].AsVector3();
|
||||
|
||||
if (agentID != null && first != null && last != null && startPos != null)
|
||||
{
|
||||
if (m_remoteAvatars.ContainsKey(agentID))
|
||||
{
|
||||
result = String.Format("Attempted to add duplicate avatar \"{0} {1}\" ({2})", first, last, agentID.ToString());
|
||||
return MsgHandlerStatus.Warning;
|
||||
}
|
||||
ScenePresence sp;
|
||||
if (m_scene.TryGetScenePresence(agentID, out sp))
|
||||
{
|
||||
result = String.Format("Confirmation of new avatar \"{0}\" ({1})", sp.Name, sp.UUID.ToString());
|
||||
HandlerDebug(msg, result);
|
||||
return MsgHandlerStatus.Success;
|
||||
}
|
||||
RegionSyncAvatar av = new RegionSyncAvatar(m_scene, agentID, first, last, startPos);
|
||||
m_remoteAvatars.Add(agentID, av);
|
||||
m_scene.AddNewClient(av);
|
||||
result = String.Format("Handled NewAvatar for UUID {0}", agentID);
|
||||
return MsgHandlerStatus.Success;
|
||||
}
|
||||
}
|
||||
result = "Could not deserialize JSON data.";
|
||||
return MsgHandlerStatus.Error;
|
||||
}
|
||||
case RegionSyncMessage.MsgType.UpdatedAvatar:
|
||||
{
|
||||
OSDMap data = DeserializeMessage(msg);
|
||||
if (data != null)
|
||||
{
|
||||
UUID agentID = data["id"].AsUUID();
|
||||
Vector3 pos = data["pos"].AsVector3();
|
||||
Vector3 vel = data["vel"].AsVector3();
|
||||
Quaternion rot = data["rot"].AsQuaternion();
|
||||
bool flying = data["fly"].AsBoolean();
|
||||
|
||||
// We get the UUID of the avatar to be updated, find it in the scene
|
||||
if (agentID != UUID.Zero)
|
||||
{
|
||||
ScenePresence presence;
|
||||
if (m_scene.TryGetScenePresence(agentID, out presence))
|
||||
{
|
||||
presence.AbsolutePosition = pos;
|
||||
presence.Velocity = vel;
|
||||
presence.Rotation = rot;
|
||||
presence.PhysicsActor.Flying = flying;
|
||||
List<IClientAPI> locals;
|
||||
lock (m_localAvatars)
|
||||
locals = new List<IClientAPI>(m_localAvatars.Values);
|
||||
presence.SendTerseUpdateToClientList(locals);
|
||||
result = String.Format("Avatar \"{0}\" ({1}) ({2}) updated (pos:{3}, vel:{4}, rot:{5}, fly:{6})",
|
||||
presence.Name, presence.UUID.ToString(), presence.LocalId.ToString(),
|
||||
presence.AbsolutePosition.ToString(), presence.Velocity.ToString(),
|
||||
presence.Rotation.ToString(), presence.PhysicsActor.Flying ? "Y" : "N");
|
||||
return MsgHandlerStatus.Success;
|
||||
}
|
||||
}
|
||||
result = String.Format("agentID {0} not found.", agentID.ToString());
|
||||
return MsgHandlerStatus.Warning;
|
||||
}
|
||||
result = "Could not deserialize JSON data.";
|
||||
return MsgHandlerStatus.Error;
|
||||
}
|
||||
case RegionSyncMessage.MsgType.RemovedAvatar:
|
||||
{
|
||||
OSDMap data = DeserializeMessage(msg);
|
||||
if (data != null)
|
||||
{
|
||||
UUID agentID = data["agentID"].AsUUID();
|
||||
|
||||
// We get the UUID of the avatar to be removed, find it in the scene
|
||||
if (agentID != UUID.Zero)
|
||||
{
|
||||
ScenePresence presence;
|
||||
// If this is a synced remote avatar and it's in the scene, then remove it
|
||||
if (m_remoteAvatars.ContainsKey(agentID))
|
||||
{
|
||||
if (m_scene.TryGetScenePresence(agentID, out presence))
|
||||
{
|
||||
m_scene.RemoveClient(agentID);
|
||||
result = String.Format("Avatar \"{0}\" removed from scene", presence.Name);
|
||||
return MsgHandlerStatus.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = String.Format("agentID {0} not found.", agentID.ToString());
|
||||
return MsgHandlerStatus.Warning;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = String.Format("agentID {0} is not a remote avatar.", agentID.ToString());
|
||||
return MsgHandlerStatus.Warning;
|
||||
}
|
||||
}
|
||||
result = String.Format("agentID {0} was UUID.Zero!", agentID.ToString());
|
||||
return MsgHandlerStatus.Error;
|
||||
}
|
||||
result = "Could not deserialize JSON data.";
|
||||
return MsgHandlerStatus.Error;
|
||||
}
|
||||
|
||||
/*
|
||||
case RegionSyncMessage.MsgType.UpdateObject:
|
||||
{
|
||||
|
@ -279,31 +462,27 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
* */
|
||||
default:
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC CLIENT] Unsupported message type");
|
||||
return false;
|
||||
result = String.Format("{0} Unsupported message type: {1}", LogHeader, ((int)msg.Type).ToString());
|
||||
return MsgHandlerStatus.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HandlerSuccess(RegionSyncMessage msg, string handlerMessage)
|
||||
private bool HandlerDebug(RegionSyncMessage msg, string handlerMessage)
|
||||
{
|
||||
//m_log.WarnFormat("[REGION SYNC CLIENT] Handled {0}: {1}", msg.ToString(), handlerMessage);
|
||||
m_log.WarnFormat("{0} DBG ({1}): {2}", LogHeader, msg.ToString(), handlerMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool HandlerFailure(RegionSyncMessage msg, string handlerMessage)
|
||||
{
|
||||
//m_log.WarnFormat("[REGION SYNC SERVER] Unable to handle {0}: {1}", msg.ToString(), handlerMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DoInitialSync()
|
||||
{
|
||||
m_scene.DeleteAllSceneObjects();
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetTerrain));
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetObjects));
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetAvatars));
|
||||
// Register for events which will be forwarded to authoritative scene
|
||||
m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
|
||||
m_scene.EventManager.OnClientClosed += new EventManager.ClientClosed(RemoveLocalClient);
|
||||
}
|
||||
|
||||
public string GetServerAddressAndPort()
|
||||
|
@ -311,11 +490,20 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
return m_addr.ToString() + ":" + m_port.ToString();
|
||||
}
|
||||
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
#region MESSAGES SENT FROM CLIENT MANAGER TO SIM
|
||||
public void EventManager_OnNewClient(IClientAPI client)
|
||||
{
|
||||
// If this client was added in response to NewAvatar message from a synced server,
|
||||
// don't subscribe to events or send back to server
|
||||
lock (m_remoteAvatars)
|
||||
{
|
||||
if (m_remoteAvatars.ContainsKey(client.AgentId))
|
||||
return;
|
||||
}
|
||||
// Otherwise, it's a real local client connecting so track it locally
|
||||
lock(m_localAvatars)
|
||||
m_localAvatars.Add(client.AgentId, client);
|
||||
m_log.WarnFormat("{0} New local client \"{1}\" ({2}) being added to remote scene.", LogHeader, client.Name, client.AgentId.ToString());
|
||||
// Let the auth sim know that a new agent has connected
|
||||
OSDMap data = new OSDMap(1);
|
||||
data["agentID"] = OSD.FromUUID(client.AgentId);
|
||||
|
@ -330,6 +518,16 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
client.OnChatFromClientRaw += HandleChatFromClientRaw;
|
||||
}
|
||||
|
||||
void RemoveLocalClient(UUID clientID, Scene scene)
|
||||
{
|
||||
m_log.WarnFormat("{0} Local client ({1}) being removed from remote scene.", LogHeader, clientID.ToString());
|
||||
m_localAvatars.Remove(clientID);
|
||||
// Let the auth sim know that an agent has disconnected
|
||||
OSDMap data = new OSDMap(1);
|
||||
data["agentID"] = OSD.FromUUID(clientID);
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.AgentRemove, OSDParser.SerializeJsonString(data)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the event handler for client movement. If a client is moving, this event is triggering.
|
||||
/// </summary>
|
||||
|
@ -342,8 +540,8 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
{
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ChatFromClient, chatData));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/*
|
||||
// Should be part of the RegionSyncClient
|
||||
public string ReceiveMsg()
|
||||
|
|
|
@ -101,6 +101,11 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
#endregion
|
||||
|
||||
#region IRegionSyncClientModule members
|
||||
public void SendCoarseLocations()
|
||||
{
|
||||
m_client.SendCoarseLocations();
|
||||
}
|
||||
|
||||
public bool Active
|
||||
{
|
||||
get { return m_active; }
|
||||
|
@ -126,6 +131,8 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
private ILog m_log;
|
||||
private Object m_client_lock = new Object();
|
||||
private RegionSyncClient m_client = null;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
|
|
@ -21,6 +21,13 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
public class RegionSyncClientView
|
||||
{
|
||||
#region RegionSyncClientView members
|
||||
|
||||
object stats = new object();
|
||||
private long msgsIn;
|
||||
private long msgsOut;
|
||||
private long bytesIn;
|
||||
private long bytesOut;
|
||||
|
||||
// The TcpClient this view uses to communicate with its RegionSyncClient
|
||||
private TcpClient m_tcpclient;
|
||||
// Set the addr and port for TcpListener
|
||||
|
@ -32,15 +39,12 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
Dictionary<UUID, RegionSyncAvatar> m_syncedAvatars = new Dictionary<UUID, RegionSyncAvatar>();
|
||||
|
||||
// A queue for incoming and outgoing traffic
|
||||
private Queue<string> m_inQ = new Queue<string>();
|
||||
private Queue<string> m_outQ = new Queue<string>();
|
||||
private OpenMetaverse.BlockingQueue<RegionSyncMessage> inbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
|
||||
|
||||
private ILog m_log;
|
||||
|
||||
private Thread m_receive_loop;
|
||||
|
||||
// The last time the entire region was sent to this RegionSyncClient
|
||||
private long m_archive_time;
|
||||
private Thread m_handler;
|
||||
|
||||
// A string of the format [REGION SYNC CLIENT VIEW #X] for use in log headers
|
||||
private string LogHeader
|
||||
|
@ -54,6 +58,12 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
get { return String.Format("RegionSyncClientView #{0}", m_connection_number); }
|
||||
}
|
||||
|
||||
public string GetStats()
|
||||
{
|
||||
lock(stats)
|
||||
return String.Format("{0},{1},{2},{3}", msgsIn, msgsOut, bytesIn, bytesOut);
|
||||
}
|
||||
|
||||
// Check if the client is connected
|
||||
public bool Connected
|
||||
{ get { return m_tcpclient.Connected; } }
|
||||
|
@ -96,12 +106,17 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
while (true)
|
||||
{
|
||||
RegionSyncMessage msg = GetMessage();
|
||||
lock (stats)
|
||||
{
|
||||
msgsIn++;
|
||||
bytesIn += msg.Length;
|
||||
}
|
||||
HandleMessage(msg);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("{0} RegionSyncClient has disconnected.", LogHeader);
|
||||
m_log.WarnFormat("{0} RegionSyncClient has disconnected: {1}", LogHeader, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,10 +125,30 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
{
|
||||
// Get a RegionSyncMessager from the incoming stream
|
||||
RegionSyncMessage msg = new RegionSyncMessage(m_tcpclient.GetStream());
|
||||
m_log.WarnFormat("{0} Received {1}", LogHeader, msg.ToString());
|
||||
//m_log.WarnFormat("{0} Received {1}", LogHeader, msg.ToString());
|
||||
return msg;
|
||||
}
|
||||
|
||||
HashSet<string> exceptions = new HashSet<string>();
|
||||
private OSDMap DeserializeMessage(RegionSyncMessage msg)
|
||||
{
|
||||
OSDMap data = null;
|
||||
try
|
||||
{
|
||||
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data)) 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));
|
||||
data = null;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
// Handle an incoming message
|
||||
// *** Perhaps this should not be synchronous with the receive
|
||||
// We could handle messages from an incoming Queue
|
||||
|
@ -122,6 +157,11 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
//string handlerMessage = "";
|
||||
switch (msg.Type)
|
||||
{
|
||||
case RegionSyncMessage.MsgType.GetTerrain:
|
||||
{
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString()));
|
||||
return HandlerSuccess(msg, "Terrain sent");
|
||||
}
|
||||
case RegionSyncMessage.MsgType.GetObjects:
|
||||
{
|
||||
List<EntityBase> entities = m_scene.GetEntities();
|
||||
|
@ -130,19 +170,28 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
if (e is SceneObjectGroup)
|
||||
{
|
||||
string sogxml = SceneObjectSerializer.ToXml2Format((SceneObjectGroup)e);
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.AddObject, sogxml));
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.NewObject, sogxml));
|
||||
}
|
||||
}
|
||||
return HandlerSuccess(msg, "Sent all scene objects");
|
||||
}
|
||||
case RegionSyncMessage.MsgType.GetTerrain:
|
||||
case RegionSyncMessage.MsgType.GetAvatars:
|
||||
{
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString()));
|
||||
return HandlerSuccess(msg, "Terrain sent");
|
||||
m_scene.ForEachScenePresence(delegate(ScenePresence presence)
|
||||
{
|
||||
// Let the client managers know about this avatar
|
||||
OSDMap data = new OSDMap(1);
|
||||
data["agentID"] = OSD.FromUUID(presence.ControllingClient.AgentId);
|
||||
data["first"] = OSD.FromString(presence.ControllingClient.FirstName);
|
||||
data["last"] = OSD.FromString(presence.ControllingClient.LastName);
|
||||
data["startPos"] = OSD.FromVector3(presence.ControllingClient.StartPos);
|
||||
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.NewAvatar, OSDParser.SerializeJsonString(data)));
|
||||
});
|
||||
return HandlerSuccess(msg, "Sent all scene avatars");
|
||||
}
|
||||
case RegionSyncMessage.MsgType.AgentAdd:
|
||||
{
|
||||
OSDMap data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data)) as OSDMap;
|
||||
OSDMap data = DeserializeMessage(msg);
|
||||
if (data != null)
|
||||
{
|
||||
UUID agentID = data["agentID"].AsUUID();
|
||||
|
@ -165,7 +214,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
return HandlerSuccess(msg, String.Format("Handled AddAgent for UUID {0}", agentID));
|
||||
}
|
||||
}
|
||||
return HandlerFailure(msg, "Could not parse AddAgent parameters");
|
||||
return HandlerFailure(msg, "Could not deserialize JSON data.");
|
||||
|
||||
}
|
||||
case RegionSyncMessage.MsgType.AgentUpdate:
|
||||
|
@ -204,6 +253,42 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
else
|
||||
return HandlerFailure(msg, String.Format("Could not handle AgentUpdate UUID {0}", agentID));
|
||||
}
|
||||
case RegionSyncMessage.MsgType.AgentRemove:
|
||||
{
|
||||
OSDMap data = DeserializeMessage(msg);
|
||||
if (data != null)
|
||||
{
|
||||
UUID agentID = data["agentID"].AsUUID();
|
||||
|
||||
if (agentID != null && agentID != UUID.Zero)
|
||||
{
|
||||
lock (m_syncedAvatars)
|
||||
{
|
||||
if (m_syncedAvatars.ContainsKey(agentID))
|
||||
{
|
||||
m_syncedAvatars.Remove(agentID);
|
||||
ScenePresence presence;
|
||||
if (m_scene.TryGetScenePresence(agentID, out presence))
|
||||
{
|
||||
string name = presence.Name;
|
||||
m_scene.RemoveClient(agentID);
|
||||
return HandlerSuccess(msg, String.Format("Agent \"{0}\" ({1}) was removed from scene.", name, agentID));
|
||||
}
|
||||
else
|
||||
{
|
||||
return HandlerFailure(msg, String.Format("Agent {0} not found in the scene.", agentID));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HandlerFailure(msg, String.Format("Agent {0} not in the list of synced avatars.", agentID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return HandlerFailure(msg, "Could not deserialize JSON data.");
|
||||
|
||||
}
|
||||
default:
|
||||
{
|
||||
m_log.WarnFormat("{0} Unable to handle unsupported message type", LogHeader);
|
||||
|
@ -212,9 +297,15 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
}
|
||||
}
|
||||
|
||||
private bool HandlerDebug(RegionSyncMessage msg, string handlerMessage)
|
||||
{
|
||||
m_log.WarnFormat("{0} DBG ({1}): {2}", LogHeader, msg.ToString(), handlerMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool HandlerSuccess(RegionSyncMessage msg, string handlerMessage)
|
||||
{
|
||||
m_log.WarnFormat("{0} Handled {1}: {2}", LogHeader, msg.ToString(), handlerMessage);
|
||||
//m_log.WarnFormat("{0} Handled {1}: {2}", LogHeader, msg.ToString(), handlerMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -236,6 +327,11 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
{
|
||||
try
|
||||
{
|
||||
lock (stats)
|
||||
{
|
||||
msgsOut++;
|
||||
bytesOut += data.Length;
|
||||
}
|
||||
m_tcpclient.GetStream().Write(data, 0, data.Length);
|
||||
}
|
||||
catch (IOException e)
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
// CM -> SIM
|
||||
AgentAdd,
|
||||
AgentUpdate,
|
||||
AgentRemove,
|
||||
GetTerrain,
|
||||
GetObjects,
|
||||
SubscribeObjects,
|
||||
|
@ -27,12 +28,12 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
ChatFromClient,
|
||||
// SIM -> CM
|
||||
Terrain,
|
||||
AddObject,
|
||||
UpdateObject,
|
||||
RemoveObject,
|
||||
AddAvatarResponse,
|
||||
UpdateAvatarTerse,
|
||||
RemoveAvatar,
|
||||
NewObject, // objects
|
||||
UpdatedObject, // objects
|
||||
RemovedObject, // objects
|
||||
NewAvatar, // avatars
|
||||
UpdatedAvatar, // avatars
|
||||
RemovedAvatar, // avatars
|
||||
ChatFromSim,
|
||||
// BIDIR
|
||||
EchoRequest,
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
private IPAddress m_addr;
|
||||
private Int32 m_port;
|
||||
|
||||
private int clientCounter;
|
||||
|
||||
// The local scene.
|
||||
private Scene m_scene;
|
||||
|
||||
|
@ -36,27 +38,50 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
private Thread m_listenerThread;
|
||||
|
||||
// The list of clients and the threads handling IO for each client
|
||||
// Lock should be used when client managers connect or disconnect
|
||||
// while modifying the client list.
|
||||
private Object clientLock = new Object();
|
||||
private List<RegionSyncClientView> m_client_views = new List<RegionSyncClientView>();
|
||||
// The list is read most of the time and only updated when a new client manager
|
||||
// connects, so we just replace the list when it changes. Iterators on this
|
||||
// list need to be able to handle if an element is shutting down.
|
||||
private HashSet<RegionSyncClientView> m_client_views = new HashSet<RegionSyncClientView>();
|
||||
|
||||
// Check if any of the client views are in a connected state
|
||||
public bool Synced
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (clientLock)
|
||||
return (m_client_views.Count > 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the client view to the list and increment synced client counter
|
||||
public void AddSyncedClient(RegionSyncClientView rscv)
|
||||
{
|
||||
foreach (RegionSyncClientView cv in m_client_views)
|
||||
HashSet<RegionSyncClientView> newlist = new HashSet<RegionSyncClientView>(m_client_views);
|
||||
newlist.Add(rscv);
|
||||
// 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
|
||||
Interlocked.Exchange<HashSet<RegionSyncClientView>>(ref m_client_views, newlist);
|
||||
}
|
||||
|
||||
// Remove the client view from the list and decrement synced client counter
|
||||
public void RemoveSyncedClient(RegionSyncClientView rscv)
|
||||
{
|
||||
if (cv.Connected)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
HashSet<RegionSyncClientView> newlist = new HashSet<RegionSyncClientView>(m_client_views);
|
||||
newlist.Remove(rscv);
|
||||
// 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
|
||||
Interlocked.Exchange<HashSet<RegionSyncClientView>>(ref m_client_views, newlist);
|
||||
}
|
||||
|
||||
public void ReportStats()
|
||||
{
|
||||
// We should be able to safely iterate over our reference to the list since
|
||||
// the only places which change it will replace it with an updated version
|
||||
foreach (RegionSyncClientView rscv in m_client_views)
|
||||
{
|
||||
m_log.ErrorFormat("{0}: {1}", rscv.Description, rscv.GetStats());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Constructor
|
||||
|
@ -81,20 +106,19 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
|
||||
// Stop the server and disconnect all RegionSyncClients
|
||||
public void Shutdown()
|
||||
{
|
||||
lock (clientLock)
|
||||
{
|
||||
// Stop the listener and listening thread so no new clients are accepted
|
||||
m_listener.Stop();
|
||||
m_listenerThread.Abort();
|
||||
m_listenerThread = null;
|
||||
|
||||
// Stop all existing client views and clear client list
|
||||
foreach (RegionSyncClientView cv in m_client_views)
|
||||
HashSet<RegionSyncClientView> list = new HashSet<RegionSyncClientView>(m_client_views);
|
||||
foreach (RegionSyncClientView rscv in list)
|
||||
{
|
||||
// Each client view will clean up after itself
|
||||
cv.Shutdown();
|
||||
}
|
||||
m_client_views.Clear();
|
||||
rscv.Shutdown();
|
||||
RemoveSyncedClient(rscv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,16 +141,13 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
TcpClient tcpclient = m_listener.AcceptTcpClient();
|
||||
IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address;
|
||||
int port = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Port;
|
||||
lock (clientLock)
|
||||
{
|
||||
// Add the RegionSyncClientView to the list of clients
|
||||
// *** Need to work on the timing order of starting the client view and adding to the server list
|
||||
// so that messages coming from the scene do not get lost before the client view is added but
|
||||
// not sent before it is ready to process them.
|
||||
RegionSyncClientView rscv = new RegionSyncClientView(m_client_views.Count, m_scene, tcpclient);
|
||||
RegionSyncClientView rscv = new RegionSyncClientView(++clientCounter, m_scene, tcpclient);
|
||||
m_log.WarnFormat("[REGION SYNC SERVER] New connection from {0}", rscv.Description);
|
||||
m_client_views.Add(rscv);
|
||||
}
|
||||
AddSyncedClient(rscv);
|
||||
}
|
||||
}
|
||||
catch (SocketException e)
|
||||
|
@ -138,23 +159,31 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
// Broadcast a message to all connected RegionSyncClients
|
||||
public void Broadcast(RegionSyncMessage msg)
|
||||
{
|
||||
List<RegionSyncClientView> clients = new List<RegionSyncClientView>();
|
||||
lock (clientLock)
|
||||
{
|
||||
foreach (RegionSyncClientView client in m_client_views)
|
||||
{
|
||||
if (client.Connected)
|
||||
clients.Add(client);
|
||||
}
|
||||
}
|
||||
|
||||
if(clients.Count > 0 )
|
||||
List<RegionSyncClientView> closed = null;
|
||||
//lock (m_client_views)
|
||||
{
|
||||
//m_log.WarnFormat("[REGION SYNC SERVER] Broadcasting {0} to all connected RegionSyncClients", msg.ToString());
|
||||
foreach( RegionSyncClientView client in clients)
|
||||
foreach (RegionSyncClientView client in m_client_views)
|
||||
{
|
||||
// If connected, send the message.
|
||||
if (client.Connected)
|
||||
{
|
||||
client.Send(msg);
|
||||
}
|
||||
// Else, remove the client view from the list
|
||||
else
|
||||
{
|
||||
if (closed == null)
|
||||
closed = new List<RegionSyncClientView>();
|
||||
closed.Add(client);
|
||||
}
|
||||
}
|
||||
if (closed != null)
|
||||
{
|
||||
foreach (RegionSyncClientView rscv in closed)
|
||||
RemoveSyncedClient(rscv);
|
||||
//m_client_views.Remove(rscv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Nini.Config;
|
||||
|
@ -32,6 +33,7 @@ using OpenMetaverse;
|
|||
using OpenMetaverse.StructuredData;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Client;
|
||||
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||
|
@ -42,7 +44,7 @@ using System.Threading;
|
|||
|
||||
namespace OpenSim.Region.Examples.RegionSyncModule
|
||||
{
|
||||
public class RegionSyncServerModule : IRegionModule, IRegionSyncServerModule
|
||||
public class RegionSyncServerModule : IRegionModule, IRegionSyncServerModule, ICommandableModule
|
||||
{
|
||||
#region IRegionModule Members
|
||||
public void Initialise(Scene scene, IConfigSource config)
|
||||
|
@ -60,6 +62,11 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
m_serverport = syncConfig.GetInt("ServerPort", 13000);
|
||||
m_scene = scene;
|
||||
m_scene.RegisterModuleInterface<IRegionSyncServerModule>(this);
|
||||
|
||||
// Setup the command line interface
|
||||
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||
InstallInterfaces();
|
||||
|
||||
m_log.Warn("[REGION SYNC SERVER MODULE] Initialised");
|
||||
}
|
||||
|
||||
|
@ -69,12 +76,13 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
return;
|
||||
|
||||
//m_scene.EventManager.OnObjectBeingRemovedFromScene += new EventManager.ObjectBeingRemovedFromScene(EventManager_OnObjectBeingRemovedFromScene);
|
||||
//m_scene.EventManager.OnNewClient +=new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
|
||||
//m_scene.EventManager.OnNewPresence +=new EventManager.OnNewPresenceDelegate(EventManager_OnNewPresence);
|
||||
|
||||
//m_scene.EventManager.OnAvatarEnteringNewParcel += new EventManager.AvatarEnteringNewParcel(EventManager_OnAvatarEnteringNewParcel);
|
||||
//m_scene.EventManager.OnClientMovement += new EventManager.ClientMovement(EventManager_OnClientMovement);
|
||||
//m_scene.EventManager.OnLandObjectAdded += new EventManager.LandObjectAdded(EventManager_OnLandObjectAdded);
|
||||
//m_scene.EventManager.OnLandObjectRemoved += new EventManager.LandObjectRemoved(EventManager_OnLandObjectRemoved);
|
||||
m_scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
|
||||
//m_scene.EventManager.OnNewPresence += new EventManager.OnNewPresenceDelegate(EventManager_OnNewPresence);
|
||||
m_scene.EventManager.OnRemovePresence += new EventManager.OnRemovePresenceDelegate(EventManager_OnRemovePresence);
|
||||
m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(SceneGraph_OnObjectCreate);
|
||||
m_scene.SceneGraph.OnObjectDuplicate += new ObjectDuplicateDelegate(SceneGraph_OnObjectDuplicate);
|
||||
|
@ -103,7 +111,15 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
{
|
||||
get { return false; }
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region ICommandableModule Members
|
||||
private readonly Commander m_commander = new Commander("sync");
|
||||
public ICommander CommandInterface
|
||||
{
|
||||
get { return m_commander; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IRegionSyncServerModule members
|
||||
// Lock is used to synchronize access to the update status and both update queues
|
||||
|
@ -116,7 +132,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
{
|
||||
if (!Active || !Synced)
|
||||
return;
|
||||
lock (m_primUpdates)
|
||||
lock (m_updateLock)
|
||||
{
|
||||
m_primUpdates[part.ParentGroup.UUID] = part.ParentGroup;
|
||||
}
|
||||
|
@ -127,7 +143,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
{
|
||||
if (!Active || !Synced)
|
||||
return;
|
||||
lock (m_presenceUpdates)
|
||||
lock (m_updateLock)
|
||||
{
|
||||
m_presenceUpdates[presence.UUID] = presence;
|
||||
}
|
||||
|
@ -148,10 +164,14 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
|
||||
List<SceneObjectGroup> primUpdates;
|
||||
List<ScenePresence> presenceUpdates;
|
||||
|
||||
lock (m_updateLock)
|
||||
{
|
||||
primUpdates = new List<SceneObjectGroup>(m_primUpdates.Values);
|
||||
presenceUpdates = new List<ScenePresence>(m_presenceUpdates.Values);
|
||||
m_primUpdates.Clear();
|
||||
m_presenceUpdates.Clear();
|
||||
}
|
||||
|
||||
// This could be another thread for sending outgoing messages or just have the Queue functions
|
||||
// create and queue the messages directly into the outgoing server thread.
|
||||
|
@ -164,20 +184,27 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
if (!sog.IsDeleted)
|
||||
{
|
||||
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
|
||||
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.UpdateObject, sogxml));
|
||||
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.UpdatedObject, sogxml));
|
||||
}
|
||||
}
|
||||
foreach (ScenePresence presence in presenceUpdates)
|
||||
{
|
||||
if (!presence.IsDeleted)
|
||||
{
|
||||
OSDMap data = new OSDMap(4);
|
||||
OSDMap data = new OSDMap(5);
|
||||
data["id"] = OSD.FromUUID(presence.UUID);
|
||||
// Do not include offset for appearance height. That will be handled by RegionSyncClient before sending to viewers
|
||||
if(presence.AbsolutePosition.IsFinite())
|
||||
data["pos"] = OSD.FromVector3(presence.AbsolutePosition);
|
||||
else
|
||||
data["pos"] = OSD.FromVector3(Vector3.Zero);
|
||||
if(presence.Velocity.IsFinite())
|
||||
data["vel"] = OSD.FromVector3(presence.Velocity);
|
||||
else
|
||||
data["vel"] = OSD.FromVector3(Vector3.Zero);
|
||||
data["rot"] = OSD.FromQuaternion(presence.Rotation);
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.UpdateAvatarTerse, OSDParser.SerializeJsonString(data));
|
||||
data["fly"] = OSD.FromBoolean(presence.Flying);
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.UpdatedAvatar, OSDParser.SerializeJsonString(data));
|
||||
m_server.Broadcast(rsm);
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +220,7 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
OSDMap data = new OSDMap(2);
|
||||
data["regionHandle"] = OSD.FromULong(regionHandle);
|
||||
data["localID"] = OSD.FromUInteger(localID);
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.RemoveObject, OSDParser.SerializeJsonString(data));
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.RemovedObject, OSDParser.SerializeJsonString(data));
|
||||
m_server.Broadcast(rsm);
|
||||
}
|
||||
|
||||
|
@ -272,10 +299,12 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
#region Event Handlers
|
||||
private void SceneGraph_OnObjectCreate(EntityBase entity)
|
||||
{
|
||||
if (!Synced)
|
||||
return;
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
string sogxml = SceneObjectSerializer.ToXml2Format((SceneObjectGroup)entity);
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.AddObject, sogxml);
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.NewObject, sogxml);
|
||||
m_server.Broadcast(rsm);
|
||||
}
|
||||
else
|
||||
|
@ -286,10 +315,12 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
|
||||
private void SceneGraph_OnObjectDuplicate(EntityBase original, EntityBase copy)
|
||||
{
|
||||
if (!Synced)
|
||||
return;
|
||||
if (original is SceneObjectGroup && copy is SceneObjectGroup)
|
||||
{
|
||||
string sogxml = SceneObjectSerializer.ToXml2Format((SceneObjectGroup)copy);
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.AddObject, sogxml);
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.NewObject, sogxml);
|
||||
m_server.Broadcast(rsm);
|
||||
}
|
||||
else
|
||||
|
@ -300,10 +331,12 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
|
||||
private void SceneGraph_OnObjectRemove(EntityBase entity)
|
||||
{
|
||||
if (!Synced)
|
||||
return;
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
// No reason to send the entire object, just send the UUID to be deleted
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.RemoveObject, entity.UUID.ToString());
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.RemovedObject, entity.UUID.ToString());
|
||||
m_server.Broadcast(rsm);
|
||||
}
|
||||
else
|
||||
|
@ -315,6 +348,8 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
// A ficticious event
|
||||
public void Scene_AddNewPrim(SceneObjectGroup sog)
|
||||
{
|
||||
if (!Synced)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -385,47 +420,47 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
|
||||
void EventManager_OnClientMovement(ScenePresence client)
|
||||
{
|
||||
|
||||
m_moveCounter++;
|
||||
if (m_moveCounter % 100 == 0)
|
||||
{
|
||||
string msg = (string.Format("EventManager_OnClientMovement - Event has been triggered 100 times"));
|
||||
m_server.Broadcast(msg);
|
||||
m_log.Warn("REGION SYNC SERVER MODULE] " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EventManager_OnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID)
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC SERVER MODULE] (OnAvatarEnteringNewParcel) Avatar \"{0}\" has joined the scene (1) {2} {3} {4}", avatar.Name, avatar.ControllingClient.AgentId.ToString(), avatar.UUID.ToString(), localLandID, regionID.ToString());
|
||||
DebugSceneStats();
|
||||
}
|
||||
|
||||
*/
|
||||
private void EventManager_OnNewPresence(ScenePresence presence)
|
||||
{
|
||||
if (!Synced)
|
||||
return;
|
||||
m_log.WarnFormat("[REGION SYNC SERVER MODULE] (OneNewPresence) \"{0}\"", presence.Name);
|
||||
}
|
||||
|
||||
private void EventManager_OnNewClient(IClientAPI client)
|
||||
{
|
||||
ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
|
||||
if (presence != null)
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC SERVER MODULE] (OnNewClient) \"{0}\"", presence.Name);
|
||||
DebugSceneStats();
|
||||
if (!Synced)
|
||||
return;
|
||||
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Agent \"{0}\" (1) has joined the scene", client.FirstName + " " + client.LastName, client.AgentId.ToString());
|
||||
// Let the client managers know that a new agent has connected
|
||||
OSDMap data = new OSDMap(1);
|
||||
data["agentID"] = OSD.FromUUID(client.AgentId);
|
||||
data["first"] = OSD.FromString(client.FirstName);
|
||||
data["last"] = OSD.FromString(client.LastName);
|
||||
data["startPos"] = OSD.FromVector3(client.StartPos);
|
||||
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.NewAvatar, OSDParser.SerializeJsonString(data)));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC SERVER MODULE] (OnNewClient) A new client connected but module could not get ScenePresence");
|
||||
}
|
||||
}
|
||||
|
||||
private void EventManager_OnNewPresence(ScenePresence presence)
|
||||
{
|
||||
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Avatar \"{0}\" (1) {2} has joined the scene", presence.Firstname + " " + presence.Lastname, presence.ControllingClient.AgentId.ToString(), presence.UUID.ToString());
|
||||
DebugSceneStats();
|
||||
}
|
||||
* */
|
||||
|
||||
private void EventManager_OnRemovePresence(UUID agentID)
|
||||
{
|
||||
if (!Synced)
|
||||
return;
|
||||
/*
|
||||
ScenePresence avatar;
|
||||
if (m_scene.TryGetScenePresence(agentID, out avatar))
|
||||
{
|
||||
|
@ -435,39 +470,61 @@ namespace OpenSim.Region.Examples.RegionSyncModule
|
|||
{
|
||||
m_log.WarnFormat("[REGION SYNC SERVER MODULE] Avatar \"unknown\" has left the scene");
|
||||
}
|
||||
OSDArray data = new OSDArray();
|
||||
data.Add(OSD.FromULong(avatar.RegionHandle));
|
||||
data.Add(OSD.FromUInteger(avatar.LocalId));
|
||||
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.RemoveAvatar, data.ToString());
|
||||
m_server.Broadcast(rsm);
|
||||
* */
|
||||
OSDMap data = new OSDMap();
|
||||
data["agentID"] = OSD.FromUUID(agentID);
|
||||
m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.RemovedAvatar, OSDParser.SerializeJsonString(data)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/*
|
||||
private void DebugSceneStats()
|
||||
#region Console Command Interface
|
||||
private void InstallInterfaces()
|
||||
{
|
||||
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);
|
||||
Command cmdSyncStats = new Command("stats", CommandIntentions.COMMAND_HAZARDOUS, SyncStats, "Reports stats for the RegionSyncServer.");
|
||||
m_commander.RegisterCommand("stats", cmdSyncStats);
|
||||
|
||||
lock (m_scene)
|
||||
{
|
||||
// Add this to our scene so scripts can call these functions
|
||||
m_scene.RegisterModuleCommander(m_commander);
|
||||
}
|
||||
}
|
||||
|
||||
public IClientAPI ClientAggregator
|
||||
|
||||
/// <summary>
|
||||
/// Processes commandline input. Do not call directly.
|
||||
/// </summary>
|
||||
/// <param name="args">Commandline arguments</param>
|
||||
private void EventManager_OnPluginConsole(string[] args)
|
||||
{
|
||||
get {return m_clientAggregator;}
|
||||
if (args[0] == "sync")
|
||||
{
|
||||
if (args.Length == 1)
|
||||
{
|
||||
m_commander.ProcessConsoleCommand("help", new string[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
private void AddAvatars()
|
||||
{
|
||||
for (int i = 0; i < 1; i++)
|
||||
{
|
||||
MyNpcCharacter m_character = new MyNpcCharacter(m_scene, this);
|
||||
m_scene.AddNewClient(m_character);
|
||||
string[] tmpArgs = new string[args.Length - 2];
|
||||
int i;
|
||||
for (i = 2; i < args.Length; i++)
|
||||
tmpArgs[i - 2] = args[i];
|
||||
|
||||
m_scene.AgentCrossing(m_character.AgentId, m_character.StartPos, false);
|
||||
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private void SyncStats(Object[] args)
|
||||
{
|
||||
if (Synced)
|
||||
m_server.ReportStats();
|
||||
else if (m_server != null)
|
||||
m_log.Error("No RegionSyncClients connected");
|
||||
else
|
||||
m_log.Error("The RegionSyncServer is not running!");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,5 +35,6 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
{
|
||||
bool Active { get; }
|
||||
bool Synced { get; }
|
||||
void SendCoarseLocations();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1429,21 +1429,49 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
// Run through all ScenePresences looking for updates
|
||||
// Presence updates and queued object updates for each presence are sent to clients
|
||||
// If it's a synced client, just send prim updates
|
||||
// This will get fixed later to only send to locally logged in presences rather than all presences
|
||||
// but requires pulling apart the concept of a client from the concept of a presence/avatar
|
||||
if (IsSyncedClient())
|
||||
{
|
||||
ForEachScenePresence(delegate(ScenePresence sp) { sp.SendPrimUpdates(); });
|
||||
RegionSyncClientModule.SendCoarseLocations();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_frame % m_update_presences == 0)
|
||||
m_sceneGraph.UpdatePresences();
|
||||
}
|
||||
|
||||
// REGION SYNC
|
||||
// If this is a synced server, send updates to client managers at this time
|
||||
// This batches updates, but the client manager will forward on to clients without
|
||||
// additional delay
|
||||
if (IsSyncedServer())
|
||||
{
|
||||
m_regionSyncServerModule.SendUpdates();
|
||||
}
|
||||
|
||||
int tmpPhysicsMS2 = Util.EnvironmentTickCount();
|
||||
// Do not simulate physics locally if this is a synced client
|
||||
if (!IsSyncedClient())
|
||||
{
|
||||
if ((m_frame % m_update_physics == 0) && m_physics_enabled)
|
||||
m_sceneGraph.UpdatePreparePhysics();
|
||||
}
|
||||
physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
|
||||
|
||||
// Do not simulate physics locally if this is a synced client
|
||||
if (!IsSyncedClient())
|
||||
{
|
||||
if (m_frame % m_update_entitymovement == 0)
|
||||
m_sceneGraph.UpdateScenePresenceMovement();
|
||||
}
|
||||
|
||||
int tmpPhysicsMS = Util.EnvironmentTickCount();
|
||||
// Do not simulate physics locally if this is a synced client
|
||||
if (!IsSyncedClient())
|
||||
{
|
||||
if (m_frame % m_update_physics == 0)
|
||||
{
|
||||
if (m_physics_enabled)
|
||||
|
@ -1451,6 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (SynchronizeScene != null)
|
||||
SynchronizeScene(this);
|
||||
}
|
||||
}
|
||||
physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
|
||||
|
||||
// Delete temp-on-rez stuff
|
||||
|
@ -1562,7 +1591,46 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
public void GetCoarseLocations(out List<UUID> ids, out List<Vector3> locations)
|
||||
{
|
||||
List<UUID> resultIds = new List<UUID>();
|
||||
List<Vector3> resultLocations = new List<Vector3>();
|
||||
|
||||
ForEachScenePresence(delegate(ScenePresence sp)
|
||||
{
|
||||
if (sp.IsChildAgent)
|
||||
return;
|
||||
resultIds.Add(sp.UUID);
|
||||
resultLocations.Add(sp.AbsolutePosition);
|
||||
});
|
||||
ids = resultIds;
|
||||
locations = resultLocations;
|
||||
|
||||
/*
|
||||
if (sp.ParentID != 0)
|
||||
{
|
||||
// sitting avatar
|
||||
SceneObjectPart sop = GetSceneObjectPart(sp.ParentID);
|
||||
if (sop != null)
|
||||
{
|
||||
locations.Add(sop.AbsolutePosition + sp.m_pos);
|
||||
ids.Add(sp.UUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can't find the parent.. ! arg!
|
||||
locations.Add(sp.m_pos);
|
||||
ids.Add(sp.UUID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
locations.Add(sp.m_pos);
|
||||
ids.Add(sp.UUID);
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
public void AddGroupTarget(SceneObjectGroup grp)
|
||||
{
|
||||
|
@ -3233,9 +3301,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
m_eventManager.TriggerOnRemovePresence(agentID);
|
||||
|
||||
if(IsSyncedServer())
|
||||
RegionSyncServerModule.DeleteObject(avatar.RegionHandle, avatar.LocalId);
|
||||
else
|
||||
// Don't try to send kills to clients if this is a synced server.
|
||||
// The client closed event will trigger the broadcast to client managers
|
||||
//if(!IsSyncedServer())
|
||||
{
|
||||
ForEachClient(
|
||||
delegate(IClientAPI client)
|
||||
|
@ -3325,11 +3393,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
|
||||
|
||||
// REGION SYNC
|
||||
if( IsSyncedServer() )
|
||||
RegionSyncServerModule.DeleteObject(m_regionHandle, localID);
|
||||
else
|
||||
ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -4365,11 +4433,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// Performs action on all scene presences.
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
static int s_ForEachPresenceCounter = 0;
|
||||
public void ForEachScenePresence(Action<ScenePresence> action)
|
||||
{
|
||||
if (IsSyncedServer())
|
||||
return;
|
||||
//if (IsSyncedServer())
|
||||
// return;
|
||||
// We don't want to try to send messages if there are no avatars.
|
||||
if (m_sceneGraph != null)
|
||||
{
|
||||
|
@ -4450,7 +4517,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public void ForEachClient(Action<IClientAPI> action)
|
||||
{
|
||||
// REGION SYNC
|
||||
if (IsSyncedServer())
|
||||
if (false)//IsSyncedServer())
|
||||
return;
|
||||
m_clientManager.ForEachSync(action);
|
||||
}
|
||||
|
|
|
@ -1272,7 +1272,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (Scene.IsSyncedServer())
|
||||
{
|
||||
Scene.RegionSyncServerModule.DeleteObject(part.RegionHandle, part.LocalId);
|
||||
return;
|
||||
//return;
|
||||
}
|
||||
Scene.ForEachScenePresence(delegate(ScenePresence avatar)
|
||||
{
|
||||
|
|
|
@ -1259,13 +1259,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public void AddFullUpdateToAllAvatars()
|
||||
{
|
||||
// REGION SYNC
|
||||
if (m_parentGroup.Scene.IsSyncedServer())
|
||||
m_parentGroup.Scene.RegionSyncServerModule.QueuePartForUpdate(this);
|
||||
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
|
||||
{
|
||||
avatar.SceneViewer.QueuePartForUpdate(this);
|
||||
});
|
||||
// REGION SYNC
|
||||
if (m_parentGroup.Scene.IsSyncedServer())
|
||||
m_parentGroup.Scene.RegionSyncServerModule.QueuePartForUpdate(this);
|
||||
}
|
||||
|
||||
public void AddFullUpdateToAvatar(ScenePresence presence)
|
||||
|
@ -1286,12 +1286,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// Terse updates
|
||||
public void AddTerseUpdateToAllAvatars()
|
||||
{
|
||||
if (m_parentGroup.Scene.IsSyncedServer())
|
||||
m_parentGroup.Scene.RegionSyncServerModule.QueuePartForUpdate(this);
|
||||
m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
|
||||
{
|
||||
avatar.SceneViewer.QueuePartForUpdate(this);
|
||||
});
|
||||
// REGION SYNC
|
||||
if (m_parentGroup.Scene.IsSyncedServer())
|
||||
m_parentGroup.Scene.RegionSyncServerModule.QueuePartForUpdate(this);
|
||||
}
|
||||
|
||||
public void AddTerseUpdateToAvatar(ScenePresence presence)
|
||||
|
|
|
@ -383,6 +383,18 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
set { m_allowMovement = value; }
|
||||
}
|
||||
|
||||
// Added for region sync module.
|
||||
// Should not rely on a physics actor like so many of these params seem to
|
||||
public bool Flying
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PhysicsActor != null)
|
||||
return PhysicsActor.Flying;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SetAlwaysRun
|
||||
{
|
||||
get
|
||||
|
@ -688,12 +700,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
AbsolutePosition = posLastSignificantMove = m_CameraCenter =
|
||||
m_lastCameraCenter = m_controllingClient.StartPos;
|
||||
|
||||
if (!m_scene.IsSyncedServer())
|
||||
{
|
||||
m_reprioritization_timer = new Timer(world.ReprioritizationInterval);
|
||||
m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
|
||||
m_reprioritization_timer.AutoReset = false;
|
||||
}
|
||||
|
||||
AdjustKnownSeeds();
|
||||
|
||||
|
@ -1196,6 +1205,39 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
// Move the avatar to a specific position, velocity and rotation and mark it as changed
|
||||
// Mostly copied from HandleAgentUpdate
|
||||
public void MoveTo(Vector3 pos, Vector3 vel, Quaternion rot)
|
||||
{
|
||||
++m_movementUpdateCount;
|
||||
if (m_movementUpdateCount < 1)
|
||||
m_movementUpdateCount = 1;
|
||||
#region Sanity Checking
|
||||
|
||||
// This is irritating. Really.
|
||||
if (!AbsolutePosition.IsFinite())
|
||||
{
|
||||
RemoveFromPhysicalScene();
|
||||
m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
|
||||
|
||||
m_pos = m_LastFinitePos;
|
||||
if (!m_pos.IsFinite())
|
||||
{
|
||||
m_pos.X = 127f;
|
||||
m_pos.Y = 127f;
|
||||
m_pos.Z = 127f;
|
||||
m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
|
||||
}
|
||||
|
||||
AddToPhysicalScene(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LastFinitePos = m_pos;
|
||||
}
|
||||
#endregion Sanity Checking
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the event handler for client movement. If a client is moving, this event is triggering.
|
||||
/// </summary>
|
||||
|
@ -2324,6 +2366,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
SendTerseUpdateToAllClients();
|
||||
|
||||
// REGION SYNC
|
||||
if(m_scene.IsSyncedServer())
|
||||
m_scene.RegionSyncServerModule.QueuePresenceForTerseUpdate(this);
|
||||
|
||||
// Update the "last" values
|
||||
m_lastPosition = m_pos;
|
||||
m_lastRotation = m_bodyRot;
|
||||
|
@ -2382,6 +2428,19 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a location/velocity/accelleration update to all agents in a list
|
||||
/// </summary>
|
||||
public void SendTerseUpdateToClientList(List<IClientAPI> clients)
|
||||
{
|
||||
m_perfMonMS = Util.EnvironmentTickCount();
|
||||
foreach( IClientAPI client in clients)
|
||||
{
|
||||
SendTerseUpdateToClient(client);
|
||||
}
|
||||
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
||||
}
|
||||
|
||||
public void SendCoarseLocations()
|
||||
{
|
||||
SendCourseLocationsMethod d = m_sendCourseLocationsMethod;
|
||||
|
@ -2400,39 +2459,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p)
|
||||
{
|
||||
m_perfMonMS = Util.EnvironmentTickCount();
|
||||
|
||||
List<Vector3> CoarseLocations = new List<Vector3>();
|
||||
List<UUID> AvatarUUIDs = new List<UUID>();
|
||||
m_scene.ForEachScenePresence(delegate(ScenePresence sp)
|
||||
{
|
||||
if (sp.IsChildAgent)
|
||||
return;
|
||||
|
||||
if (sp.ParentID != 0)
|
||||
{
|
||||
// sitting avatar
|
||||
SceneObjectPart sop = m_scene.GetSceneObjectPart(sp.ParentID);
|
||||
if (sop != null)
|
||||
{
|
||||
CoarseLocations.Add(sop.AbsolutePosition + sp.m_pos);
|
||||
AvatarUUIDs.Add(sp.UUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can't find the parent.. ! arg!
|
||||
CoarseLocations.Add(sp.m_pos);
|
||||
AvatarUUIDs.Add(sp.UUID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CoarseLocations.Add(sp.m_pos);
|
||||
AvatarUUIDs.Add(sp.UUID);
|
||||
}
|
||||
});
|
||||
|
||||
List<Vector3> CoarseLocations = new List<Vector3>();
|
||||
// This is not cheap to compile this list of locations.
|
||||
// It should ideally be done once and then sent to every client rather than compiled for each client
|
||||
m_scene.GetCoarseLocations(out AvatarUUIDs, out CoarseLocations);
|
||||
m_controllingClient.SendCoarseLocationUpdate(AvatarUUIDs, CoarseLocations);
|
||||
|
||||
m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Nini.Config;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
@ -36,6 +38,8 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
|||
{
|
||||
public class BasicScene : PhysicsScene
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private List<BasicActor> _actors = new List<BasicActor>();
|
||||
private float[] _heightMap;
|
||||
|
||||
|
@ -129,7 +133,16 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
|||
actorPosition.X = ((int)Constants.RegionSize - 0.1f);
|
||||
}
|
||||
|
||||
float height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z;
|
||||
float height = 25.0F;
|
||||
try
|
||||
{
|
||||
height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z;
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
m_log.WarnFormat("[BASICPHYSICS]: Actor out of range: {0}", actor.SOPName, actor.Position.ToString());
|
||||
}
|
||||
|
||||
if (actor.Flying)
|
||||
{
|
||||
if (actor.Position.Z + (actor.Velocity.Z*timeStep) <
|
||||
|
|
|
@ -906,10 +906,9 @@ namespace OpenSim.Region.Physics.OdePlugin
|
|||
d.Vector3 localpos = d.BodyGetPosition(Body);
|
||||
Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z);
|
||||
|
||||
if (!localPos.IsFinite())
|
||||
if (!localPos.IsFinite() || localpos.X < 0.0 || localpos.X > 256.0 || localpos.Y < 0.0 || localpos.Y > 256.0 || localpos.Z < 0.0)
|
||||
{
|
||||
|
||||
m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
|
||||
m_log.Warn("[PHYSICS]: Avatar Position is non-finite or out of bounds!");
|
||||
defects.Add(this);
|
||||
// _parent_scene.RemoveCharacter(this);
|
||||
|
||||
|
|
Loading…
Reference in New Issue