Compare commits
24 Commits
Author | SHA1 | Date |
---|---|---|
Justin Clark-Casey (justincc) | 741caee040 | |
Justin Clark-Casey (justincc) | e7f1695338 | |
Justin Clark-Casey (justincc) | bd962f7e07 | |
Robert Adams | 2995cde302 | |
Robert Adams | b58ab0ca12 | |
Justin Clark-Casey (justincc) | f23be9cd0a | |
Justin Clark-Casey (justincc) | 08d3452092 | |
Diva Canto | 42644e3b84 | |
Justin Clark-Casey (justincc) | 4509bbb8e4 | |
Justin Clark-Casey (justincc) | 26f0e9fa66 | |
Justin Clark-Casey (justincc) | 49c4fc405d | |
Justin Clark-Casey (justincc) | 3d0ded051c | |
AliciaRaven | f0bccb3d77 | |
Justin Clark-Casey (justincc) | f07828784b | |
Justin Clark-Casey (justincc) | b7d2d497fe | |
Justin Clark-Casey (justincc) | 9907b429d6 | |
Justin Clark-Casey (justincc) | 1797601fec | |
Justin Clark-Casey (justincc) | c3dd46ca87 | |
Justin Clark-Casey (justincc) | f1204c4752 | |
Justin Clark-Casey (justincc) | 202533c8ed | |
Justin Clark-Casey (justincc) | 979afbd748 | |
Justin Clark-Casey (justincc) | d748c0896d | |
Justin Clark-Casey (justincc) | 7317092733 | |
Justin Clark-Casey (justincc) | e9901ecfda |
|
@ -97,7 +97,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||||
osdname["display_name"] = OSD.FromString(name);
|
osdname["display_name"] = OSD.FromString(name);
|
||||||
osdname["legacy_first_name"] = parts[0];
|
osdname["legacy_first_name"] = parts[0];
|
||||||
osdname["legacy_last_name"] = parts[1];
|
osdname["legacy_last_name"] = parts[1];
|
||||||
osdname["username"] = OSD.FromString(name);
|
osdname["username"] = "";
|
||||||
osdname["id"] = OSD.FromUUID(uuid);
|
osdname["id"] = OSD.FromUUID(uuid);
|
||||||
osdname["is_display_name_default"] = OSD.FromBoolean(false);
|
osdname["is_display_name_default"] = OSD.FromBoolean(false);
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
|
m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", ex);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -87,7 +87,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
|
m_log.Warn("[POLL SERVICE WORKER THREAD]: Error ", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
PollServiceArgs.RequestsHandled++;
|
PollServiceArgs.RequestsHandled++;
|
||||||
|
|
|
@ -235,7 +235,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod, UUID agentID)
|
private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod, UUID agentID)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request");
|
// m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request");
|
||||||
|
|
||||||
OSDMap copy = DeepCopy();
|
OSDMap copy = DeepCopy();
|
||||||
|
|
||||||
|
|
|
@ -119,8 +119,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public readonly uint CircuitCode;
|
public readonly uint CircuitCode;
|
||||||
/// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
|
/// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
|
||||||
public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
|
public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true then we take action in response to unacked reliably sent packets such as resending the packet.
|
||||||
|
/// </summary>
|
||||||
|
public bool ProcessUnackedSends { get; set; }
|
||||||
|
|
||||||
/// <summary>Packets we have sent that need to be ACKed by the client</summary>
|
/// <summary>Packets we have sent that need to be ACKed by the client</summary>
|
||||||
public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
|
public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
|
||||||
|
|
||||||
/// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
|
/// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
|
||||||
public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>();
|
public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>();
|
||||||
|
|
||||||
|
@ -225,6 +232,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (maxRTO != 0)
|
if (maxRTO != 0)
|
||||||
m_maxRTO = maxRTO;
|
m_maxRTO = maxRTO;
|
||||||
|
|
||||||
|
ProcessUnackedSends = true;
|
||||||
|
|
||||||
// Create a token bucket throttle for this client that has the scene token bucket as a parent
|
// Create a token bucket throttle for this client that has the scene token bucket as a parent
|
||||||
m_throttleClient
|
m_throttleClient
|
||||||
= new AdaptiveTokenBucket(
|
= new AdaptiveTokenBucket(
|
||||||
|
|
|
@ -1137,7 +1137,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
|
Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
|
||||||
outgoingPacket.SequenceNumber = sequenceNumber;
|
outgoingPacket.SequenceNumber = sequenceNumber;
|
||||||
|
|
||||||
if (isReliable)
|
if (udpClient.ProcessUnackedSends && isReliable)
|
||||||
{
|
{
|
||||||
// Add this packet to the list of ACK responses we are waiting on from the server
|
// Add this packet to the list of ACK responses we are waiting on from the server
|
||||||
udpClient.NeedAcks.Add(outgoingPacket);
|
udpClient.NeedAcks.Add(outgoingPacket);
|
||||||
|
@ -1325,12 +1325,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
#region ACK Receiving
|
#region ACK Receiving
|
||||||
|
|
||||||
|
if (udpClient.ProcessUnackedSends)
|
||||||
|
{
|
||||||
// Handle appended ACKs
|
// Handle appended ACKs
|
||||||
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
|
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
|
// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
|
||||||
// packet.Header.AckList.Length, client.Name, m_scene.Name);
|
// packet.Header.AckList.Length, client.Name, m_scene.Name);
|
||||||
|
|
||||||
for (int i = 0; i < packet.Header.AckList.Length; i++)
|
for (int i = 0; i < packet.Header.AckList.Length; i++)
|
||||||
udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
|
udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
|
||||||
|
@ -1341,9 +1343,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
PacketAckPacket ackPacket = (PacketAckPacket)packet;
|
PacketAckPacket ackPacket = (PacketAckPacket)packet;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
|
// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
|
||||||
// ackPacket.Packets.Length, client.Name, m_scene.Name);
|
// ackPacket.Packets.Length, client.Name, m_scene.Name);
|
||||||
|
|
||||||
for (int i = 0; i < ackPacket.Packets.Length; i++)
|
for (int i = 0; i < ackPacket.Packets.Length; i++)
|
||||||
udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
|
udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
|
||||||
|
@ -1351,6 +1353,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
// We don't need to do anything else with PacketAck packets
|
// We don't need to do anything else with PacketAck packets
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (packet.Type == PacketType.PacketAck)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion ACK Receiving
|
#endregion ACK Receiving
|
||||||
|
|
||||||
|
@ -2011,7 +2018,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
if (udpClient.IsConnected)
|
if (udpClient.IsConnected)
|
||||||
{
|
{
|
||||||
if (m_resendUnacked)
|
if (udpClient.ProcessUnackedSends && m_resendUnacked)
|
||||||
HandleUnacked(llClient);
|
HandleUnacked(llClient);
|
||||||
|
|
||||||
if (m_sendAcks)
|
if (m_sendAcks)
|
||||||
|
|
|
@ -195,6 +195,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
"Start, stop or get status of OutgoingQueueRefillEngine.",
|
"Start, stop or get status of OutgoingQueueRefillEngine.",
|
||||||
"If stopped then refill requests are processed directly via the threadpool.",
|
"If stopped then refill requests are processed directly via the threadpool.",
|
||||||
HandleOqreCommand);
|
HandleOqreCommand);
|
||||||
|
|
||||||
|
m_console.Commands.AddCommand(
|
||||||
|
"Debug",
|
||||||
|
false,
|
||||||
|
"debug lludp client get",
|
||||||
|
"debug lludp client get [<avatar-first-name> <avatar-last-name>]",
|
||||||
|
"Get debug parameters for the client. If no name is given then all client information is returned.",
|
||||||
|
"process-unacked-sends - Do we take action if a sent reliable packet has not been acked.",
|
||||||
|
HandleClientGetCommand);
|
||||||
|
|
||||||
|
m_console.Commands.AddCommand(
|
||||||
|
"Debug",
|
||||||
|
false,
|
||||||
|
"debug lludp client set",
|
||||||
|
"debug lludp client set <param> <value> [<avatar-first-name> <avatar-last-name>]",
|
||||||
|
"Set a debug parameter for a particular client. If no name is given then the value is set on all clients.",
|
||||||
|
"process-unacked-sends - Do we take action if a sent reliable packet has not been acked.",
|
||||||
|
HandleClientSetCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleShowServerThrottlesCommand(string module, string[] args)
|
private void HandleShowServerThrottlesCommand(string module, string[] args)
|
||||||
|
@ -538,6 +556,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name);
|
m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleClientGetCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Length != 4 && args.Length != 6)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("Usage: debug lludp client get [<avatar-first-name> <avatar-last-name>]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = null;
|
||||||
|
|
||||||
|
if (args.Length == 6)
|
||||||
|
name = string.Format("{0} {1}", args[4], args[5]);
|
||||||
|
|
||||||
|
m_udpServer.Scene.ForEachScenePresence(
|
||||||
|
sp =>
|
||||||
|
{
|
||||||
|
if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView)
|
||||||
|
{
|
||||||
|
LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
|
||||||
|
|
||||||
|
m_console.OutputFormat(
|
||||||
|
"Client debug parameters for {0} ({1}) in {2}",
|
||||||
|
sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name);
|
||||||
|
|
||||||
|
ConsoleDisplayList cdl = new ConsoleDisplayList();
|
||||||
|
cdl.AddRow("process-unacked-sends", udpClient.ProcessUnackedSends);
|
||||||
|
|
||||||
|
m_console.Output(cdl.ToString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleClientSetCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Length != 6 && args.Length != 8)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("Usage: debug lludp client set <param> <value> [<avatar-first-name> <avatar-last-name>]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string param = args[4];
|
||||||
|
string rawValue = args[5];
|
||||||
|
|
||||||
|
string name = null;
|
||||||
|
|
||||||
|
if (args.Length == 8)
|
||||||
|
name = string.Format("{0} {1}", args[6], args[7]);
|
||||||
|
|
||||||
|
if (param == "process-unacked-sends")
|
||||||
|
{
|
||||||
|
bool newValue;
|
||||||
|
|
||||||
|
if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newValue))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_udpServer.Scene.ForEachScenePresence(
|
||||||
|
sp =>
|
||||||
|
{
|
||||||
|
if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView)
|
||||||
|
{
|
||||||
|
LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
|
||||||
|
udpClient.ProcessUnackedSends = newValue;
|
||||||
|
|
||||||
|
m_console.OutputFormat("{0} set to {1} for {2} in {3}", param, newValue, sp.Name, m_udpServer.Scene.Name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void HandlePacketCommand(string module, string[] args)
|
private void HandlePacketCommand(string module, string[] args)
|
||||||
{
|
{
|
||||||
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
|
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
|
||||||
|
|
|
@ -795,9 +795,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
Utils.StringToBytes(sceneObjectXml),
|
Utils.StringToBytes(sceneObjectXml),
|
||||||
sp.UUID);
|
sp.UUID);
|
||||||
|
|
||||||
IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
|
if (m_invAccessModule != null)
|
||||||
|
m_invAccessModule.UpdateInventoryItemAsset(sp.UUID, item, asset);
|
||||||
invAccess.UpdateInventoryItemAsset(sp.UUID, item, asset);
|
|
||||||
|
|
||||||
// If the name of the object has been changed whilst attached then we want to update the inventory
|
// If the name of the object has been changed whilst attached then we want to update the inventory
|
||||||
// item in the viewer.
|
// item in the viewer.
|
||||||
|
|
|
@ -1059,7 +1059,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
||||||
|
|
||||||
if (!GetProfileData(ref props, foreign, out result))
|
if (!GetProfileData(ref props, foreign, out result))
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("Error getting profile for {0}: {1}", avatarID, result);
|
// m_log.DebugFormat("Error getting profile for {0}: {1}", avatarID, result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1155,7 +1155,12 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.Debug(string.Format("Request using the OpenProfile API to {0} failed", serverURI), e);
|
m_log.Debug(
|
||||||
|
string.Format(
|
||||||
|
"[PROFILES]: Request using the OpenProfile API for user {0} to {1} failed",
|
||||||
|
properties.UserId, serverURI),
|
||||||
|
e);
|
||||||
|
|
||||||
// Allow the return 'message' to say "JsonRpcRequest" and not "OpenProfile", because
|
// Allow the return 'message' to say "JsonRpcRequest" and not "OpenProfile", because
|
||||||
// the most likely reason that OpenProfile failed is that the remote server
|
// the most likely reason that OpenProfile failed is that the remote server
|
||||||
// doesn't support OpenProfile, and that's not very interesting.
|
// doesn't support OpenProfile, and that's not very interesting.
|
||||||
|
@ -1164,7 +1169,9 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
||||||
|
|
||||||
if (!secondChanceSuccess)
|
if (!secondChanceSuccess)
|
||||||
{
|
{
|
||||||
message = string.Format("JsonRpcRequest to {0} failed", serverURI);
|
message = string.Format("JsonRpcRequest for user {0} to {1} failed", properties.UserId, serverURI);
|
||||||
|
m_log.DebugFormat("[PROFILES]: {0}", message);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// else, continue below
|
// else, continue below
|
||||||
|
|
|
@ -297,6 +297,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
{
|
{
|
||||||
if (item != null && item.Owner == ownerID && asset != null)
|
if (item != null && item.Owner == ownerID && asset != null)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[INVENTORY ACCESS MODULE]: Updating item {0} {1} with new asset {2}",
|
||||||
|
// item.Name, item.ID, asset.ID);
|
||||||
|
|
||||||
item.AssetID = asset.FullID;
|
item.AssetID = asset.FullID;
|
||||||
item.Description = asset.Description;
|
item.Description = asset.Description;
|
||||||
item.Name = asset.Name;
|
item.Name = asset.Name;
|
||||||
|
@ -314,7 +318,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
(item == null || asset == null? "null item or asset" : "wrong owner"));
|
(item == null || asset == null? "null item or asset" : "wrong owner"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual List<InventoryItemBase> CopyToInventory(
|
public virtual List<InventoryItemBase> CopyToInventory(
|
||||||
|
|
|
@ -486,9 +486,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder);
|
delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder);
|
||||||
|
|
||||||
void SendInventoryAsync(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder)
|
void SendInventoryAsync(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
SendInventoryUpdate(remoteClient, new InventoryFolderBase(folderID), fetchFolders, fetchItems);
|
SendInventoryUpdate(remoteClient, new InventoryFolderBase(folderID), fetchFolders, fetchItems);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Error(
|
||||||
|
string.Format(
|
||||||
|
"[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SendInventoryComplete(IAsyncResult iar)
|
void SendInventoryComplete(IAsyncResult iar)
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public class SceneCommunicationService //one instance per region
|
public class SceneCommunicationService //one instance per region
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private static string LogHeader = "[SCENE COMMUNIATION SERVICE]";
|
private static string LogHeader = "[SCENE COMMUNICATION SERVICE]";
|
||||||
|
|
||||||
protected RegionInfo m_regionInfo;
|
protected RegionInfo m_regionInfo;
|
||||||
protected Scene m_scene;
|
protected Scene m_scene;
|
||||||
|
|
|
@ -911,9 +911,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void LoadScriptState(XmlReader reader)
|
public void LoadScriptState(XmlReader reader)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[SCENE OBJECT GROUP]: Looking for script state for {0} in {1}", Name);
|
// m_log.DebugFormat("[SCENE OBJECT GROUP]: Looking for script state for {0}", Name);
|
||||||
|
|
||||||
while (reader.ReadToFollowing("SavedScriptState"))
|
while (true)
|
||||||
|
{
|
||||||
|
if (reader.Name == "SavedScriptState" && reader.NodeType == XmlNodeType.Element)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[SCENE OBJECT GROUP]: Loading script state for {0}", Name);
|
// m_log.DebugFormat("[SCENE OBJECT GROUP]: Loading script state for {0}", Name);
|
||||||
|
|
||||||
|
@ -935,6 +937,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_log.WarnFormat("[SCENE OBJECT GROUP]: SavedScriptState element had no UUID in object {0}", Name);
|
m_log.WarnFormat("[SCENE OBJECT GROUP]: SavedScriptState element had no UUID in object {0}", Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!reader.Read())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -400,6 +400,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
private UUID RestoreSavedScriptState(UUID loadedID, UUID oldID, UUID newID)
|
private UUID RestoreSavedScriptState(UUID loadedID, UUID oldID, UUID newID)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[PRIM INVENTORY]: Restoring scripted state for item {0}, oldID {1}, loadedID {2}",
|
||||||
|
// newID, oldID, loadedID);
|
||||||
|
|
||||||
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
|
IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
|
||||||
if (engines.Length == 0) // No engine at all
|
if (engines.Length == 0) // No engine at all
|
||||||
return oldID;
|
return oldID;
|
||||||
|
@ -442,6 +446,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// This created document has only the minimun data
|
// This created document has only the minimun data
|
||||||
// necessary for XEngine to parse it successfully
|
// necessary for XEngine to parse it successfully
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[PRIM INVENTORY]: Adding legacy state {0} in {1}", stateID, newID);
|
||||||
|
|
||||||
m_part.ParentGroup.m_savedScriptState[stateID] = newDoc.OuterXml;
|
m_part.ParentGroup.m_savedScriptState[stateID] = newDoc.OuterXml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,6 +211,21 @@ public struct HACDParams
|
||||||
public float addNeighboursDistPoints; // false
|
public float addNeighboursDistPoints; // false
|
||||||
public float addFacesPoints; // false
|
public float addFacesPoints; // false
|
||||||
public float shouldAdjustCollisionMargin; // false
|
public float shouldAdjustCollisionMargin; // false
|
||||||
|
// VHACD
|
||||||
|
public float whichHACD; // zero if Bullet HACD, non-zero says VHACD
|
||||||
|
// http://kmamou.blogspot.ca/2014/12/v-hacd-20-parameters-description.html
|
||||||
|
public float vHACDresolution; // 100,000 max number of voxels generated during voxelization stage
|
||||||
|
public float vHACDdepth; // 20 max number of clipping stages
|
||||||
|
public float vHACDconcavity; // 0.0025 maximum concavity
|
||||||
|
public float vHACDplaneDownsampling; // 4 granularity of search for best clipping plane
|
||||||
|
public float vHACDconvexHullDownsampling; // 4 precision of hull gen process
|
||||||
|
public float vHACDalpha; // 0.05 bias toward clipping along symmetry planes
|
||||||
|
public float vHACDbeta; // 0.05 bias toward clipping along revolution axis
|
||||||
|
public float vHACDgamma; // 0.00125 max concavity when merging
|
||||||
|
public float vHACDpca; // 0 on/off normalizing mesh before decomp
|
||||||
|
public float vHACDmode; // 0 0:voxel based, 1: tetrahedron based
|
||||||
|
public float vHACDmaxNumVerticesPerCH; // 64 max triangles per convex hull
|
||||||
|
public float vHACDminVolumePerCH; // 0.0001 sampling of generated convex hulls
|
||||||
}
|
}
|
||||||
|
|
||||||
// The states a bullet collision object can have
|
// The states a bullet collision object can have
|
||||||
|
|
|
@ -183,6 +183,7 @@ public static class BSParam
|
||||||
public static bool VehicleEnableAngularBanking { get; private set; }
|
public static bool VehicleEnableAngularBanking { get; private set; }
|
||||||
|
|
||||||
// Convex Hulls
|
// Convex Hulls
|
||||||
|
// Parameters for convex hull routine that ships with Bullet
|
||||||
public static int CSHullMaxDepthSplit { get; private set; }
|
public static int CSHullMaxDepthSplit { get; private set; }
|
||||||
public static int CSHullMaxDepthSplitForSimpleShapes { get; private set; }
|
public static int CSHullMaxDepthSplitForSimpleShapes { get; private set; }
|
||||||
public static float CSHullConcavityThresholdPercent { get; private set; }
|
public static float CSHullConcavityThresholdPercent { get; private set; }
|
||||||
|
@ -198,6 +199,22 @@ public static class BSParam
|
||||||
public static bool BHullAddNeighboursDistPoints { get; private set; } // false
|
public static bool BHullAddNeighboursDistPoints { get; private set; } // false
|
||||||
public static bool BHullAddFacesPoints { get; private set; } // false
|
public static bool BHullAddFacesPoints { get; private set; } // false
|
||||||
public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
|
public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
|
||||||
|
public static float WhichHACD { get; private set; } // zero if Bullet HACD, non-zero says VHACD
|
||||||
|
// Parameters for VHACD 2.0: http://code.google.com/p/v-hacd
|
||||||
|
// To enable, set both ShouldUseBulletHACD=true and WhichHACD=1
|
||||||
|
// http://kmamou.blogspot.ca/2014/12/v-hacd-20-parameters-description.html
|
||||||
|
public static float VHACDresolution { get; private set; } // 100,000 max number of voxels generated during voxelization stage
|
||||||
|
public static float VHACDdepth { get; private set; } // 20 max number of clipping stages
|
||||||
|
public static float VHACDconcavity { get; private set; } // 0.0025 maximum concavity
|
||||||
|
public static float VHACDplaneDownsampling { get; private set; } // 4 granularity of search for best clipping plane
|
||||||
|
public static float VHACDconvexHullDownsampling { get; private set; } // 4 precision of hull gen process
|
||||||
|
public static float VHACDalpha { get; private set; } // 0.05 bias toward clipping along symmetry planes
|
||||||
|
public static float VHACDbeta { get; private set; } // 0.05 bias toward clipping along revolution axis
|
||||||
|
public static float VHACDgamma { get; private set; } // 0.00125 max concavity when merging
|
||||||
|
public static float VHACDpca { get; private set; } // 0 on/off normalizing mesh before decomp
|
||||||
|
public static float VHACDmode { get; private set; } // 0 0:voxel based, 1: tetrahedron based
|
||||||
|
public static float VHACDmaxNumVerticesPerCH { get; private set; } // 64 max triangles per convex hull
|
||||||
|
public static float VHACDminVolumePerCH { get; private set; } // 0.0001 sampling of generated convex hulls
|
||||||
|
|
||||||
// Linkset implementation parameters
|
// Linkset implementation parameters
|
||||||
public static float LinksetImplementation { get; private set; }
|
public static float LinksetImplementation { get; private set; }
|
||||||
|
@ -749,6 +766,33 @@ public static class BSParam
|
||||||
new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
|
new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
|
||||||
false ),
|
false ),
|
||||||
|
|
||||||
|
new ParameterDefn<float>("WhichHACD", "zero if Bullet HACD, non-zero says VHACD",
|
||||||
|
0f ),
|
||||||
|
new ParameterDefn<float>("VHACDresolution", "max number of voxels generated during voxelization stage",
|
||||||
|
100000f ),
|
||||||
|
new ParameterDefn<float>("VHACDdepth", "max number of clipping stages",
|
||||||
|
20f ),
|
||||||
|
new ParameterDefn<float>("VHACDconcavity", "maximum concavity",
|
||||||
|
0.0025f ),
|
||||||
|
new ParameterDefn<float>("VHACDplaneDownsampling", "granularity of search for best clipping plane",
|
||||||
|
4f ),
|
||||||
|
new ParameterDefn<float>("VHACDconvexHullDownsampling", "precision of hull gen process",
|
||||||
|
4f ),
|
||||||
|
new ParameterDefn<float>("VHACDalpha", "bias toward clipping along symmetry planes",
|
||||||
|
0.05f ),
|
||||||
|
new ParameterDefn<float>("VHACDbeta", "bias toward clipping along revolution axis",
|
||||||
|
0.05f ),
|
||||||
|
new ParameterDefn<float>("VHACDgamma", "max concavity when merging",
|
||||||
|
0.00125f ),
|
||||||
|
new ParameterDefn<float>("VHACDpca", "on/off normalizing mesh before decomp",
|
||||||
|
0f ),
|
||||||
|
new ParameterDefn<float>("VHACDmode", "0:voxel based, 1: tetrahedron based",
|
||||||
|
0f ),
|
||||||
|
new ParameterDefn<float>("VHACDmaxNumVerticesPerCH", "max triangles per convex hull",
|
||||||
|
64f ),
|
||||||
|
new ParameterDefn<float>("VHACDminVolumePerCH", "sampling of generated convex hulls",
|
||||||
|
0.0001f ),
|
||||||
|
|
||||||
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
||||||
(float)BSLinkset.LinksetImplementation.Compound ),
|
(float)BSLinkset.LinksetImplementation.Compound ),
|
||||||
new ParameterDefn<bool>("LinksetOffsetCenterOfMass", "If 'true', compute linkset center-of-mass and offset linkset position to account for same",
|
new ParameterDefn<bool>("LinksetOffsetCenterOfMass", "If 'true', compute linkset center-of-mass and offset linkset position to account for same",
|
||||||
|
|
|
@ -782,7 +782,7 @@ public class BSShapeHull : BSShape
|
||||||
|
|
||||||
if (meshShape.physShapeInfo.HasPhysicalShape)
|
if (meshShape.physShapeInfo.HasPhysicalShape)
|
||||||
{
|
{
|
||||||
HACDParams parms;
|
HACDParams parms = new HACDParams();
|
||||||
parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
|
parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
|
||||||
parms.minClusters = BSParam.BHullMinClusters;
|
parms.minClusters = BSParam.BHullMinClusters;
|
||||||
parms.compacityWeight = BSParam.BHullCompacityWeight;
|
parms.compacityWeight = BSParam.BHullCompacityWeight;
|
||||||
|
@ -792,6 +792,7 @@ public class BSShapeHull : BSShape
|
||||||
parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
|
parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
|
||||||
parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
|
parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
|
||||||
parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
|
parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
|
||||||
|
parms.whichHACD = 0; // Use the HACD routine that comes with Bullet
|
||||||
|
|
||||||
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
|
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
|
||||||
newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
|
newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
|
||||||
|
|
|
@ -97,6 +97,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string State { get; set; }
|
string State { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true then the engine is responsible for persisted state. If false then some other component may
|
||||||
|
/// persist state (e.g. attachments persisting in assets).
|
||||||
|
/// </summary>
|
||||||
|
bool StatePersistedHere { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Time the script was last started
|
/// Time the script was last started
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -469,8 +469,12 @@ namespace SecondLife
|
||||||
scriptCompileCounter++;
|
scriptCompileCounter++;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (File.Exists(assembly))
|
||||||
|
{
|
||||||
|
File.SetAttributes(assembly, FileAttributes.Normal);
|
||||||
File.Delete(assembly);
|
File.Delete(assembly);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (Exception e) // NOTLEGIT - Should be just FileIOException
|
catch (Exception e) // NOTLEGIT - Should be just FileIOException
|
||||||
{
|
{
|
||||||
throw new Exception("Unable to delete old existing " +
|
throw new Exception("Unable to delete old existing " +
|
||||||
|
|
|
@ -58,6 +58,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public bool StatePersistedHere { get { return m_AttachedAvatar == UUID.Zero; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current work item if an event for this script is running or waiting to run,
|
/// The current work item if an event for this script is running or waiting to run,
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -76,7 +78,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
private string m_CurrentEvent = String.Empty;
|
private string m_CurrentEvent = String.Empty;
|
||||||
private bool m_InSelfDelete;
|
private bool m_InSelfDelete;
|
||||||
private int m_MaxScriptQueue;
|
private int m_MaxScriptQueue;
|
||||||
private bool m_SaveState = true;
|
private bool m_SaveState;
|
||||||
private int m_ControlEventsInQueue;
|
private int m_ControlEventsInQueue;
|
||||||
private int m_LastControlLevel;
|
private int m_LastControlLevel;
|
||||||
private bool m_CollisionInQueue;
|
private bool m_CollisionInQueue;
|
||||||
|
@ -238,6 +240,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
m_postOnRez = postOnRez;
|
m_postOnRez = postOnRez;
|
||||||
m_AttachedAvatar = Part.ParentGroup.AttachedAvatar;
|
m_AttachedAvatar = Part.ParentGroup.AttachedAvatar;
|
||||||
m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID;
|
m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID;
|
||||||
|
|
||||||
|
m_SaveState = StatePersistedHere;
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[SCRIPT INSTANCE]: Instantiated script instance {0} (id {1}) in part {2} (id {3}) in object {4} attached avatar {5} in {6}",
|
||||||
|
// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, m_AttachedAvatar, Engine.World.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -339,8 +347,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_SaveState = true;
|
// For attachments, XEngine saves the state into a .state file when XEngine.SetXMLState() is called.
|
||||||
|
|
||||||
string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
|
string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
|
||||||
|
|
||||||
if (File.Exists(savedState))
|
if (File.Exists(savedState))
|
||||||
|
@ -389,6 +396,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
m_SaveState = false;
|
m_SaveState = false;
|
||||||
m_startedFromSavedState = true;
|
m_startedFromSavedState = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this script is in an attachment then we no longer need the state file.
|
||||||
|
if (!StatePersistedHere)
|
||||||
|
RemoveState();
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
// {
|
// {
|
||||||
|
@ -984,7 +995,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
(int)m_Script.GetStateEventFlags(State));
|
(int)m_Script.GetStateEventFlags(State));
|
||||||
if (running)
|
if (running)
|
||||||
Start();
|
Start();
|
||||||
m_SaveState = true;
|
|
||||||
|
m_SaveState = StatePersistedHere;
|
||||||
|
|
||||||
PostEvent(new EventParams("state_entry",
|
PostEvent(new EventParams("state_entry",
|
||||||
new Object[0], new DetectParams[0]));
|
new Object[0], new DetectParams[0]));
|
||||||
}
|
}
|
||||||
|
@ -1010,7 +1023,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
|
|
||||||
if (m_CurrentEvent != "state_entry")
|
if (m_CurrentEvent != "state_entry")
|
||||||
{
|
{
|
||||||
m_SaveState = true;
|
m_SaveState = StatePersistedHere;
|
||||||
PostEvent(new EventParams("state_entry",
|
PostEvent(new EventParams("state_entry",
|
||||||
new Object[0], new DetectParams[0]));
|
new Object[0], new DetectParams[0]));
|
||||||
throw new EventAbortException();
|
throw new EventAbortException();
|
||||||
|
@ -1027,6 +1040,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
|
|
||||||
public void SetVars(Dictionary<string, object> vars)
|
public void SetVars(Dictionary<string, object> vars)
|
||||||
{
|
{
|
||||||
|
// foreach (KeyValuePair<string, object> kvp in vars)
|
||||||
|
// m_log.DebugFormat("[SCRIPT INSTANCE]: Setting var {0}={1}", kvp.Key, kvp.Value);
|
||||||
|
|
||||||
m_Script.SetVars(vars);
|
m_Script.SetVars(vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1060,6 +1076,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[SCRIPT INSTANCE]: Saving state for script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}",
|
||||||
|
// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name);
|
||||||
|
|
||||||
PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID);
|
PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID);
|
||||||
|
|
||||||
string xml = ScriptSerializer.Serialize(this);
|
string xml = ScriptSerializer.Serialize(this);
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using Nini.Config;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.CoreModules.Avatar.Attachments;
|
||||||
|
using OpenSim.Region.CoreModules.Framework.InventoryAccess;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine;
|
||||||
|
using OpenSim.Services.Interfaces;
|
||||||
|
using OpenSim.Tests.Common;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class XEnginePersistenceTests : OpenSimTestCase
|
||||||
|
{
|
||||||
|
private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
private void OnChatFromWorld(object sender, OSChatMessage oscm)
|
||||||
|
{
|
||||||
|
// Console.WriteLine("Got chat [{0}]", oscm.Message);
|
||||||
|
|
||||||
|
// m_osChatMessageReceived = oscm;
|
||||||
|
m_chatEvent.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddCommonConfig(IConfigSource config, List<object> modules)
|
||||||
|
{
|
||||||
|
config.AddConfig("Modules");
|
||||||
|
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
|
||||||
|
|
||||||
|
AttachmentsModule attMod = new AttachmentsModule();
|
||||||
|
attMod.DebugLevel = 1;
|
||||||
|
modules.Add(attMod);
|
||||||
|
modules.Add(new BasicInventoryAccessModule());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddScriptingConfig(IConfigSource config, XEngine.XEngine xEngine, List<object> modules)
|
||||||
|
{
|
||||||
|
IConfig startupConfig = config.AddConfig("Startup");
|
||||||
|
startupConfig.Set("DefaultScriptEngine", "XEngine");
|
||||||
|
|
||||||
|
IConfig xEngineConfig = config.AddConfig("XEngine");
|
||||||
|
xEngineConfig.Set("Enabled", "true");
|
||||||
|
xEngineConfig.Set("StartDelay", "0");
|
||||||
|
|
||||||
|
// These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
|
||||||
|
// to AssemblyResolver.OnAssemblyResolve fails.
|
||||||
|
xEngineConfig.Set("AppDomainLoading", "false");
|
||||||
|
|
||||||
|
modules.Add(xEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Scene CreateScriptingEnabledTestScene(XEngine.XEngine xEngine)
|
||||||
|
{
|
||||||
|
IConfigSource config = new IniConfigSource();
|
||||||
|
List<object> modules = new List<object>();
|
||||||
|
|
||||||
|
AddCommonConfig(config, modules);
|
||||||
|
AddScriptingConfig(config, xEngine, modules);
|
||||||
|
|
||||||
|
Scene scene
|
||||||
|
= new SceneHelpers().SetupScene(
|
||||||
|
"attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
|
||||||
|
SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
|
||||||
|
|
||||||
|
scene.StartScripts();
|
||||||
|
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestScriptedAttachmentPersistence()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
XEngine.XEngine xEngine = new XEngine.XEngine();
|
||||||
|
Scene scene = CreateScriptingEnabledTestScene(xEngine);
|
||||||
|
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||||
|
ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
|
||||||
|
|
||||||
|
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
|
||||||
|
TaskInventoryHelpers.AddScript(
|
||||||
|
scene,
|
||||||
|
so.RootPart,
|
||||||
|
"scriptItem",
|
||||||
|
"default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }");
|
||||||
|
|
||||||
|
InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
|
||||||
|
|
||||||
|
// FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
|
||||||
|
// In the future, we need to be able to do this programatically more predicably.
|
||||||
|
scene.EventManager.OnChatFromWorld += OnChatFromWorld;
|
||||||
|
|
||||||
|
SceneObjectGroup rezzedSo
|
||||||
|
= scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
|
||||||
|
TaskInventoryItem rezzedScriptItem = rezzedSo.RootPart.Inventory.GetInventoryItem("scriptItem");
|
||||||
|
|
||||||
|
// Wait for chat to signal rezzed script has been started.
|
||||||
|
m_chatEvent.WaitOne(60000);
|
||||||
|
|
||||||
|
// Force save
|
||||||
|
xEngine.DoBackup(new Object[] { 0 });
|
||||||
|
|
||||||
|
// Console.WriteLine("ItemID {0}", rezzedScriptItem.ItemID);
|
||||||
|
//
|
||||||
|
// foreach (
|
||||||
|
// string s in Directory.EnumerateFileSystemEntries(
|
||||||
|
// string.Format("ScriptEngines/{0}", scene.RegionInfo.RegionID)))
|
||||||
|
// Console.WriteLine(s);
|
||||||
|
|
||||||
|
Assert.IsFalse(
|
||||||
|
File.Exists(
|
||||||
|
string.Format("ScriptEngines/{0}/{1}.state", scene.RegionInfo.RegionID, rezzedScriptItem.ItemID)));
|
||||||
|
|
||||||
|
scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -247,7 +247,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
m_ScriptConfig = configSource.Configs["XEngine"];
|
m_ScriptConfig = configSource.Configs["XEngine"];
|
||||||
m_ConfigSource = configSource;
|
m_ConfigSource = configSource;
|
||||||
|
|
||||||
string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "coop");
|
string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "co-op");
|
||||||
|
|
||||||
m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy);
|
m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy);
|
||||||
|
|
||||||
|
@ -718,6 +718,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
//
|
//
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (instance.StatePersistedHere)
|
||||||
instance.SaveState();
|
instance.SaveState();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -830,8 +831,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
lock (m_Scripts)
|
lock (m_Scripts)
|
||||||
{
|
{
|
||||||
foreach (IScriptInstance instance in m_Scripts.Values)
|
foreach (IScriptInstance instance in m_Scripts.Values)
|
||||||
|
{
|
||||||
|
if (instance.StatePersistedHere)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[XEngine]: Adding script {0}.{1}, item UUID {2}, prim UUID {3} in {4} for state persistence",
|
||||||
|
// instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name);
|
||||||
|
|
||||||
instances.Add(instance);
|
instances.Add(instance);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (IScriptInstance i in instances)
|
foreach (IScriptInstance i in instances)
|
||||||
{
|
{
|
||||||
|
@ -860,6 +870,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
|
||||||
public void SaveAllState()
|
public void SaveAllState()
|
||||||
{
|
{
|
||||||
|
DoBackup(new object[] { 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
public object DoMaintenance(object p)
|
||||||
|
{
|
||||||
|
object[] parms = (object[])p;
|
||||||
|
int sleepTime = (int)parms[0];
|
||||||
|
|
||||||
foreach (IScriptInstance inst in m_Scripts.Values)
|
foreach (IScriptInstance inst in m_Scripts.Values)
|
||||||
{
|
{
|
||||||
if (inst.EventTime() > m_EventLimit)
|
if (inst.EventTime() > m_EventLimit)
|
||||||
|
@ -869,14 +887,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
inst.Start();
|
inst.Start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public object DoMaintenance(object p)
|
|
||||||
{
|
|
||||||
object[] parms = (object[])p;
|
|
||||||
int sleepTime = (int)parms[0];
|
|
||||||
|
|
||||||
SaveAllState();
|
|
||||||
|
|
||||||
System.Threading.Thread.Sleep(sleepTime);
|
System.Threading.Thread.Sleep(sleepTime);
|
||||||
|
|
||||||
|
@ -1043,6 +1053,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
int scriptsStarted = 0;
|
int scriptsStarted = 0;
|
||||||
|
|
||||||
while (m_CompileQueue.Dequeue(out o))
|
while (m_CompileQueue.Dequeue(out o))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (DoOnRezScript(o))
|
if (DoOnRezScript(o))
|
||||||
{
|
{
|
||||||
|
@ -1054,6 +1066,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
"[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name);
|
"[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Error(
|
||||||
|
string.Format(
|
||||||
|
"[XEngine]: Failure in DoOnRezScriptQueue() for item {0} in {1}. Continuing. Exception ",
|
||||||
|
o[1], m_Scene.Name),
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_InitialStartup)
|
if (m_InitialStartup)
|
||||||
m_log.InfoFormat(
|
m_log.InfoFormat(
|
||||||
|
@ -1437,8 +1458,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
|
||||||
instance.Stop(m_WaitForEventCompletionOnScriptStop);
|
instance.Stop(m_WaitForEventCompletionOnScriptStop);
|
||||||
|
|
||||||
// bool objectRemoved = false;
|
|
||||||
|
|
||||||
lock (m_PrimObjects)
|
lock (m_PrimObjects)
|
||||||
{
|
{
|
||||||
// Remove the script from it's prim
|
// Remove the script from it's prim
|
||||||
|
@ -1450,14 +1469,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
|
||||||
// If there are no more scripts, remove prim
|
// If there are no more scripts, remove prim
|
||||||
if (m_PrimObjects[localID].Count == 0)
|
if (m_PrimObjects[localID].Count == 0)
|
||||||
{
|
|
||||||
m_PrimObjects.Remove(localID);
|
m_PrimObjects.Remove(localID);
|
||||||
// objectRemoved = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instance.StatePersistedHere)
|
||||||
instance.RemoveState();
|
instance.RemoveState();
|
||||||
|
|
||||||
instance.DestroyScriptInstance();
|
instance.DestroyScriptInstance();
|
||||||
|
|
||||||
m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
|
m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
|
||||||
|
|
|
@ -84,16 +84,16 @@ namespace OpenSim.Services.Connectors
|
||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(m_ServerURI))
|
if (String.IsNullOrEmpty(m_ServerURI))
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[HELO SERVICE]: Unable to invoke HELO due to malformed URL");
|
m_log.WarnFormat("[HELO SERVICE]: Unable to invoke HELO due to empty URL");
|
||||||
return String.Empty;
|
return String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI);
|
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI);
|
||||||
// Eventually we need to switch to HEAD
|
// Eventually we need to switch to HEAD
|
||||||
/* req.Method = "HEAD"; */
|
/* req.Method = "HEAD"; */
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (WebResponse response = req.GetResponse())
|
using (WebResponse response = req.GetResponse())
|
||||||
{
|
{
|
||||||
if (response.Headers.Get("X-Handlers-Provided") == null) // just in case this ever returns a null
|
if (response.Headers.Get("X-Handlers-Provided") == null) // just in case this ever returns a null
|
||||||
|
|
|
@ -164,7 +164,13 @@ namespace OpenSim.Services.GridService
|
||||||
|
|
||||||
configVal = loginConfig.GetString("MapTileURL", string.Empty);
|
configVal = loginConfig.GetString("MapTileURL", string.Empty);
|
||||||
if (!string.IsNullOrEmpty(configVal))
|
if (!string.IsNullOrEmpty(configVal))
|
||||||
|
{
|
||||||
|
// This URL must end with '/', the viewer doesn't check
|
||||||
|
configVal = configVal.Trim();
|
||||||
|
if (!configVal.EndsWith("/"))
|
||||||
|
configVal = configVal + "/";
|
||||||
m_ExtraFeatures["map-server-url"] = configVal;
|
m_ExtraFeatures["map-server-url"] = configVal;
|
||||||
|
}
|
||||||
|
|
||||||
configVal = loginConfig.GetString("DestinationGuide", string.Empty);
|
configVal = loginConfig.GetString("DestinationGuide", string.Empty);
|
||||||
if (!string.IsNullOrEmpty(configVal))
|
if (!string.IsNullOrEmpty(configVal))
|
||||||
|
|
|
@ -196,6 +196,9 @@ namespace OpenSim.Services.ProfilesService
|
||||||
|
|
||||||
public bool UserPreferencesRequest(ref UserPreferences pref, ref string result)
|
public bool UserPreferencesRequest(ref UserPreferences pref, ref string result)
|
||||||
{
|
{
|
||||||
|
if (!ProfilesData.GetUserPreferences(ref pref, ref result))
|
||||||
|
return false;
|
||||||
|
|
||||||
if(string.IsNullOrEmpty(pref.EMail))
|
if(string.IsNullOrEmpty(pref.EMail))
|
||||||
{
|
{
|
||||||
UserAccount account = new UserAccount();
|
UserAccount account = new UserAccount();
|
||||||
|
@ -228,9 +231,6 @@ namespace OpenSim.Services.ProfilesService
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ProfilesData.GetUserPreferences (ref pref, ref result))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
if(string.IsNullOrEmpty(pref.EMail))
|
if(string.IsNullOrEmpty(pref.EMail))
|
||||||
pref.EMail = "No Email Address On Record";
|
pref.EMail = "No Email Address On Record";
|
||||||
|
|
|
@ -116,26 +116,44 @@ namespace OpenSim.Tests.Common
|
||||||
/// <returns>The item that was added</returns>
|
/// <returns>The item that was added</returns>
|
||||||
public static TaskInventoryItem AddScript(
|
public static TaskInventoryItem AddScript(
|
||||||
Scene scene, SceneObjectPart part, string scriptName, string scriptSource)
|
Scene scene, SceneObjectPart part, string scriptName, string scriptSource)
|
||||||
|
{
|
||||||
|
return AddScript(scene, part, UUID.Random(), UUID.Random(), scriptName, scriptSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a simple script to the given part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// TODO: Accept input for item and asset IDs so that we have completely replicatable regression tests rather
|
||||||
|
/// than a random component.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="scene"></param>
|
||||||
|
/// <param name="part"></param>
|
||||||
|
/// <param name="itemId">Item UUID for the script</param>
|
||||||
|
/// <param name="assetId">Asset UUID for the script</param>
|
||||||
|
/// <param name="scriptName">Name of the script to add</param>
|
||||||
|
/// <param name="scriptSource">LSL script source</param>
|
||||||
|
/// <returns>The item that was added</returns>
|
||||||
|
public static TaskInventoryItem AddScript(
|
||||||
|
Scene scene, SceneObjectPart part, UUID itemId, UUID assetId, string scriptName, string scriptSource)
|
||||||
{
|
{
|
||||||
AssetScriptText ast = new AssetScriptText();
|
AssetScriptText ast = new AssetScriptText();
|
||||||
ast.Source = scriptSource;
|
ast.Source = scriptSource;
|
||||||
ast.Encode();
|
ast.Encode();
|
||||||
|
|
||||||
UUID assetUuid = UUID.Random();
|
|
||||||
UUID itemUuid = UUID.Random();
|
|
||||||
|
|
||||||
AssetBase asset
|
AssetBase asset
|
||||||
= AssetHelpers.CreateAsset(assetUuid, AssetType.LSLText, ast.AssetData, UUID.Zero);
|
= AssetHelpers.CreateAsset(assetId, AssetType.LSLText, ast.AssetData, UUID.Zero);
|
||||||
scene.AssetService.Store(asset);
|
scene.AssetService.Store(asset);
|
||||||
TaskInventoryItem item
|
TaskInventoryItem item
|
||||||
= new TaskInventoryItem
|
= new TaskInventoryItem
|
||||||
{ Name = scriptName, AssetID = assetUuid, ItemID = itemUuid,
|
{ Name = scriptName, AssetID = assetId, ItemID = itemId,
|
||||||
Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL };
|
Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL };
|
||||||
part.Inventory.AddInventoryItem(item, true);
|
part.Inventory.AddInventoryItem(item, true);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a scene object item to the given part.
|
/// Add a scene object item to the given part.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace pCampBot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PhysicsBehaviour2 : AbstractBehaviour
|
public class PhysicsBehaviour2 : AbstractBehaviour
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public PhysicsBehaviour2()
|
public PhysicsBehaviour2()
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace pCampBot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TwitchyBehaviour : AbstractBehaviour
|
public class TwitchyBehaviour : AbstractBehaviour
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public TwitchyBehaviour()
|
public TwitchyBehaviour()
|
||||||
{
|
{
|
||||||
|
|
|
@ -187,12 +187,13 @@
|
||||||
;; YOU HAVE BEEN WARNED!!!
|
;; YOU HAVE BEEN WARNED!!!
|
||||||
; TrustBinaries = false
|
; TrustBinaries = false
|
||||||
|
|
||||||
;# {CombineContiguousRegions} {} {Create megaregions where possible? (Do not use with existing content!)} {true false} false
|
;# {CombineContiguousRegions} {} {Create megaregions where possible? (Do not use with existing content or varregions!)} {true false} false
|
||||||
;; Combine all contiguous regions into one large megaregion
|
;; Combine all contiguous regions into one large megaregion
|
||||||
;; Order your regions from South to North, West to East in your regions.ini
|
;; Order your regions from South to North, West to East in your regions.ini
|
||||||
;; and then set this to true
|
;; and then set this to true
|
||||||
;; Warning! Don't use this with regions that have existing content!,
|
;; Warning! Don't use this with regions that have existing content!,
|
||||||
;; This will likely break them
|
;; This will likely break them
|
||||||
|
;; Also, this setting should be set to false for varregions as they are proper larger single regions rather than combined smaller regions.
|
||||||
; CombineContiguousRegions = false
|
; CombineContiguousRegions = false
|
||||||
|
|
||||||
;# {InworldRestartShutsDown} {} {Shutdown instance on region restart?} {true false} false
|
;# {InworldRestartShutsDown} {} {Shutdown instance on region restart?} {true false} false
|
||||||
|
|
|
@ -453,6 +453,7 @@
|
||||||
|
|
||||||
[MapImageService]
|
[MapImageService]
|
||||||
LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService"
|
LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService"
|
||||||
|
|
||||||
; Set this if you want to change the default
|
; Set this if you want to change the default
|
||||||
; TilesStoragePath = "maptiles"
|
; TilesStoragePath = "maptiles"
|
||||||
;
|
;
|
||||||
|
|
|
@ -166,7 +166,6 @@
|
||||||
;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 to show a default "Ruth" avatar rather than a cloud.
|
;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 to show a default "Ruth" avatar rather than a cloud.
|
||||||
CreateDefaultAvatarEntries = true
|
CreateDefaultAvatarEntries = true
|
||||||
|
|
||||||
|
|
||||||
;; The interface that local users get when they are in other grids
|
;; The interface that local users get when they are in other grids
|
||||||
;; This greatly restricts the inventory operations while in other grids
|
;; This greatly restricts the inventory operations while in other grids
|
||||||
[HGInventoryService]
|
[HGInventoryService]
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue