Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
2cdcf62b48
|
@ -287,6 +287,12 @@ namespace OpenSim.Framework
|
||||||
public Vector3 AtAxis;
|
public Vector3 AtAxis;
|
||||||
public Vector3 LeftAxis;
|
public Vector3 LeftAxis;
|
||||||
public Vector3 UpAxis;
|
public Vector3 UpAxis;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signal on a V2 teleport that Scene.IncomingChildAgentDataUpdate(AgentData ad) should wait for the
|
||||||
|
/// scene presence to become root (triggered when the viewer sends a CompleteAgentMovement UDP packet after
|
||||||
|
/// establishing the connection triggered by it's receipt of a TeleportFinish EQ message).
|
||||||
|
/// </summary>
|
||||||
public bool SenderWantsToWaitForRoot;
|
public bool SenderWantsToWaitForRoot;
|
||||||
|
|
||||||
public float Far;
|
public float Far;
|
||||||
|
|
|
@ -26,10 +26,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
using OpenMetaverse.StructuredData;
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
|
@ -262,6 +264,41 @@ namespace OpenSim.Framework.Monitoring
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Hashtable HandleStatsRequest(Hashtable request)
|
||||||
|
{
|
||||||
|
Hashtable responsedata = new Hashtable();
|
||||||
|
string regpath = request["uri"].ToString();
|
||||||
|
int response_code = 200;
|
||||||
|
string contenttype = "text/json";
|
||||||
|
|
||||||
|
string pCategoryName = StatsManager.AllSubCommand;
|
||||||
|
string pContainerName = StatsManager.AllSubCommand;
|
||||||
|
string pStatName = StatsManager.AllSubCommand;
|
||||||
|
|
||||||
|
if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString();
|
||||||
|
if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString();
|
||||||
|
if (request.ContainsKey("stat")) pStatName = request["cat"].ToString();
|
||||||
|
|
||||||
|
string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString();
|
||||||
|
|
||||||
|
// If requestor wants it as a callback function, build response as a function rather than just the JSON string.
|
||||||
|
if (request.ContainsKey("callback"))
|
||||||
|
{
|
||||||
|
strOut = request["callback"].ToString() + "(" + strOut + ");";
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_log.DebugFormat("{0} StatFetch: uri={1}, cat={2}, cont={3}, stat={4}, resp={5}",
|
||||||
|
// LogHeader, regpath, pCategoryName, pContainerName, pStatName, strOut);
|
||||||
|
|
||||||
|
responsedata["int_response_code"] = response_code;
|
||||||
|
responsedata["content_type"] = contenttype;
|
||||||
|
responsedata["keepalive"] = false;
|
||||||
|
responsedata["str_response_string"] = strOut;
|
||||||
|
responsedata["access_control_allow_origin"] = "*";
|
||||||
|
|
||||||
|
return responsedata;
|
||||||
|
}
|
||||||
|
|
||||||
// /// <summary>
|
// /// <summary>
|
||||||
// /// Start collecting statistics related to assets.
|
// /// Start collecting statistics related to assets.
|
||||||
// /// Should only be called once.
|
// /// Should only be called once.
|
||||||
|
|
|
@ -55,11 +55,18 @@ namespace OpenSim.Framework.Tests
|
||||||
Location TestLocation2 = new Location(1095216660736000);
|
Location TestLocation2 = new Location(1095216660736000);
|
||||||
Assert.That(TestLocation1 == TestLocation2);
|
Assert.That(TestLocation1 == TestLocation2);
|
||||||
|
|
||||||
|
Assert.That(TestLocation1.X == 255000 && TestLocation1.Y == 256000, "Test xy location doesn't match position in the constructor");
|
||||||
Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided");
|
Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided");
|
||||||
|
|
||||||
Assert.That(TestLocation2.RegionHandle == 1095216660736000,
|
Assert.That(TestLocation2.RegionHandle == 1095216660736000,
|
||||||
"Location RegionHandle Property didn't match regionhandle provided in constructor");
|
"Location RegionHandle Property didn't match regionhandle provided in constructor");
|
||||||
|
|
||||||
|
ulong RegionHandle = TestLocation1.RegionHandle;
|
||||||
|
Assert.That(RegionHandle.Equals(1095216660736000), "Equals(regionhandle) failed to match the position in the constructor");
|
||||||
|
|
||||||
|
TestLocation2 = new Location(RegionHandle);
|
||||||
|
Assert.That(TestLocation2.Equals(255000, 256000), "Decoded regionhandle failed to match the original position in the constructor");
|
||||||
|
|
||||||
|
|
||||||
TestLocation1 = new Location(255001, 256001);
|
TestLocation1 = new Location(255001, 256001);
|
||||||
TestLocation2 = new Location(1095216660736000);
|
TestLocation2 = new Location(1095216660736000);
|
||||||
|
|
|
@ -282,5 +282,87 @@ namespace OpenSim.Framework.Tests
|
||||||
String.Format("Incorrect InventoryType mapped from Content-Type {0}", invcontenttypes[i]));
|
String.Format("Incorrect InventoryType mapped from Content-Type {0}", invcontenttypes[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FakeParcelIDTests()
|
||||||
|
{
|
||||||
|
byte[] hexBytes8 = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
|
||||||
|
byte[] hexBytes16 = {
|
||||||
|
0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
|
||||||
|
0x77, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f };
|
||||||
|
UInt64 var64Bit = (UInt64)0xfedcba9876543210;
|
||||||
|
|
||||||
|
//Region handle is for location 255000,256000.
|
||||||
|
ulong regionHandle1 = 1095216660736000;
|
||||||
|
uint x1 = 100;
|
||||||
|
uint y1 = 200;
|
||||||
|
uint z1 = 22;
|
||||||
|
ulong regionHandle2;
|
||||||
|
uint x2, y2, z2;
|
||||||
|
UUID fakeParcelID1, fakeParcelID2, uuid;
|
||||||
|
|
||||||
|
ulong bigInt64 = Util.BytesToUInt64Big(hexBytes8);
|
||||||
|
Assert.AreEqual(var64Bit, bigInt64,
|
||||||
|
"BytesToUint64Bit conversion of 8 bytes to UInt64 failed.");
|
||||||
|
|
||||||
|
//Test building and decoding using some typical input values
|
||||||
|
fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1);
|
||||||
|
Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2);
|
||||||
|
Assert.AreEqual(regionHandle1, regionHandle2,
|
||||||
|
"region handle decoded from FakeParcelID wth X/Y failed.");
|
||||||
|
Assert.AreEqual(x1, x2,
|
||||||
|
"X coordinate decoded from FakeParcelID wth X/Y failed.");
|
||||||
|
Assert.AreEqual(y1, y2,
|
||||||
|
"Y coordinate decoded from FakeParcelID wth X/Y failed.");
|
||||||
|
|
||||||
|
fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1, z1);
|
||||||
|
Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2, out z2);
|
||||||
|
Assert.AreEqual(regionHandle1, regionHandle2,
|
||||||
|
"region handle decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
Assert.AreEqual(x1, x2,
|
||||||
|
"X coordinate decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
Assert.AreEqual(y1, y2,
|
||||||
|
"Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
Assert.AreEqual(z1, z2,
|
||||||
|
"Z coordinate decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
|
||||||
|
//Do some more extreme tests to check the encoding and decoding
|
||||||
|
x1 = 0x55aa;
|
||||||
|
y1 = 0x9966;
|
||||||
|
z1 = 0x5a96;
|
||||||
|
|
||||||
|
fakeParcelID1 = Util.BuildFakeParcelID(var64Bit, x1, y1);
|
||||||
|
Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2);
|
||||||
|
Assert.AreEqual(var64Bit, regionHandle2,
|
||||||
|
"region handle decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
Assert.AreEqual(x1, x2,
|
||||||
|
"X coordinate decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
Assert.AreEqual(y1, y2,
|
||||||
|
"Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
|
||||||
|
fakeParcelID1 = Util.BuildFakeParcelID(var64Bit, x1, y1, z1);
|
||||||
|
Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2, out z2);
|
||||||
|
Assert.AreEqual(var64Bit, regionHandle2,
|
||||||
|
"region handle decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
Assert.AreEqual(x1, x2,
|
||||||
|
"X coordinate decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
Assert.AreEqual(y1, y2,
|
||||||
|
"Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
Assert.AreEqual(z1, z2,
|
||||||
|
"Z coordinate decoded from FakeParcelID with X/Y/Z failed.");
|
||||||
|
|
||||||
|
|
||||||
|
x1 = 64;
|
||||||
|
y1 = 192;
|
||||||
|
fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1);
|
||||||
|
Util.FakeParcelIDToGlobalPosition(fakeParcelID1, out x2, out y2);
|
||||||
|
Assert.AreEqual(255000+x1, x2,
|
||||||
|
"Global X coordinate decoded from regionHandle failed.");
|
||||||
|
Assert.AreEqual(256000+y1, y2,
|
||||||
|
"Global Y coordinate decoded from regionHandle failed.");
|
||||||
|
|
||||||
|
uuid = new UUID("00dd0700-00d1-0700-3800-000032000000");
|
||||||
|
Util.FakeParcelIDToGlobalPosition(uuid, out x2, out y2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1247,7 +1247,7 @@ namespace OpenSim.Framework
|
||||||
byte[] bytes =
|
byte[] bytes =
|
||||||
{
|
{
|
||||||
(byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
|
(byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
|
||||||
(byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56),
|
(byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
|
||||||
(byte)x, (byte)(x >> 8), 0, 0,
|
(byte)x, (byte)(x >> 8), 0, 0,
|
||||||
(byte)y, (byte)(y >> 8), 0, 0 };
|
(byte)y, (byte)(y >> 8), 0, 0 };
|
||||||
return new UUID(bytes, 0);
|
return new UUID(bytes, 0);
|
||||||
|
@ -1258,7 +1258,7 @@ namespace OpenSim.Framework
|
||||||
byte[] bytes =
|
byte[] bytes =
|
||||||
{
|
{
|
||||||
(byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
|
(byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
|
||||||
(byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56),
|
(byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
|
||||||
(byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
|
(byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
|
||||||
(byte)y, (byte)(y >> 8), 0, 0 };
|
(byte)y, (byte)(y >> 8), 0, 0 };
|
||||||
return new UUID(bytes, 0);
|
return new UUID(bytes, 0);
|
||||||
|
|
|
@ -172,6 +172,13 @@ namespace OpenSim
|
||||||
if (userStatsURI != String.Empty)
|
if (userStatsURI != String.Empty)
|
||||||
MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this));
|
MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this));
|
||||||
|
|
||||||
|
if (managedStatsURI != String.Empty)
|
||||||
|
{
|
||||||
|
string urlBase = String.Format("/{0}/", managedStatsURI);
|
||||||
|
MainServer.Instance.AddHTTPHandler(urlBase, StatsManager.HandleStatsRequest);
|
||||||
|
m_log.InfoFormat("[OPENSIM] Enabling remote managed stats fetch. URL = {0}", urlBase);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_console is RemoteConsole)
|
if (m_console is RemoteConsole)
|
||||||
{
|
{
|
||||||
if (m_consolePort == 0)
|
if (m_consolePort == 0)
|
||||||
|
@ -348,18 +355,6 @@ namespace OpenSim
|
||||||
m_console.Commands.AddCommand("Regions", false, "delete-region",
|
m_console.Commands.AddCommand("Regions", false, "delete-region",
|
||||||
"delete-region <name>",
|
"delete-region <name>",
|
||||||
"Delete a region from disk", RunCommand);
|
"Delete a region from disk", RunCommand);
|
||||||
|
|
||||||
m_console.Commands.AddCommand("General", false, "modules list",
|
|
||||||
"modules list",
|
|
||||||
"List modules", HandleModules);
|
|
||||||
|
|
||||||
m_console.Commands.AddCommand("General", false, "modules load",
|
|
||||||
"modules load <name>",
|
|
||||||
"Load a module", HandleModules);
|
|
||||||
|
|
||||||
m_console.Commands.AddCommand("General", false, "modules unload",
|
|
||||||
"modules unload <name>",
|
|
||||||
"Unload a module", HandleModules);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ShutdownSpecific()
|
protected override void ShutdownSpecific()
|
||||||
|
@ -556,34 +551,6 @@ namespace OpenSim
|
||||||
regInfo.EstateSettings.Save();
|
regInfo.EstateSettings.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Load, Unload, and list Region modules in use
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="module"></param>
|
|
||||||
/// <param name="cmd"></param>
|
|
||||||
private void HandleModules(string module, string[] cmd)
|
|
||||||
{
|
|
||||||
List<string> args = new List<string>(cmd);
|
|
||||||
args.RemoveAt(0);
|
|
||||||
string[] cmdparams = args.ToArray();
|
|
||||||
|
|
||||||
if (cmdparams.Length > 0)
|
|
||||||
{
|
|
||||||
switch (cmdparams[0].ToLower())
|
|
||||||
{
|
|
||||||
case "list":
|
|
||||||
//TODO: Convert to new region modules
|
|
||||||
break;
|
|
||||||
case "unload":
|
|
||||||
//TODO: Convert to new region modules
|
|
||||||
break;
|
|
||||||
case "load":
|
|
||||||
//TODO: Convert to new region modules
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs commands issued by the server console from the operator
|
/// Runs commands issued by the server console from the operator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -75,6 +75,7 @@ namespace OpenSim
|
||||||
protected int proxyOffset = 0;
|
protected int proxyOffset = 0;
|
||||||
|
|
||||||
public string userStatsURI = String.Empty;
|
public string userStatsURI = String.Empty;
|
||||||
|
public string managedStatsURI = String.Empty;
|
||||||
|
|
||||||
protected bool m_autoCreateClientStack = true;
|
protected bool m_autoCreateClientStack = true;
|
||||||
|
|
||||||
|
@ -188,6 +189,7 @@ namespace OpenSim
|
||||||
CreatePIDFile(pidFile);
|
CreatePIDFile(pidFile);
|
||||||
|
|
||||||
userStatsURI = startupConfig.GetString("Stats_URI", String.Empty);
|
userStatsURI = startupConfig.GetString("Stats_URI", String.Empty);
|
||||||
|
managedStatsURI = startupConfig.GetString("ManagedStatsRemoteFetchURI", String.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the simulation data service
|
// Load the simulation data service
|
||||||
|
|
|
@ -327,7 +327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private PriorityQueue m_entityProps;
|
private PriorityQueue m_entityProps;
|
||||||
private Prioritizer m_prioritizer;
|
private Prioritizer m_prioritizer;
|
||||||
private bool m_disableFacelights = false;
|
private bool m_disableFacelights = false;
|
||||||
|
private volatile bool m_justEditedTerrain = false;
|
||||||
/// <value>
|
/// <value>
|
||||||
/// List used in construction of data blocks for an object update packet. This is to stop us having to
|
/// List used in construction of data blocks for an object update packet. This is to stop us having to
|
||||||
/// continually recreate it.
|
/// continually recreate it.
|
||||||
|
@ -1239,9 +1239,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
LLHeightFieldMoronize(map);
|
LLHeightFieldMoronize(map);
|
||||||
|
|
||||||
LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
|
LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
|
||||||
layerpack.Header.Reliable = true;
|
|
||||||
|
|
||||||
OutPacket(layerpack, ThrottleOutPacketType.Land);
|
// When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
|
||||||
|
// To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
|
||||||
|
// We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area
|
||||||
|
// invalidating previous packets for that area.
|
||||||
|
|
||||||
|
// It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a
|
||||||
|
// tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower.
|
||||||
|
|
||||||
|
// One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will
|
||||||
|
// have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain
|
||||||
|
// patches.
|
||||||
|
|
||||||
|
// m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
|
||||||
|
if (m_justEditedTerrain)
|
||||||
|
{
|
||||||
|
layerpack.Header.Reliable = false;
|
||||||
|
OutPacket(layerpack,
|
||||||
|
ThrottleOutPacketType.Unknown );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
layerpack.Header.Reliable = true;
|
||||||
|
OutPacket(layerpack,
|
||||||
|
ThrottleOutPacketType.Land);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -6263,6 +6286,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
//m_log.Info("[LAND]: LAND:" + modify.ToString());
|
//m_log.Info("[LAND]: LAND:" + modify.ToString());
|
||||||
if (modify.ParcelData.Length > 0)
|
if (modify.ParcelData.Length > 0)
|
||||||
{
|
{
|
||||||
|
// Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
|
||||||
|
// a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
|
||||||
|
m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
|
||||||
if (OnModifyTerrain != null)
|
if (OnModifyTerrain != null)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < modify.ParcelData.Length; i++)
|
for (int i = 0; i < modify.ParcelData.Length; i++)
|
||||||
|
@ -6278,6 +6304,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -689,7 +689,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
|
TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
|
||||||
else
|
else
|
||||||
TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
|
TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
|
private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
|
||||||
|
@ -698,7 +697,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
ulong destinationHandle = finalDestination.RegionHandle;
|
ulong destinationHandle = finalDestination.RegionHandle;
|
||||||
AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
|
AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
|
||||||
|
|
||||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Using TP V1");
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
|
||||||
|
sp.Name, Scene.Name, finalDestination.RegionName);
|
||||||
|
|
||||||
// Let's create an agent there if one doesn't exist yet.
|
// Let's create an agent there if one doesn't exist yet.
|
||||||
// NOTE: logout will always be false for a non-HG teleport.
|
// NOTE: logout will always be false for a non-HG teleport.
|
||||||
bool logout = false;
|
bool logout = false;
|
||||||
|
@ -956,6 +958,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
|
||||||
|
{
|
||||||
|
m_interRegionTeleportCancels.Value++;
|
||||||
|
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
|
||||||
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
|
{
|
||||||
|
m_interRegionTeleportAborts.Value++;
|
||||||
|
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
|
||||||
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
|
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
|
||||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
||||||
|
|
||||||
|
@ -1058,21 +1081,23 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
if (!sp.DoNotCloseAfterTeleport)
|
if (!sp.DoNotCloseAfterTeleport)
|
||||||
{
|
{
|
||||||
// OK, it got this agent. Let's close everything
|
// OK, it got this agent. Let's close everything
|
||||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Closing in agent {0} in region {1}", sp.Name, Scene.RegionInfo.RegionName);
|
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Closing in agent {0} in region {1}", sp.Name, Scene.Name);
|
||||||
sp.CloseChildAgents(newRegionX, newRegionY);
|
sp.CloseChildAgents(newRegionX, newRegionY);
|
||||||
sp.Scene.IncomingCloseAgent(sp.UUID, false);
|
sp.Scene.IncomingCloseAgent(sp.UUID, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Not closing agent {0}, user is back in {0}", sp.Name, Scene.RegionInfo.RegionName);
|
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Not closing agent {0}, user is back in {0}", sp.Name, Scene.Name);
|
||||||
sp.DoNotCloseAfterTeleport = false;
|
sp.DoNotCloseAfterTeleport = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
// now we have a child agent in this region.
|
// now we have a child agent in this region.
|
||||||
sp.Reset();
|
sp.Reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation.
|
/// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation.
|
||||||
|
|
|
@ -45,6 +45,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log =
|
private static readonly ILog m_log =
|
||||||
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private static string LogHeader = "[MODULE COMMS]";
|
||||||
|
|
||||||
private Dictionary<string,object> m_constants = new Dictionary<string,object>();
|
private Dictionary<string,object> m_constants = new Dictionary<string,object>();
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
|
||||||
MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
|
MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
|
||||||
if (mi == null)
|
if (mi == null)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
|
m_log.WarnFormat("{0} Failed to register method {1}", LogHeader, meth);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
|
// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
|
||||||
|
|
||||||
Type delegateType;
|
Type delegateType = typeof(void);
|
||||||
List<Type> typeArgs = mi.GetParameters()
|
List<Type> typeArgs = mi.GetParameters()
|
||||||
.Select(p => p.ParameterType)
|
.Select(p => p.ParameterType)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -175,10 +176,18 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
|
||||||
delegateType = Expression.GetActionType(typeArgs.ToArray());
|
delegateType = Expression.GetActionType(typeArgs.ToArray());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
typeArgs.Add(mi.ReturnType);
|
typeArgs.Add(mi.ReturnType);
|
||||||
delegateType = Expression.GetFuncType(typeArgs.ToArray());
|
delegateType = Expression.GetFuncType(typeArgs.ToArray());
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("{0} Failed to create function signature. Most likely more than 5 parameters. Method={1}. Error={2}",
|
||||||
|
LogHeader, mi.Name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Delegate fcall;
|
Delegate fcall;
|
||||||
if (!(target is Type))
|
if (!(target is Type))
|
||||||
|
|
|
@ -76,6 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
|
||||||
" that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
|
" that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
|
||||||
consoleSetTerrainHeights);
|
consoleSetTerrainHeights);
|
||||||
|
|
||||||
|
m_module.Scene.AddCommand("Regions", m_module, "set water height",
|
||||||
|
"set water height <height> [<x>] [<y>]",
|
||||||
|
"Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " +
|
||||||
|
"Specify -1 in <x> or <y> to wildcard that coordinate.",
|
||||||
|
consoleSetWaterHeight);
|
||||||
|
|
||||||
|
|
||||||
m_module.Scene.AddCommand(
|
m_module.Scene.AddCommand(
|
||||||
"Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand);
|
"Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +128,29 @@ namespace OpenSim.Region.CoreModules.World.Estate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protected void consoleSetWaterHeight(string module, string[] args)
|
||||||
|
{
|
||||||
|
string heightstring = args[3];
|
||||||
|
|
||||||
|
int x = (args.Length > 4 ? int.Parse(args[4]) : -1);
|
||||||
|
int y = (args.Length > 5 ? int.Parse(args[5]) : -1);
|
||||||
|
|
||||||
|
if (x == -1 || m_module.Scene.RegionInfo.RegionLocX == x)
|
||||||
|
{
|
||||||
|
if (y == -1 || m_module.Scene.RegionInfo.RegionLocY == y)
|
||||||
|
{
|
||||||
|
double selectedheight = double.Parse(heightstring);
|
||||||
|
|
||||||
|
m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " +
|
||||||
|
string.Format(" {0}", selectedheight));
|
||||||
|
m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight;
|
||||||
|
|
||||||
|
m_module.Scene.RegionInfo.RegionSettings.Save();
|
||||||
|
m_module.TriggerRegionInfoChange();
|
||||||
|
m_module.sendRegionHandshakeToAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
protected void consoleSetTerrainHeights(string module, string[] args)
|
protected void consoleSetTerrainHeights(string module, string[] args)
|
||||||
{
|
{
|
||||||
string num = args[3];
|
string num = args[3];
|
||||||
|
|
|
@ -4222,36 +4222,42 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to wait until the viewer contacts this region
|
// We have to wait until the viewer contacts this region
|
||||||
// after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
|
// after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
|
||||||
|
// or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
|
||||||
// a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
|
// a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
|
||||||
ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
|
ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
|
||||||
|
|
||||||
if (childAgentUpdate != null)
|
if (sp != null)
|
||||||
{
|
{
|
||||||
if (cAgentData.SessionID != childAgentUpdate.ControllingClient.SessionId)
|
if (cAgentData.SessionID != sp.ControllingClient.SessionId)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", childAgentUpdate.UUID, cAgentData.SessionID);
|
m_log.WarnFormat(
|
||||||
|
"[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
|
||||||
|
sp.UUID, cAgentData.SessionID);
|
||||||
|
|
||||||
Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
|
Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
|
||||||
childAgentUpdate.UUID, childAgentUpdate.ControllingClient.SessionId, cAgentData.SessionID));
|
sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
|
||||||
}
|
}
|
||||||
|
|
||||||
childAgentUpdate.ChildAgentDataUpdate(cAgentData);
|
sp.ChildAgentDataUpdate(cAgentData);
|
||||||
|
|
||||||
int ntimes = 20;
|
int ntimes = 20;
|
||||||
if (cAgentData.SenderWantsToWaitForRoot)
|
if (cAgentData.SenderWantsToWaitForRoot)
|
||||||
{
|
{
|
||||||
while (childAgentUpdate.IsChildAgent && ntimes-- > 0)
|
while (sp.IsChildAgent && ntimes-- > 0)
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[SCENE]: Found presence {0} {1} {2} in {3} after {4} waits",
|
"[SCENE]: Found presence {0} {1} {2} in {3} after {4} waits",
|
||||||
childAgentUpdate.Name, childAgentUpdate.UUID, childAgentUpdate.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 20 - ntimes);
|
sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", Name, 20 - ntimes);
|
||||||
|
|
||||||
if (childAgentUpdate.IsChildAgent)
|
if (sp.IsChildAgent)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,9 +285,23 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Vector3 posLastSignificantMove;
|
private Vector3 posLastSignificantMove;
|
||||||
|
|
||||||
// For teleports and crossings callbacks
|
#region For teleports and crossings callbacks
|
||||||
string m_callbackURI;
|
|
||||||
UUID m_originRegionID;
|
/// <summary>
|
||||||
|
/// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
|
||||||
|
/// </summary>
|
||||||
|
private string m_callbackURI;
|
||||||
|
|
||||||
|
public UUID m_originRegionID;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
|
||||||
|
/// teleport is reusing the connection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>May be refactored or move somewhere else soon.</remarks>
|
||||||
|
public bool DoNotCloseAfterTeleport { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
/// <value>
|
/// <value>
|
||||||
/// Script engines present in the scene
|
/// Script engines present in the scene
|
||||||
|
@ -717,13 +731,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
|
|
||||||
/// teleport is reusing the connection.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>May be refactored or move somewhere else soon.</remarks>
|
|
||||||
public bool DoNotCloseAfterTeleport { get; set; }
|
|
||||||
|
|
||||||
private float m_speedModifier = 1.0f;
|
private float m_speedModifier = 1.0f;
|
||||||
|
|
||||||
public float SpeedModifier
|
public float SpeedModifier
|
||||||
|
@ -1325,14 +1332,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
int count = 20;
|
int count = 20;
|
||||||
while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
|
while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.RegionInfo.RegionName);
|
m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
|
||||||
Thread.Sleep(200);
|
Thread.Sleep(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_originRegionID.Equals(UUID.Zero))
|
if (m_originRegionID.Equals(UUID.Zero))
|
||||||
{
|
{
|
||||||
// Movement into region will fail
|
// Movement into region will fail
|
||||||
m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived", client.Name);
|
m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,8 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
|
m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
|
||||||
PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
|
PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
|
||||||
|
|
||||||
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6}",
|
||||||
LocalID, _size, Scale, Density, _avatarVolume, RawMass);
|
LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos);
|
||||||
|
|
||||||
// do actual creation in taint time
|
// do actual creation in taint time
|
||||||
PhysScene.TaintedObject("BSCharacter.create", delegate()
|
PhysScene.TaintedObject("BSCharacter.create", delegate()
|
||||||
|
@ -190,6 +190,10 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
}
|
}
|
||||||
|
|
||||||
set {
|
set {
|
||||||
|
// This is how much the avatar size is changing. Positive means getting bigger.
|
||||||
|
// The avatar altitude must be adjusted for this change.
|
||||||
|
float heightChange = value.Z - _size.Z;
|
||||||
|
|
||||||
_size = value;
|
_size = value;
|
||||||
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
||||||
// replace with the default values.
|
// replace with the default values.
|
||||||
|
@ -207,6 +211,10 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
{
|
{
|
||||||
PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
|
PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
|
||||||
UpdatePhysicalMassProperties(RawMass, true);
|
UpdatePhysicalMassProperties(RawMass, true);
|
||||||
|
|
||||||
|
// Adjust the avatar's position to account for the increase/decrease in size
|
||||||
|
ForcePosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, RawPosition.Z + heightChange / 2f);
|
||||||
|
|
||||||
// Make sure this change appears as a property update event
|
// Make sure this change appears as a property update event
|
||||||
PhysScene.PE.PushUpdate(PhysBody);
|
PhysScene.PE.PushUpdate(PhysBody);
|
||||||
}
|
}
|
||||||
|
|
|
@ -570,9 +570,9 @@ public static class BSParam
|
||||||
new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground",
|
new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground",
|
||||||
-0.2f ),
|
-0.2f ),
|
||||||
new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground",
|
new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground",
|
||||||
0.1f ),
|
0.2f ),
|
||||||
new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground",
|
new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground",
|
||||||
0.1f ),
|
0.2f ),
|
||||||
new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
||||||
0.1f ),
|
0.1f ),
|
||||||
new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
|
new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
|
||||||
|
|
|
@ -264,8 +264,15 @@
|
||||||
|
|
||||||
; Simulator Stats URI
|
; Simulator Stats URI
|
||||||
; Enable JSON simulator data by setting a URI name (case sensitive)
|
; Enable JSON simulator data by setting a URI name (case sensitive)
|
||||||
|
; Returns regular sim stats (SimFPS, ...)
|
||||||
; Stats_URI = "jsonSimStats"
|
; Stats_URI = "jsonSimStats"
|
||||||
|
|
||||||
|
; Simulator StatsManager URI
|
||||||
|
; Enable fetch of StatsManager registered stats. Fetch is query which can optionally
|
||||||
|
; specify category, container and stat to fetch. If not selected, returns all of that type.
|
||||||
|
; http://simulatorHTTPport/ManagedStats/?cat=Category&cont=Container&stat=Statistic
|
||||||
|
; ManagedStatsRemoteFetchURI = "ManagedStats"
|
||||||
|
|
||||||
; Make OpenSim start all regions woth logins disabled. They will need
|
; Make OpenSim start all regions woth logins disabled. They will need
|
||||||
; to be enabled from the console if this is set
|
; to be enabled from the console if this is set
|
||||||
; StartDisabled = false
|
; StartDisabled = false
|
||||||
|
|
Loading…
Reference in New Issue