Compare commits

...

4 Commits

7 changed files with 144 additions and 74 deletions

View File

@@ -123,6 +123,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
availableMethods["admin_region_query"] = XmlRpcRegionQueryMethod;
availableMethods["admin_shutdown"] = XmlRpcShutdownMethod;
availableMethods["admin_broadcast"] = XmlRpcAlertMethod;
availableMethods["admin_dialog"] = XmlRpcDialogMethod;
availableMethods["admin_restart"] = XmlRpcRestartMethod;
availableMethods["admin_load_heightmap"] = XmlRpcLoadHeightmapMethod;
// User management
@@ -277,6 +278,53 @@ namespace OpenSim.ApplicationPlugins.RemoteController
m_log.Info("[RADMIN]: Alert request complete");
return response;
}
public XmlRpcResponse XmlRpcDialogMethod(XmlRpcRequest request, IPEndPoint remoteClient)
{
XmlRpcResponse response = new XmlRpcResponse();
Hashtable responseData = new Hashtable();
m_log.Info("[RADMIN]: Dialog request started");
try
{
Hashtable requestData = (Hashtable)request.Params[0];
checkStringParameters(request, new string[] { "password", "from", "message" });
if (m_requiredPassword != String.Empty &&
(!requestData.Contains("password") || (string)requestData["password"] != m_requiredPassword))
throw new Exception("wrong password");
string message = (string)requestData["message"];
string fromuuid = (string)requestData["from"];
m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message);
responseData["accepted"] = true;
responseData["success"] = true;
response.Value = responseData;
m_app.SceneManager.ForEachScene(
delegate(Scene scene)
{
IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
if (dialogModule != null)
dialogModule.SendNotificationToUsersInRegion(UUID.Zero, fromuuid, message);
});
}
catch (Exception e)
{
m_log.ErrorFormat("[RADMIN]: Broadcasting: failed: {0}", e.Message);
m_log.DebugFormat("[RADMIN]: Broadcasting: failed: {0}", e.ToString());
responseData["accepted"] = false;
responseData["success"] = false;
responseData["error"] = e.Message;
response.Value = responseData;
}
m_log.Info("[RADMIN]: Alert request complete");
return response;
}
public XmlRpcResponse XmlRpcLoadHeightmapMethod(XmlRpcRequest request, IPEndPoint remoteClient)
{

View File

@@ -785,6 +785,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public virtual void SendLayerData(float[] map)
{
Util.FireAndForget(DoSendLayerData, map);
// Send it sync, and async. It's not that much data
// and it improves user experience just so much!
DoSendLayerData(map);
}
/// <summary>
@@ -797,16 +801,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
try
{
//for (int y = 0; y < 16; y++)
//{
// for (int x = 0; x < 16; x++)
// {
// SendLayerData(x, y, map);
// }
//}
// Send LayerData in a spiral pattern. Fun!
SendLayerTopRight(map, 0, 0, 15, 15);
for (int y = 0; y < 16; y++)
{
for (int x = 0; x < 16; x+=4)
{
SendLayerPacket(x, y, map);
}
}
}
catch (Exception e)
{
@@ -814,51 +815,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
{
// Row
for (int i = x1; i <= x2; i++)
SendLayerData(i, y1, map);
// Column
for (int j = y1 + 1; j <= y2; j++)
SendLayerData(x2, j, map);
if (x2 - x1 > 0)
SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
}
void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
{
// Row in reverse
for (int i = x2; i >= x1; i--)
SendLayerData(i, y2, map);
// Column in reverse
for (int j = y2 - 1; j >= y1; j--)
SendLayerData(x1, j, map);
if (x2 - x1 > 0)
SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
}
/// <summary>
/// Sends a set of four patches (x, x+1, ..., x+3) to the client
/// </summary>
/// <param name="map">heightmap</param>
/// <param name="px">X coordinate for patches 0..12</param>
/// <param name="py">Y coordinate for patches 0..15</param>
// private void SendLayerPacket(float[] map, int y, int x)
// {
// int[] patches = new int[4];
// patches[0] = x + 0 + y * 16;
// patches[1] = x + 1 + y * 16;
// patches[2] = x + 2 + y * 16;
// patches[3] = x + 3 + y * 16;
private void SendLayerPacket(int x, int y, float[] map)
{
int[] patches = new int[4];
patches[0] = x + 0 + y * 16;
patches[1] = x + 1 + y * 16;
patches[2] = x + 2 + y * 16;
patches[3] = x + 3 + y * 16;
// Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
// OutPacket(layerpack, ThrottleOutPacketType.Land);
// }
float[] heightmap = (map.Length == 65536) ?
map :
LLHeightFieldMoronize(map);
try
{
Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
OutPacket(layerpack, ThrottleOutPacketType.Land);
}
catch
{
for (int px = x ; px < x + 4 ; px++)
SendLayerData(px, y, map);
}
}
/// <summary>
/// Sends a specified patch to a client

View File

@@ -399,6 +399,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Queue or Send
OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
outgoingPacket.Type = type;
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
SendPacketFinal(outgoingPacket);
@@ -510,6 +511,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
byte flags = buffer.Data[0];
bool isResend = (flags & Helpers.MSG_RESENT) != 0;
bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
bool sendSynchronous = false;
LLUDPClient udpClient = outgoingPacket.Client;
if (!udpClient.IsConnected)
@@ -565,9 +567,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (isReliable)
Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength);
// Put the UDP payload on the wire
AsyncBeginSend(buffer);
//Some packet types need to be sent synchonously.
//Sorry, i know it's not optimal, but until the LL client
//manages packets correctly and re-orders them as required, this is necessary.
if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate
|| outgoingPacket.Type == PacketType.ChatFromSimulator
|| outgoingPacket.Type == PacketType.ObjectUpdate
|| outgoingPacket.Type == PacketType.LayerData)
{
sendSynchronous = true;
}
// Put the UDP payload on the wire
if (sendSynchronous == true)
{
SyncBeginSend(buffer);
}
else
{
AsyncBeginSend(buffer);
}
// Keep track of when this packet was sent out (right now)
outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
}

View File

@@ -246,6 +246,24 @@ namespace OpenMetaverse
}
}
public void SyncBeginSend(UDPPacketBuffer buf)
{
if (!m_shutdownFlag)
{
try
{
m_udpSocket.SendTo(
buf.Data,
0,
buf.DataLength,
SocketFlags.None,
buf.RemoteEndPoint);
}
catch (SocketException) { }
catch (ObjectDisposedException) { }
}
}
public void AsyncBeginSend(UDPPacketBuffer buf)
{
if (!m_shutdownFlag)

View File

@@ -28,6 +28,7 @@
using System;
using OpenSim.Framework;
using OpenMetaverse;
using OpenMetaverse.Packets;
namespace OpenSim.Region.ClientStack.LindenUDP
{
@@ -52,7 +53,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public int TickCount;
/// <summary>Category this packet belongs to</summary>
public ThrottleOutPacketType Category;
/// <summary>The type of packet so its delivery method can be determined</summary>
public PacketType Type;
/// <summary>
/// Default constructor
/// </summary>

View File

@@ -164,19 +164,22 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
List<GridInstantMessage>msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>(
"POST", m_RestURL+"/RetrieveMessages/", client.AgentId);
foreach (GridInstantMessage im in msglist)
if (msglist != null)
{
// client.SendInstantMessage(im);
foreach (GridInstantMessage im in msglist)
{
// client.SendInstantMessage(im);
// Send through scene event manager so all modules get a chance
// to look at this message before it gets delivered.
//
// Needed for proper state management for stored group
// invitations
//
Scene s = FindScene(client.AgentId);
if (s != null)
s.EventManager.TriggerIncomingInstantMessage(im);
// Send through scene event manager so all modules get a chance
// to look at this message before it gets delivered.
//
// Needed for proper state management for stored group
// invitations
//
Scene s = FindScene(client.AgentId);
if (s != null)
s.EventManager.TriggerIncomingInstantMessage(im);
}
}
}

View File

@@ -1064,14 +1064,6 @@ namespace OpenSim.Region.Framework.Scenes
}
}
/// <summary>
/// Clear all pending updates of parts to clients
/// </summary>
private void ClearUpdateSchedule()
{
m_updateFlag = 0;
}
private void SendObjectPropertiesToClient(UUID AgentID)
{
ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
@@ -2387,8 +2379,8 @@ namespace OpenSim.Region.Framework.Scenes
{
const float ROTATION_TOLERANCE = 0.01f;
const float VELOCITY_TOLERANCE = 0.001f;
const float POSITION_TOLERANCE = 0.05f;
const int TIME_MS_TOLERANCE = 3000;
const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
if (m_updateFlag == 1)
{
@@ -2401,7 +2393,7 @@ namespace OpenSim.Region.Framework.Scenes
Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
{
AddTerseUpdateToAllAvatars();
ClearUpdateSchedule();
// This causes the Scene to 'poll' physical objects every couple of frames
// bad, so it's been replaced by an event driven method.
@@ -2419,13 +2411,15 @@ namespace OpenSim.Region.Framework.Scenes
m_lastAngularVelocity = AngularVelocity;
m_lastTerseSent = Environment.TickCount;
}
//Moved this outside of the if clause so updates don't get blocked.. *sigh*
m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
}
else
{
if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
{
AddFullUpdateToAllAvatars();
ClearUpdateSchedule();
m_updateFlag = 0; //Same here
}
}
}