Next step of the PresenceModule. Still not complete; local optimizations and the
messaging server changes are still missing. Completely untested. May contain bugs.0.6.1-post-fixes
parent
4acddb6797
commit
3e42cca2c0
|
@ -54,6 +54,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
|
|||
|
||||
private List<Scene> m_Scenes = new List<Scene>();
|
||||
|
||||
// we currently are only interested in root-agents. If the root isn't here, we don't know the region the
|
||||
// user is in, so we have to ask the messaging server anyway.
|
||||
private Dictionary<UUID, Scene> m_RootAgents =
|
||||
new Dictionary<UUID, Scene>();
|
||||
|
||||
|
@ -86,14 +88,14 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
|
|||
if (m_Gridmode)
|
||||
NotifyMessageServerOfStartup(scene);
|
||||
|
||||
scene.RegisterModuleInterface<IPresenceModule>(this);
|
||||
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
|
||||
//scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
|
||||
|
||||
m_Scenes.Add(scene);
|
||||
}
|
||||
|
||||
scene.RegisterModuleInterface<IPresenceModule>(this);
|
||||
|
||||
scene.EventManager.OnNewClient += OnNewClient;
|
||||
scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
|
||||
scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
|
||||
}
|
||||
|
||||
public void PostInitialise()
|
||||
|
@ -105,6 +107,18 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
|
|||
if (!m_Gridmode || !m_Enabled)
|
||||
return;
|
||||
|
||||
if (OnPresenceChange != null)
|
||||
{
|
||||
lock (m_RootAgents)
|
||||
{
|
||||
// on shutdown, users are kicked, too
|
||||
foreach (KeyValuePair<UUID, Scene> pair in m_RootAgents)
|
||||
{
|
||||
OnPresenceChange(new PresenceInfo(pair.Key, UUID.Zero));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock (m_Scenes)
|
||||
{
|
||||
foreach (Scene scene in m_Scenes)
|
||||
|
@ -130,10 +144,6 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
|
|||
if (m_Gridmode)
|
||||
{
|
||||
// TODO process local info first and only do a server lookup if necessary.
|
||||
// TODO fix m_RootAgents contents. Currently, they won't work right in a
|
||||
// non standalone server. Consider two servers, with one sim each in a
|
||||
// 2x1 grid. Clients will never be closed, just the root moves from
|
||||
// server to server. But it stays in m_RootAgents on both servers.
|
||||
Dictionary<UUID, FriendRegionInfo> infos = m_initialScene.GetFriendRegionInfos(new List<UUID>(users));
|
||||
for (int i = 0; i < users.Length; ++i)
|
||||
{
|
||||
|
@ -178,22 +188,27 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
|
|||
}
|
||||
}
|
||||
|
||||
// new client doesn't mean necessarily that user logged in, it just means it entered one of the
|
||||
// the regions on this server
|
||||
public void OnNewClient(IClientAPI client)
|
||||
{
|
||||
client.OnConnectionClosed += OnConnectionClosed;
|
||||
client.OnLogout += OnConnectionClosed;
|
||||
client.OnLogout += OnLogout;
|
||||
|
||||
// KLUDGE: See handler for details.
|
||||
client.OnEconomyDataRequest += OnEconomyDataRequest;
|
||||
}
|
||||
|
||||
// connection closed just means *one* client connection has been closed. It doesn't mean that the
|
||||
// user has logged off; it might have just TPed away.
|
||||
public void OnConnectionClosed(IClientAPI client)
|
||||
{
|
||||
// TODO: Have to think what we have to do here...
|
||||
// Should we just remove the root from the list (if scene matches)?
|
||||
if (!(client.Scene is Scene))
|
||||
return;
|
||||
|
||||
Scene scene = (Scene)client.Scene;
|
||||
|
||||
// OnConnectionClosed can be called from several threads at once (with different client, of course)
|
||||
// Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
|
||||
// correct locking).
|
||||
lock (m_RootAgents)
|
||||
{
|
||||
Scene rootScene;
|
||||
|
@ -202,7 +217,28 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
|
|||
|
||||
m_RootAgents.Remove(client.AgentId);
|
||||
}
|
||||
|
||||
// Should it have logged off, we'll do the logout part in OnLogout, even if no root is stored
|
||||
// anymore. It logged off, after all...
|
||||
}
|
||||
|
||||
// Triggered when the user logs off.
|
||||
public void OnLogout(IClientAPI client)
|
||||
{
|
||||
m_log.DebugFormat("[PRESENCE]: Got OnLogout from {0}", client.Name);
|
||||
if (!(client.Scene is Scene))
|
||||
return;
|
||||
Scene scene = (Scene)client.Scene;
|
||||
|
||||
// On logout, we really remove the client from rootAgents, even if the scene doesn't match
|
||||
lock (m_RootAgents)
|
||||
{
|
||||
if (m_RootAgents.ContainsKey(client.AgentId)) m_RootAgents.Remove(client.AgentId);
|
||||
}
|
||||
|
||||
// now inform the messaging server and anyone who is interested
|
||||
NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle);
|
||||
if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(client.AgentId, UUID.Zero));
|
||||
}
|
||||
|
||||
public void OnSetRootAgentScene(UUID agentID, Scene scene)
|
||||
|
@ -219,27 +255,59 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage
|
|||
}
|
||||
m_RootAgents[agentID] = scene;
|
||||
}
|
||||
// inform messaging server that agent changed the region
|
||||
NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle);
|
||||
}
|
||||
|
||||
// TODO not sure about that yet
|
||||
// public void OnMakeChildAgent(ScenePresence agent)
|
||||
// {
|
||||
// // OnMakeChildAgent can be called from several threads at once (with different agent).
|
||||
// // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
|
||||
// // correct locking).
|
||||
// lock (m_RootAgents)
|
||||
// {
|
||||
// Scene rootScene;
|
||||
// if (m_RootAgents.TryGetValue(agentID, out rootScene) && agent.Scene == rootScene)
|
||||
// {
|
||||
// m_RootAgents[agentID] = scene;
|
||||
// }
|
||||
// }
|
||||
// // don't notify the messaging-server; either this is just downgraded and another one will be upgraded
|
||||
// // to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment,
|
||||
// // which will update the messaging-server, too.
|
||||
// }
|
||||
private void OnEconomyDataRequest(UUID agentID)
|
||||
{
|
||||
// KLUDGE: This is the only way I found to get a message (only) after login was completed and the
|
||||
// client is connected enough to receive UDP packets.
|
||||
// This packet seems to be sent only once, just after connection was established to the first
|
||||
// region after login.
|
||||
// We use it here to trigger a presence update; the old update-on-login was never be heard by
|
||||
// the freshly logged in viewer, as it wasn't connected to the region at that time.
|
||||
// TODO: Feel free to replace this by a better solution if you find one.
|
||||
|
||||
// get the agent. This should work every time, as we just got a packet from it
|
||||
ScenePresence agent = null;
|
||||
lock (m_Scenes)
|
||||
{
|
||||
foreach (Scene scene in m_Scenes)
|
||||
{
|
||||
agent = scene.GetScenePresence(agentID);
|
||||
if (agent != null) break;
|
||||
}
|
||||
}
|
||||
|
||||
// just to be paranoid...
|
||||
if (agent == null)
|
||||
{
|
||||
m_log.ErrorFormat("[PRESENCE]: Got a packet from agent {0} who can't be found anymore!?", agentID);
|
||||
return;
|
||||
}
|
||||
|
||||
// we are a bit premature here, but the next packet will switch this child agent to root.
|
||||
if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(agentID, agent.Scene.RegionInfo.RegionID));
|
||||
}
|
||||
|
||||
public void OnMakeChildAgent(ScenePresence agent)
|
||||
{
|
||||
// OnMakeChildAgent can be called from several threads at once (with different agent).
|
||||
// Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
|
||||
// correct locking).
|
||||
lock (m_RootAgents)
|
||||
{
|
||||
Scene rootScene;
|
||||
if (m_RootAgents.TryGetValue(agent.UUID, out rootScene) && agent.Scene == rootScene)
|
||||
{
|
||||
m_RootAgents.Remove(agent.UUID);
|
||||
}
|
||||
}
|
||||
// don't notify the messaging-server; either this agent just had been downgraded and another one will be upgraded
|
||||
// to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment,
|
||||
// which will update the messaging-server, too.
|
||||
}
|
||||
|
||||
private void NotifyMessageServerOfStartup(Scene scene)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue