Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5c8c6bc12 | ||
|
|
5dd2569bf7 | ||
|
|
d7e6fe488d | ||
|
|
ce468215d5 | ||
|
|
6f7825e310 | ||
|
|
dd0a89a0e6 | ||
|
|
190f9c258b | ||
|
|
46d8405229 | ||
|
|
9598c1af9e | ||
|
|
82487549f7 | ||
|
|
cdc3781f42 | ||
|
|
7df7b86ec5 | ||
|
|
81fda6f947 | ||
|
|
e9322b0bf7 | ||
|
|
96f889b20e | ||
|
|
224efe7b76 | ||
|
|
ebb394bbda | ||
|
|
c17965eec4 | ||
|
|
4ead48f09f | ||
|
|
41f3f2400e | ||
|
|
f06394f195 | ||
|
|
d53a53d4c5 | ||
|
|
757d9163fa | ||
|
|
25111e703f | ||
|
|
ad1b9bbba6 | ||
|
|
97b8739c1d | ||
|
|
0760121eb9 | ||
|
|
0a22e78f59 | ||
|
|
5e51f16ceb | ||
|
|
fd8a7e64b9 | ||
|
|
ed5f574356 | ||
|
|
44349f742e | ||
|
|
e3993eefa5 | ||
|
|
8db5d79f4b | ||
|
|
bf56b30024 | ||
|
|
8321ecb7a2 | ||
|
|
783ee949ea | ||
|
|
e041f09750 | ||
|
|
fa3edcf55c | ||
|
|
874bde366a | ||
|
|
d8df2d6bed | ||
|
|
126eae7100 | ||
|
|
3c097cb7a9 | ||
|
|
189f51233e | ||
|
|
76dc29dc37 | ||
|
|
df3914c7cd | ||
|
|
740eac192b | ||
|
|
783ecd01f4 | ||
|
|
a0e3e23aa9 | ||
|
|
1acee36822 | ||
|
|
ac90322f1b | ||
|
|
2ca93cb144 | ||
|
|
4e2805496c | ||
|
|
46af3a3d92 | ||
|
|
717b11856e | ||
|
|
0199abd625 | ||
|
|
550f6c4ad2 | ||
|
|
2b506cffb1 | ||
|
|
33469a0d2b | ||
|
|
1f18ce516f | ||
|
|
2ec34580ce | ||
|
|
288baaecaf | ||
|
|
d2b00749ef | ||
|
|
8f02fd926e | ||
|
|
9f914327c6 | ||
|
|
4215877b48 | ||
|
|
d2e79e26d7 | ||
|
|
3f6c6eed33 | ||
|
|
0a71e3ab39 | ||
|
|
8fe8fdb0c9 | ||
|
|
fbfd28a61b | ||
|
|
a0d0c9f751 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -66,6 +66,7 @@ Examples/*.dll
|
||||
OpenSim.build
|
||||
OpenSim.sln
|
||||
OpenSim.suo
|
||||
OpenSim.userprefs
|
||||
Prebuild/Prebuild.build
|
||||
Prebuild/Prebuild.sln
|
||||
TestResult.xml
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
==== Building OpenSim ====
|
||||
|
||||
=== Building on Windows ===
|
||||
# Building on Windows
|
||||
|
||||
Steps:
|
||||
* runprebuild.bat
|
||||
@@ -9,16 +7,15 @@ Steps:
|
||||
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
|
||||
* run OpenSim.exe
|
||||
|
||||
=== Building on Linux ===
|
||||
# Building on Linux
|
||||
|
||||
Prereqs:
|
||||
* Mono >= 2.4.3
|
||||
* Nant >= 0.85
|
||||
* On some Linux distributions you may need to install additional packages.
|
||||
See http://opensimulator.org/wiki/Dependencies for more information.
|
||||
|
||||
* May also use xbuild (included in mono distributions)
|
||||
* May use Monodevelop, a cross-platform IDE
|
||||
* Mono >= 2.4.3
|
||||
* Nant >= 0.85
|
||||
* On some Linux distributions you may need to install additional packages.
|
||||
See http://opensimulator.org/wiki/Dependencies for more information.
|
||||
* May also use xbuild (included in mono distributions)
|
||||
* May use Monodevelop, a cross-platform IDE
|
||||
|
||||
From the distribution type:
|
||||
* ./runprebuild.sh
|
||||
@@ -27,13 +24,13 @@ From the distribution type:
|
||||
* copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
|
||||
* run mono OpenSim.exe
|
||||
|
||||
=== Using Monodevelop ===
|
||||
# Using Monodevelop
|
||||
|
||||
From the distribution type:
|
||||
* ./runprebuild.sh
|
||||
* type monodevelop OpenSim.sln
|
||||
|
||||
=== References ===
|
||||
# References
|
||||
|
||||
Helpful resources:
|
||||
* http://opensimulator.org/wiki/Build_Instructions
|
||||
@@ -1369,6 +1369,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
/// <description>profile url</description></item>
|
||||
/// <item><term>noassets</term>
|
||||
/// <description>true if no assets should be saved</description></item>
|
||||
/// <item><term>all</term>
|
||||
/// <description>true to save all the regions in the simulator</description></item>
|
||||
/// <item><term>perm</term>
|
||||
/// <description>C and/or T</description></item>
|
||||
/// </list>
|
||||
@@ -1425,6 +1427,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
options["checkPermissions"] = (string)requestData["perm"];
|
||||
}
|
||||
|
||||
if ((string)requestData["all"] == "true")
|
||||
{
|
||||
options["all"] = (string)requestData["all"];
|
||||
}
|
||||
|
||||
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
|
||||
|
||||
if (archiver != null)
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
|
||||
if (texture == null)
|
||||
{
|
||||
//m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
|
||||
// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
|
||||
|
||||
// Fetch locally or remotely. Misses return a 404
|
||||
texture = m_assetService.Get(textureID.ToString());
|
||||
@@ -197,7 +197,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
}
|
||||
else // it was on the cache
|
||||
{
|
||||
//m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
|
||||
// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
|
||||
WriteTextureData(httpRequest, httpResponse, texture, format);
|
||||
return true;
|
||||
}
|
||||
@@ -219,12 +219,30 @@ namespace OpenSim.Capabilities.Handlers
|
||||
int start, end;
|
||||
if (TryParseRange(range, out start, out end))
|
||||
{
|
||||
|
||||
// Before clamping start make sure we can satisfy it in order to avoid
|
||||
// sending back the last byte instead of an error status
|
||||
if (start >= texture.Data.Length)
|
||||
{
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
|
||||
m_log.DebugFormat(
|
||||
"[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
|
||||
texture.ID, start, texture.Data.Length);
|
||||
|
||||
// Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
|
||||
// Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
|
||||
// of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
|
||||
// received a very small texture may attempt to fetch bytes from the server past the
|
||||
// range of data that it received originally. Whether this happens appears to depend on whether
|
||||
// the viewer's estimation of how large a request it needs to make for certain discard levels
|
||||
// (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
|
||||
// level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
|
||||
// here will cause the viewer to treat the texture as bad and never display the full resolution
|
||||
// However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
|
||||
|
||||
// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
|
||||
// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
|
||||
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
|
||||
response.ContentType = texture.Metadata.ContentType;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -232,12 +250,18 @@ namespace OpenSim.Capabilities.Handlers
|
||||
start = Utils.Clamp(start, 0, end);
|
||||
int len = end - start + 1;
|
||||
|
||||
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
|
||||
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
|
||||
|
||||
// Always return PartialContent, even if the range covered the entire data length
|
||||
// We were accidentally sending back 404 before in this situation
|
||||
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
|
||||
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
|
||||
//
|
||||
// We also do not want to send back OK even if the whole range was satisfiable since this causes
|
||||
// HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
|
||||
// if (end > maxEnd)
|
||||
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
|
||||
// else
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
|
||||
|
||||
response.ContentLength = len;
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace OpenSim.Framework
|
||||
public class Constants
|
||||
{
|
||||
public const uint RegionSize = 256;
|
||||
public const uint RegionHeight = 4096;
|
||||
public const byte TerrainPatchSize = 16;
|
||||
public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ namespace OpenSim.Framework
|
||||
private int m_physPrimMax = 0;
|
||||
private bool m_clampPrimSize = false;
|
||||
private int m_objectCapacity = 0;
|
||||
private int m_linksetCapacity = 0;
|
||||
private int m_agentCapacity = 0;
|
||||
private string m_regionType = String.Empty;
|
||||
private RegionLightShareData m_windlight = new RegionLightShareData();
|
||||
@@ -317,6 +318,11 @@ namespace OpenSim.Framework
|
||||
get { return m_objectCapacity; }
|
||||
}
|
||||
|
||||
public int LinksetCapacity
|
||||
{
|
||||
get { return m_linksetCapacity; }
|
||||
}
|
||||
|
||||
public int AgentCapacity
|
||||
{
|
||||
get { return m_agentCapacity; }
|
||||
@@ -654,6 +660,9 @@ namespace OpenSim.Framework
|
||||
|
||||
m_objectCapacity = config.GetInt("MaxPrims", 15000);
|
||||
allKeys.Remove("MaxPrims");
|
||||
|
||||
m_linksetCapacity = config.GetInt("LinksetPrims", 0);
|
||||
allKeys.Remove("LinksetPrims");
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -692,24 +701,27 @@ namespace OpenSim.Framework
|
||||
|
||||
config.Set("ExternalHostName", m_externalHostName);
|
||||
|
||||
if (m_nonphysPrimMin != 0)
|
||||
if (m_nonphysPrimMin > 0)
|
||||
config.Set("NonphysicalPrimMax", m_nonphysPrimMin);
|
||||
|
||||
if (m_nonphysPrimMax != 0)
|
||||
if (m_nonphysPrimMax > 0)
|
||||
config.Set("NonphysicalPrimMax", m_nonphysPrimMax);
|
||||
|
||||
if (m_physPrimMin != 0)
|
||||
if (m_physPrimMin > 0)
|
||||
config.Set("PhysicalPrimMax", m_physPrimMin);
|
||||
|
||||
if (m_physPrimMax != 0)
|
||||
if (m_physPrimMax > 0)
|
||||
config.Set("PhysicalPrimMax", m_physPrimMax);
|
||||
|
||||
config.Set("ClampPrimSize", m_clampPrimSize.ToString());
|
||||
|
||||
if (m_objectCapacity != 0)
|
||||
if (m_objectCapacity > 0)
|
||||
config.Set("MaxPrims", m_objectCapacity);
|
||||
|
||||
if (m_agentCapacity != 0)
|
||||
if (m_linksetCapacity > 0)
|
||||
config.Set("LinksetPrims", m_linksetCapacity);
|
||||
|
||||
if (m_agentCapacity > 0)
|
||||
config.Set("MaxAgents", m_agentCapacity);
|
||||
|
||||
if (ScopeID != UUID.Zero)
|
||||
@@ -804,6 +816,9 @@ namespace OpenSim.Framework
|
||||
configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Max objects this sim will hold", m_objectCapacity.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("linkset_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Max prims an object will hold", m_linksetCapacity.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Max avatars this sim will hold", m_agentCapacity.ToString(), true);
|
||||
|
||||
@@ -922,6 +937,9 @@ namespace OpenSim.Framework
|
||||
case "object_capacity":
|
||||
m_objectCapacity = (int)configuration_result;
|
||||
break;
|
||||
case "linkset_capacity":
|
||||
m_linksetCapacity = (int)configuration_result;
|
||||
break;
|
||||
case "agent_capacity":
|
||||
m_agentCapacity = (int)configuration_result;
|
||||
break;
|
||||
@@ -1052,4 +1070,4 @@ namespace OpenSim.Framework
|
||||
return kvp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,11 @@ namespace OpenSim.Framework.Serialization
|
||||
/// </value>
|
||||
public const string INVENTORY_PATH = "inventory/";
|
||||
|
||||
/// <value>
|
||||
/// Path for regions in a multi-region archive
|
||||
/// </value>
|
||||
public const string REGIONS_PATH = "regions/";
|
||||
|
||||
/// <value>
|
||||
/// Path for the prims file
|
||||
/// </value>
|
||||
|
||||
@@ -449,9 +449,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (TryGetStreamHandler(handlerKey, out requestHandler))
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
|
||||
request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
|
||||
LogIncomingToStreamHandler(request, requestHandler);
|
||||
|
||||
response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
|
||||
|
||||
@@ -563,9 +561,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (DoWeHaveALLSDHandler(request.RawUrl))
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
LogIncomingToContentTypeHandler(request);
|
||||
|
||||
buffer = HandleLLSDRequests(request, response);
|
||||
}
|
||||
@@ -573,18 +569,14 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
else if (DoWeHaveAHTTPHandler(request.RawUrl))
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
LogIncomingToContentTypeHandler(request);
|
||||
|
||||
buffer = HandleHTTPRequest(request, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
LogIncomingToXmlRpcHandler(request);
|
||||
|
||||
// generic login request.
|
||||
buffer = HandleXmlRpcRequests(request, response);
|
||||
@@ -654,6 +646,58 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
}
|
||||
}
|
||||
|
||||
private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
|
||||
request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
|
||||
|
||||
if (DebugLevel >= 4)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingToContentTypeHandler(OSHttpRequest request)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
if (DebugLevel >= 4)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
if (DebugLevel >= 4)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingInDetail(OSHttpRequest request)
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8))
|
||||
{
|
||||
string output;
|
||||
|
||||
if (DebugLevel == 4)
|
||||
{
|
||||
const int sampleLength = 80;
|
||||
char[] sampleChars = new char[sampleLength];
|
||||
reader.Read(sampleChars, 0, sampleLength);
|
||||
output = string.Format("[BASE HTTP SERVER]: {0}...", new string(sampleChars).Replace("\n", @"\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
output = string.Format("[BASE HTTP SERVER]: {0}", reader.ReadToEnd());
|
||||
}
|
||||
|
||||
m_log.Debug(output);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler)
|
||||
{
|
||||
string bestMatch = null;
|
||||
|
||||
@@ -29,6 +29,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
@@ -104,6 +105,11 @@ namespace OpenSim.Framework.Servers
|
||||
|
||||
public static void RegisterHttpConsoleCommands(ICommandConsole console)
|
||||
{
|
||||
console.Commands.AddCommand(
|
||||
"Comms", false, "show http-handlers",
|
||||
"show http-handlers",
|
||||
"Show all registered http handlers", HandleShowHttpHandlersCommand);
|
||||
|
||||
console.Commands.AddCommand(
|
||||
"Debug", false, "debug http", "debug http [<level>]",
|
||||
"Turn on inbound non-poll http request debugging.",
|
||||
@@ -111,6 +117,8 @@ namespace OpenSim.Framework.Servers
|
||||
+ "If level >= 1, then short warnings are logged when receiving bad input data.\n"
|
||||
+ "If level >= 2, then long warnings are logged when receiving bad input data.\n"
|
||||
+ "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n"
|
||||
+ "If level >= 4, then a sample from the beginning of the incoming data is logged.\n"
|
||||
+ "If level >= 5, then the entire incoming data is logged.\n"
|
||||
+ "If no level is specified then the current level is returned.",
|
||||
HandleDebugHttpCommand);
|
||||
}
|
||||
@@ -136,10 +144,55 @@ namespace OpenSim.Framework.Servers
|
||||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: debug http 0..3");
|
||||
MainConsole.Instance.Output("Usage: debug http 0..5");
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleShowHttpHandlersCommand(string module, string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: show http-handlers");
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder handlers = new StringBuilder();
|
||||
|
||||
lock (m_Servers)
|
||||
{
|
||||
foreach (BaseHttpServer httpServer in m_Servers.Values)
|
||||
{
|
||||
handlers.AppendFormat(
|
||||
"Registered HTTP Handlers for server at {0}:{1}\n", httpServer.ListenIPAddress, httpServer.Port);
|
||||
|
||||
handlers.AppendFormat("* XMLRPC:\n");
|
||||
foreach (String s in httpServer.GetXmlRpcHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* HTTP:\n");
|
||||
List<String> poll = httpServer.GetPollServiceHandlerKeys();
|
||||
foreach (String s in httpServer.GetHTTPHandlerKeys())
|
||||
handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
|
||||
|
||||
handlers.AppendFormat("* Agent:\n");
|
||||
foreach (String s in httpServer.GetAgentHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* LLSD:\n");
|
||||
foreach (String s in httpServer.GetLLSDHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* StreamHandlers ({0}):\n", httpServer.GetStreamHandlerKeys().Count);
|
||||
foreach (String s in httpServer.GetStreamHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.Append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output(handlers.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an already started HTTP server to the collection of known servers.
|
||||
/// </summary>
|
||||
|
||||
@@ -1007,6 +1007,38 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy data from one stream to another, leaving the read position of both streams at the beginning.
|
||||
/// </summary>
|
||||
/// <param name='inputStream'>
|
||||
/// Input stream. Must be seekable.
|
||||
/// </param>
|
||||
/// <exception cref='ArgumentException'>
|
||||
/// Thrown if the input stream is not seekable.
|
||||
/// </exception>
|
||||
public static Stream Copy(Stream inputStream)
|
||||
{
|
||||
if (!inputStream.CanSeek)
|
||||
throw new ArgumentException("Util.Copy(Stream inputStream) must receive an inputStream that can seek");
|
||||
|
||||
const int readSize = 256;
|
||||
byte[] buffer = new byte[readSize];
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
int count = inputStream.Read(buffer, 0, readSize);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
ms.Write(buffer, 0, count);
|
||||
count = inputStream.Read(buffer, 0, readSize);
|
||||
}
|
||||
|
||||
ms.Position = 0;
|
||||
inputStream.Position = 0;
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args)
|
||||
{
|
||||
return SendXmlRpcCommand(url, methodName, args);
|
||||
|
||||
@@ -292,7 +292,7 @@ namespace OpenSim
|
||||
|
||||
m_console.Commands.AddCommand("Archiving", false, "save oar",
|
||||
//"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
|
||||
"save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]",
|
||||
"save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [<OAR path>]",
|
||||
"Save a region's data to an OAR archive.",
|
||||
// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
|
||||
"-h|--home=<url> adds the url of the profile service to the saved user information.\n"
|
||||
@@ -302,6 +302,7 @@ namespace OpenSim
|
||||
+ " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
|
||||
+ "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
|
||||
+ " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
|
||||
+ "--all saves all the regions in the simulator, instead of just the current region.\n"
|
||||
+ "The OAR path must be a filesystem path."
|
||||
+ " If this is not given then the oar is saved to region.oar in the current directory.",
|
||||
SaveOar);
|
||||
@@ -332,10 +333,6 @@ namespace OpenSim
|
||||
"show circuits",
|
||||
"Show agent circuit data", HandleShow);
|
||||
|
||||
m_console.Commands.AddCommand("Comms", false, "show http-handlers",
|
||||
"show http-handlers",
|
||||
"Show all registered http handlers", HandleShow);
|
||||
|
||||
m_console.Commands.AddCommand("Comms", false, "show pending-objects",
|
||||
"show pending-objects",
|
||||
"Show # of objects on the pending queues of all scene viewers", HandleShow);
|
||||
@@ -1013,33 +1010,6 @@ namespace OpenSim
|
||||
HandleShowCircuits();
|
||||
break;
|
||||
|
||||
case "http-handlers":
|
||||
System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n");
|
||||
|
||||
handlers.AppendFormat("* XMLRPC:\n");
|
||||
foreach (String s in HttpServer.GetXmlRpcHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* HTTP:\n");
|
||||
List<String> poll = HttpServer.GetPollServiceHandlerKeys();
|
||||
foreach (String s in HttpServer.GetHTTPHandlerKeys())
|
||||
handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
|
||||
|
||||
handlers.AppendFormat("* Agent:\n");
|
||||
foreach (String s in HttpServer.GetAgentHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* LLSD:\n");
|
||||
foreach (String s in HttpServer.GetLLSDHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count);
|
||||
foreach (String s in HttpServer.GetStreamHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
MainConsole.Instance.Output(handlers.ToString());
|
||||
break;
|
||||
|
||||
case "modules":
|
||||
MainConsole.Instance.Output("The currently loaded shared modules are:");
|
||||
foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules)
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack
|
||||
|
||||
protected override void StartupSpecific()
|
||||
{
|
||||
SceneManager = new SceneManager();
|
||||
SceneManager = SceneManager.Instance;
|
||||
m_clientStackManager = CreateClientStackManager();
|
||||
|
||||
Initialize();
|
||||
|
||||
@@ -52,7 +52,7 @@ using OpenSim.Services.Interfaces;
|
||||
[assembly: Addin("FlotsamAssetCache", "1.1")]
|
||||
[assembly: AddinDependency("OpenSim", "0.5")]
|
||||
|
||||
namespace Flotsam.RegionModules.AssetCache
|
||||
namespace OpenSim.Region.CoreModules.Asset
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||
public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService
|
||||
@@ -107,8 +107,6 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
private IAssetService m_AssetService;
|
||||
private List<Scene> m_Scenes = new List<Scene>();
|
||||
|
||||
private bool m_DeepScanBeforePurge;
|
||||
|
||||
public FlotsamAssetCache()
|
||||
{
|
||||
m_InvalidChars.AddRange(Path.GetInvalidPathChars());
|
||||
@@ -170,8 +168,6 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen);
|
||||
|
||||
m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt);
|
||||
|
||||
m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge);
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
|
||||
@@ -506,13 +502,10 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
// Purge all files last accessed prior to this point
|
||||
DateTime purgeLine = DateTime.Now - m_FileExpiration;
|
||||
|
||||
// An optional deep scan at this point will ensure assets present in scenes,
|
||||
// or referenced by objects in the scene, but not recently accessed
|
||||
// are not purged.
|
||||
if (m_DeepScanBeforePurge)
|
||||
{
|
||||
CacheScenes();
|
||||
}
|
||||
// An asset cache may contain local non-temporary assets that are not in the asset service. Therefore,
|
||||
// before cleaning up expired files we must scan the objects in the scene to make sure that we retain
|
||||
// such local assets if they have not been recently accessed.
|
||||
TouchAllSceneAssets(false);
|
||||
|
||||
foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
|
||||
{
|
||||
@@ -705,11 +698,14 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through all Scenes, doing a deep scan through assets
|
||||
/// to cache all assets present in the scene or referenced by assets
|
||||
/// in the scene
|
||||
/// to update the access time of all assets present in the scene or referenced by assets
|
||||
/// in the scene.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private int CacheScenes()
|
||||
/// <param name="storeUncached">
|
||||
/// If true, then assets scanned which are not found in cache are added to the cache.
|
||||
/// </param>
|
||||
/// <returns>Number of distinct asset references found in the scene.</returns>
|
||||
private int TouchAllSceneAssets(bool storeUncached)
|
||||
{
|
||||
UuidGatherer gatherer = new UuidGatherer(m_AssetService);
|
||||
|
||||
@@ -732,7 +728,7 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
{
|
||||
File.SetLastAccessTime(filename, DateTime.Now);
|
||||
}
|
||||
else
|
||||
else if (storeUncached)
|
||||
{
|
||||
m_AssetService.Get(assetID.ToString());
|
||||
}
|
||||
@@ -860,13 +856,14 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case "assets":
|
||||
m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes.");
|
||||
m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes.");
|
||||
|
||||
Util.FireAndForget(delegate {
|
||||
int assetsCached = CacheScenes();
|
||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached);
|
||||
int assetReferenceTotal = TouchAllSceneAssets(true);
|
||||
m_log.InfoFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
|
||||
assetReferenceTotal);
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
@@ -35,7 +35,6 @@ using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Assets;
|
||||
using Flotsam.RegionModules.AssetCache;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||
|
||||
@@ -482,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
Util.FireAndForget(
|
||||
delegate
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
|
||||
friendList.Count, agentID, online);
|
||||
// m_log.DebugFormat(
|
||||
// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
|
||||
// friendList.Count, agentID, online);
|
||||
|
||||
// Notify about this user status
|
||||
StatusNotify(friendList, agentID, online);
|
||||
|
||||
@@ -308,6 +308,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
protected override InventoryItemBase GetItem(UUID agentID, UUID itemID)
|
||||
{
|
||||
InventoryItemBase item = base.GetItem(agentID, itemID);
|
||||
if (item == null)
|
||||
return null;
|
||||
|
||||
string userAssetServer = string.Empty;
|
||||
if (IsForeignUser(agentID, out userAssetServer))
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.Drawing;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
{
|
||||
public class DynamicTexture : IDynamicTexture
|
||||
{
|
||||
public string InputCommands { get; private set; }
|
||||
public Uri InputUri { get; private set; }
|
||||
public string InputParams { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
public Size Size { get; private set; }
|
||||
public bool IsReuseable { get; private set; }
|
||||
|
||||
public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
|
||||
{
|
||||
InputCommands = inputCommands;
|
||||
InputParams = inputParams;
|
||||
Data = data;
|
||||
Size = size;
|
||||
IsReuseable = isReuseable;
|
||||
}
|
||||
|
||||
public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
|
||||
{
|
||||
InputUri = inputUri;
|
||||
InputParams = inputParams;
|
||||
Data = data;
|
||||
Size = size;
|
||||
IsReuseable = isReuseable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
{
|
||||
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
|
||||
{
|
||||
//private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private const int ALL_SIDES = -1;
|
||||
|
||||
@@ -54,6 +54,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
/// </summary>
|
||||
public bool ReuseTextures { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If false, then textures which have a low data size are not reused when ReuseTextures = true.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
|
||||
/// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
|
||||
/// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
|
||||
/// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
|
||||
/// to work around this problem.</remarks>
|
||||
public bool ReuseLowDataTextures { get; set; }
|
||||
|
||||
private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
|
||||
|
||||
private Dictionary<string, IDynamicTextureRender> RenderPlugins =
|
||||
@@ -83,18 +94,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
/// <summary>
|
||||
/// Called by code which actually renders the dynamic texture to supply texture data.
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="isReuseable">True if the data generated can be reused for subsequent identical requests</param>
|
||||
public void ReturnData(UUID id, byte[] data, bool isReuseable)
|
||||
/// <param name="updaterId"></param>
|
||||
/// <param name="texture"></param>
|
||||
public void ReturnData(UUID updaterId, IDynamicTexture texture)
|
||||
{
|
||||
DynamicTextureUpdater updater = null;
|
||||
|
||||
lock (Updaters)
|
||||
{
|
||||
if (Updaters.ContainsKey(id))
|
||||
if (Updaters.ContainsKey(updaterId))
|
||||
{
|
||||
updater = Updaters[id];
|
||||
updater = Updaters[updaterId];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,11 +113,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
if (RegisteredScenes.ContainsKey(updater.SimUUID))
|
||||
{
|
||||
Scene scene = RegisteredScenes[updater.SimUUID];
|
||||
UUID newTextureID = updater.DataReceived(data, scene);
|
||||
UUID newTextureID = updater.DataReceived(texture.Data, scene);
|
||||
|
||||
if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
|
||||
if (ReuseTextures
|
||||
&& !updater.BlendWithOldTexture
|
||||
&& texture.IsReuseable
|
||||
&& (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
|
||||
{
|
||||
m_reuseableDynamicTextures.Store(
|
||||
GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
|
||||
GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +138,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the texture is reuseable based on its data size.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
|
||||
/// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
|
||||
/// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
private bool IsDataSizeReuseable(IDynamicTexture texture)
|
||||
{
|
||||
// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
|
||||
int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
|
||||
// discardLevel2DataThreshold, texture.Data.Length);
|
||||
|
||||
return discardLevel2DataThreshold < texture.Data.Length;
|
||||
}
|
||||
|
||||
public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
|
||||
string extraParams, int updateTimer)
|
||||
{
|
||||
@@ -249,10 +285,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
}
|
||||
}
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
|
||||
// part.Name, part.ParentGroup.Scene.Name);
|
||||
|
||||
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
|
||||
// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
|
||||
|
||||
// No need to add to updaters as the texture is always the same. Not that this functionality
|
||||
// apppears to be implemented anyway.
|
||||
updater.UpdatePart(part, (UUID)objReusableTextureUUID);
|
||||
@@ -285,7 +329,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
{
|
||||
IConfig texturesConfig = config.Configs["Textures"];
|
||||
if (texturesConfig != null)
|
||||
{
|
||||
ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
|
||||
ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
|
||||
}
|
||||
|
||||
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
|
||||
{
|
||||
@@ -448,8 +495,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
|
||||
if (cacheLayerDecode != null)
|
||||
{
|
||||
cacheLayerDecode.Decode(asset.FullID, asset.Data);
|
||||
cacheLayerDecode = null;
|
||||
if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
|
||||
m_log.WarnFormat(
|
||||
"[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
|
||||
asset.ID, part.Name, part.ParentGroup.Scene.Name);
|
||||
}
|
||||
|
||||
UUID oldID = UpdatePart(part, asset.FullID);
|
||||
|
||||
@@ -32,6 +32,7 @@ using System.Net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Imaging;
|
||||
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using log4net;
|
||||
@@ -73,12 +74,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
// return false;
|
||||
// }
|
||||
|
||||
public byte[] ConvertUrl(string url, string extraParams)
|
||||
public IDynamicTexture ConvertUrl(string url, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] ConvertData(string bodyData, string extraParams)
|
||||
public IDynamicTexture ConvertData(string bodyData, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -171,11 +172,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
|
||||
private void HttpRequestReturn(IAsyncResult result)
|
||||
{
|
||||
|
||||
RequestState state = (RequestState) result.AsyncState;
|
||||
WebRequest request = (WebRequest) state.Request;
|
||||
Stream stream = null;
|
||||
byte[] imageJ2000 = new byte[0];
|
||||
Size newSize = new Size(0, 0);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -188,37 +189,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
try
|
||||
{
|
||||
Bitmap image = new Bitmap(stream);
|
||||
Size newsize;
|
||||
|
||||
// TODO: make this a bit less hard coded
|
||||
if ((image.Height < 64) && (image.Width < 64))
|
||||
{
|
||||
newsize = new Size(32, 32);
|
||||
newSize.Width = 32;
|
||||
newSize.Height = 32;
|
||||
}
|
||||
else if ((image.Height < 128) && (image.Width < 128))
|
||||
{
|
||||
newsize = new Size(64, 64);
|
||||
newSize.Width = 64;
|
||||
newSize.Height = 64;
|
||||
}
|
||||
else if ((image.Height < 256) && (image.Width < 256))
|
||||
{
|
||||
newsize = new Size(128, 128);
|
||||
newSize.Width = 128;
|
||||
newSize.Height = 128;
|
||||
}
|
||||
else if ((image.Height < 512 && image.Width < 512))
|
||||
{
|
||||
newsize = new Size(256, 256);
|
||||
newSize.Width = 256;
|
||||
newSize.Height = 256;
|
||||
}
|
||||
else if ((image.Height < 1024 && image.Width < 1024))
|
||||
{
|
||||
newsize = new Size(512, 512);
|
||||
newSize.Width = 512;
|
||||
newSize.Height = 512;
|
||||
}
|
||||
else
|
||||
{
|
||||
newsize = new Size(1024, 1024);
|
||||
newSize.Width = 1024;
|
||||
newSize.Height = 1024;
|
||||
}
|
||||
|
||||
Bitmap resize = new Bitmap(image, newsize);
|
||||
|
||||
imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
|
||||
using (Bitmap resize = new Bitmap(image, newSize))
|
||||
{
|
||||
imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -233,7 +240,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
}
|
||||
catch (WebException)
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -243,10 +249,13 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
}
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
|
||||
m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
|
||||
imageJ2000.Length, state.RequestID);
|
||||
|
||||
m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
|
||||
m_textureManager.ReturnData(
|
||||
state.RequestID,
|
||||
new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
|
||||
request.RequestUri, null, imageJ2000, newSize, false));
|
||||
}
|
||||
|
||||
#region Nested type: RequestState
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
|
||||
|
||||
m_dtm = new DynamicTextureModule();
|
||||
m_dtm.ReuseTextures = reuseTextures;
|
||||
// m_dtm.ReuseLowDataTextures = reuseTextures;
|
||||
|
||||
m_vrm = new VectorRenderModule();
|
||||
|
||||
@@ -201,6 +202,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
|
||||
public void TestRepeatSameDrawReusingTexture()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
|
||||
|
||||
@@ -228,6 +230,46 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
|
||||
Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
|
||||
/// problems for current viewers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
|
||||
/// texture
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void TestRepeatSameDrawLowDataTexture()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
|
||||
|
||||
SetupScene(true);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"1024",
|
||||
0);
|
||||
|
||||
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"1024",
|
||||
0);
|
||||
|
||||
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ using System.Net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Imaging;
|
||||
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using log4net;
|
||||
@@ -46,6 +47,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
{
|
||||
public class VectorRenderModule : IRegionModule, IDynamicTextureRender
|
||||
{
|
||||
// These fields exist for testing purposes, please do not remove.
|
||||
// private static bool s_flipper;
|
||||
// private static byte[] s_asset1Data;
|
||||
// private static byte[] s_asset2Data;
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
@@ -80,20 +86,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
// return lines.Any((str, r) => str.StartsWith("Image"));
|
||||
// }
|
||||
|
||||
public byte[] ConvertUrl(string url, string extraParams)
|
||||
public IDynamicTexture ConvertUrl(string url, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] ConvertData(string bodyData, string extraParams)
|
||||
public IDynamicTexture ConvertData(string bodyData, string extraParams)
|
||||
{
|
||||
bool reuseable;
|
||||
return Draw(bodyData, extraParams, out reuseable);
|
||||
}
|
||||
|
||||
private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
|
||||
{
|
||||
return Draw(bodyData, extraParams, out reuseable);
|
||||
return Draw(bodyData, extraParams);
|
||||
}
|
||||
|
||||
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
|
||||
@@ -104,10 +104,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
|
||||
{
|
||||
// XXX: This isn't actually being done asynchronously!
|
||||
bool reuseable;
|
||||
byte[] data = ConvertData(bodyData, extraParams, out reuseable);
|
||||
|
||||
m_textureManager.ReturnData(id, data, reuseable);
|
||||
m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -161,6 +158,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
{
|
||||
m_textureManager.RegisterRender(GetContentType(), this);
|
||||
}
|
||||
|
||||
// This code exists for testing purposes, please do not remove.
|
||||
// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
|
||||
// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
|
||||
|
||||
// Terrain dirt - smallest bin/assets file (6004 bytes)
|
||||
// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
@@ -179,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
|
||||
#endregion
|
||||
|
||||
private byte[] Draw(string data, string extraParams, out bool reuseable)
|
||||
private IDynamicTexture Draw(string data, string extraParams)
|
||||
{
|
||||
// We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
|
||||
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
|
||||
@@ -322,6 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
|
||||
Bitmap bitmap = null;
|
||||
Graphics graph = null;
|
||||
bool reuseable = false;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -364,6 +369,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
}
|
||||
|
||||
byte[] imageJ2000 = new byte[0];
|
||||
|
||||
// This code exists for testing purposes, please do not remove.
|
||||
// if (s_flipper)
|
||||
// imageJ2000 = s_asset1Data;
|
||||
// else
|
||||
// imageJ2000 = s_asset2Data;
|
||||
//
|
||||
// s_flipper = !s_flipper;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -376,7 +389,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
|
||||
return imageJ2000;
|
||||
return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
|
||||
data, extraParams, imageJ2000, new Size(width, height), reuseable);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ using OpenSim.Tests.Common;
|
||||
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class GridConnectorsTests
|
||||
public class GridConnectorsTests : OpenSimTestCase
|
||||
{
|
||||
LocalGridServicesConnector m_LocalConnector;
|
||||
private void SetUp()
|
||||
|
||||
@@ -43,6 +43,7 @@ using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Framework.Scenes.Serialization;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using System.Threading;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
@@ -52,7 +53,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
public class ArchiveReadRequest
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Contains data used while dearchiving a single scene.
|
||||
/// </summary>
|
||||
private class DearchiveContext
|
||||
{
|
||||
public Scene Scene { get; set; }
|
||||
|
||||
public List<string> SerialisedSceneObjects { get; set; }
|
||||
|
||||
public List<string> SerialisedParcels { get; set; }
|
||||
|
||||
public List<SceneObjectGroup> SceneObjects { get; set; }
|
||||
|
||||
public DearchiveContext(Scene scene)
|
||||
{
|
||||
Scene = scene;
|
||||
SerialisedSceneObjects = new List<string>();
|
||||
SerialisedParcels = new List<string>();
|
||||
SceneObjects = new List<SceneObjectGroup>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
|
||||
/// bumps here should be compatible.
|
||||
@@ -62,9 +86,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
/// <summary>
|
||||
/// Has the control file been loaded for this archive?
|
||||
/// </summary>
|
||||
public bool ControlFileLoaded { get; private set; }
|
||||
public bool ControlFileLoaded { get; private set; }
|
||||
|
||||
protected Scene m_scene;
|
||||
protected string m_loadPath;
|
||||
protected Scene m_rootScene;
|
||||
protected Stream m_loadStream;
|
||||
protected Guid m_requestId;
|
||||
protected string m_errorMessage;
|
||||
@@ -91,7 +116,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
if (m_UserMan == null)
|
||||
{
|
||||
m_UserMan = m_scene.RequestModuleInterface<IUserManagement>();
|
||||
m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>();
|
||||
}
|
||||
return m_UserMan;
|
||||
}
|
||||
@@ -104,10 +129,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
|
||||
private IGroupsModule m_groupsModule;
|
||||
|
||||
private IAssetService m_assetService = null;
|
||||
|
||||
|
||||
public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
|
||||
{
|
||||
m_scene = scene;
|
||||
m_rootScene = scene;
|
||||
|
||||
m_loadPath = loadPath;
|
||||
try
|
||||
{
|
||||
m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress);
|
||||
@@ -128,12 +157,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
// Zero can never be a valid user id
|
||||
m_validUserUuids[UUID.Zero] = false;
|
||||
|
||||
m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
|
||||
m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
|
||||
m_assetService = m_rootScene.AssetService;
|
||||
}
|
||||
|
||||
public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
|
||||
{
|
||||
m_scene = scene;
|
||||
m_rootScene = scene;
|
||||
m_loadPath = null;
|
||||
m_loadStream = loadStream;
|
||||
m_merge = merge;
|
||||
m_skipAssets = skipAssets;
|
||||
@@ -142,33 +173,34 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
// Zero can never be a valid user id
|
||||
m_validUserUuids[UUID.Zero] = false;
|
||||
|
||||
m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
|
||||
m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
|
||||
m_assetService = m_rootScene.AssetService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dearchive the region embodied in this request.
|
||||
/// </summary>
|
||||
public void DearchiveRegion()
|
||||
{
|
||||
// The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions
|
||||
DearchiveRegion0DotStar();
|
||||
}
|
||||
|
||||
private void DearchiveRegion0DotStar()
|
||||
{
|
||||
int successfulAssetRestores = 0;
|
||||
int failedAssetRestores = 0;
|
||||
List<string> serialisedSceneObjects = new List<string>();
|
||||
List<string> serialisedParcels = new List<string>();
|
||||
string filePath = "NONE";
|
||||
|
||||
TarArchiveReader archive = new TarArchiveReader(m_loadStream);
|
||||
DearchiveScenesInfo dearchivedScenes;
|
||||
|
||||
// We dearchive all the scenes at once, because the files in the TAR archive might be mixed.
|
||||
// Therefore, we have to keep track of the dearchive context of all the scenes.
|
||||
Dictionary<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>();
|
||||
|
||||
string fullPath = "NONE";
|
||||
TarArchiveReader archive = null;
|
||||
byte[] data;
|
||||
TarArchiveReader.TarEntryType entryType;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
|
||||
FindAndLoadControlFile(out archive, out dearchivedScenes);
|
||||
|
||||
while ((data = archive.ReadEntry(out fullPath, out entryType)) != null)
|
||||
{
|
||||
//m_log.DebugFormat(
|
||||
// "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
|
||||
@@ -176,9 +208,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
|
||||
continue;
|
||||
|
||||
|
||||
// Find the scene that this file belongs to
|
||||
|
||||
Scene scene;
|
||||
string filePath;
|
||||
if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath))
|
||||
continue; // this file belongs to a region that we're not loading
|
||||
|
||||
DearchiveContext sceneContext = null;
|
||||
if (scene != null)
|
||||
{
|
||||
if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext))
|
||||
{
|
||||
sceneContext = new DearchiveContext(scene);
|
||||
sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Process the file
|
||||
|
||||
if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
|
||||
{
|
||||
serialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
|
||||
sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
|
||||
}
|
||||
else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets)
|
||||
{
|
||||
@@ -192,19 +245,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
}
|
||||
else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
|
||||
{
|
||||
LoadTerrain(filePath, data);
|
||||
LoadTerrain(scene, filePath, data);
|
||||
}
|
||||
else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
|
||||
{
|
||||
LoadRegionSettings(filePath, data);
|
||||
LoadRegionSettings(scene, filePath, data, dearchivedScenes);
|
||||
}
|
||||
else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
|
||||
{
|
||||
serialisedParcels.Add(Encoding.UTF8.GetString(data));
|
||||
sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
|
||||
}
|
||||
else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
|
||||
{
|
||||
LoadControlFile(filePath, data);
|
||||
// Ignore, because we already read the control file
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,15 +265,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e);
|
||||
m_log.Error(
|
||||
String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e);
|
||||
m_errorMessage += e.ToString();
|
||||
m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
|
||||
m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
archive.Close();
|
||||
if (archive != null)
|
||||
archive.Close();
|
||||
}
|
||||
|
||||
if (!m_skipAssets)
|
||||
@@ -234,32 +288,143 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_merge)
|
||||
foreach (DearchiveContext sceneContext in sceneContexts.Values)
|
||||
{
|
||||
m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
|
||||
m_scene.DeleteAllSceneObjects();
|
||||
m_log.InfoFormat("[ARCHIVER:] Loading region {0}", sceneContext.Scene.RegionInfo.RegionName);
|
||||
|
||||
if (!m_merge)
|
||||
{
|
||||
m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
|
||||
sceneContext.Scene.DeleteAllSceneObjects();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
|
||||
LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
|
||||
|
||||
// Inform any interested parties that the region has changed. We waited until now so that all
|
||||
// of the region's objects will be loaded when we send this notification.
|
||||
IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
|
||||
if (estateModule != null)
|
||||
estateModule.TriggerRegionInfoChange();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e);
|
||||
m_errorMessage += e.ToString();
|
||||
m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LoadParcels(serialisedParcels);
|
||||
LoadObjects(serialisedSceneObjects);
|
||||
// Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
|
||||
// that users can enter the scene. If we allow the scripts to start in the loop above
|
||||
// then they significantly increase the time until the OAR finishes loading.
|
||||
Util.FireAndForget(delegate(object o)
|
||||
{
|
||||
Thread.Sleep(15000);
|
||||
m_log.Info("Starting scripts in scene objects");
|
||||
|
||||
foreach (DearchiveContext sceneContext in sceneContexts.Values)
|
||||
{
|
||||
foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
|
||||
{
|
||||
sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
|
||||
sceneObject.ResumeScripts();
|
||||
}
|
||||
|
||||
sceneContext.SceneObjects.Clear();
|
||||
}
|
||||
});
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
|
||||
|
||||
m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
|
||||
m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches through the files in the archive for the control file, and reads it.
|
||||
/// We must read the control file first, in order to know which regions are available.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In most cases the control file *is* first, since that's how we create archives. However,
|
||||
/// it's possible that someone rewrote the archive externally so we can't rely on this fact.
|
||||
/// </remarks>
|
||||
/// <param name="archive"></param>
|
||||
/// <param name="dearchivedScenes"></param>
|
||||
private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes)
|
||||
{
|
||||
archive = new TarArchiveReader(m_loadStream);
|
||||
dearchivedScenes = new DearchiveScenesInfo();
|
||||
|
||||
string filePath;
|
||||
byte[] data;
|
||||
TarArchiveReader.TarEntryType entryType;
|
||||
bool firstFile = true;
|
||||
|
||||
while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
|
||||
{
|
||||
if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
|
||||
continue;
|
||||
|
||||
if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
|
||||
{
|
||||
LoadControlFile(filePath, data, dearchivedScenes);
|
||||
|
||||
// Find which scenes are available in the simulator
|
||||
ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup();
|
||||
SceneManager.Instance.ForEachScene(delegate(Scene scene2)
|
||||
{
|
||||
simulatorScenes.AddScene(scene2);
|
||||
});
|
||||
simulatorScenes.CalcSceneLocations();
|
||||
dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes);
|
||||
|
||||
// If the control file wasn't the first file then reset the read pointer
|
||||
if (!firstFile)
|
||||
{
|
||||
m_log.Warn("Control file wasn't the first file in the archive");
|
||||
if (m_loadStream.CanSeek)
|
||||
{
|
||||
m_loadStream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
else if (m_loadPath != null)
|
||||
{
|
||||
archive.Close();
|
||||
archive = null;
|
||||
m_loadStream.Close();
|
||||
m_loadStream = null;
|
||||
m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress);
|
||||
archive = new TarArchiveReader(m_loadStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
// There isn't currently a scenario where this happens, but it's best to add a check just in case
|
||||
throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
firstFile = false;
|
||||
}
|
||||
|
||||
throw new Exception("Control file not found");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load serialized scene objects.
|
||||
/// </summary>
|
||||
/// <param name="serialisedSceneObjects"></param>
|
||||
protected void LoadObjects(List<string> serialisedSceneObjects)
|
||||
protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects)
|
||||
{
|
||||
// Reload serialized prims
|
||||
m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
|
||||
|
||||
UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject;
|
||||
UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
|
||||
|
||||
IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>();
|
||||
IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
|
||||
int sceneObjectsLoadedCount = 0;
|
||||
|
||||
foreach (string serialisedSceneObject in serialisedSceneObjects)
|
||||
@@ -280,7 +445,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
|
||||
SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
|
||||
|
||||
bool isTelehub = (sceneObject.UUID == oldTelehubUUID);
|
||||
bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
|
||||
|
||||
// For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
|
||||
// on the same region server and multiple examples a single object archive to be imported
|
||||
@@ -290,8 +455,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
if (isTelehub)
|
||||
{
|
||||
// Change the Telehub Object to the new UUID
|
||||
m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
|
||||
m_scene.RegionInfo.RegionSettings.Save();
|
||||
scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
|
||||
scene.RegionInfo.RegionSettings.Save();
|
||||
oldTelehubUUID = UUID.Zero;
|
||||
}
|
||||
|
||||
@@ -301,17 +466,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
if (part.CreatorData == null || part.CreatorData == string.Empty)
|
||||
{
|
||||
if (!ResolveUserUuid(part.CreatorID))
|
||||
part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
if (!ResolveUserUuid(scene, part.CreatorID))
|
||||
part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
}
|
||||
if (UserManager != null)
|
||||
UserManager.AddUser(part.CreatorID, part.CreatorData);
|
||||
|
||||
if (!ResolveUserUuid(part.OwnerID))
|
||||
part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
if (!ResolveUserUuid(scene, part.OwnerID))
|
||||
part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
|
||||
if (!ResolveUserUuid(part.LastOwnerID))
|
||||
part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
if (!ResolveUserUuid(scene, part.LastOwnerID))
|
||||
part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
|
||||
if (!ResolveGroupUuid(part.GroupID))
|
||||
part.GroupID = UUID.Zero;
|
||||
@@ -328,15 +493,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
TaskInventoryDictionary inv = part.TaskInventory;
|
||||
foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
|
||||
{
|
||||
if (!ResolveUserUuid(kvp.Value.OwnerID))
|
||||
if (!ResolveUserUuid(scene, kvp.Value.OwnerID))
|
||||
{
|
||||
kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
}
|
||||
|
||||
if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
|
||||
{
|
||||
if (!ResolveUserUuid(kvp.Value.CreatorID))
|
||||
kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
|
||||
kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
}
|
||||
|
||||
if (UserManager != null)
|
||||
@@ -348,10 +513,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
}
|
||||
}
|
||||
|
||||
if (m_scene.AddRestoredSceneObject(sceneObject, true, false))
|
||||
if (scene.AddRestoredSceneObject(sceneObject, true, false))
|
||||
{
|
||||
sceneObjectsLoadedCount++;
|
||||
sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0);
|
||||
sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0);
|
||||
sceneObject.ResumeScripts();
|
||||
}
|
||||
}
|
||||
@@ -366,16 +531,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
if (oldTelehubUUID != UUID.Zero)
|
||||
{
|
||||
m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
|
||||
m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
|
||||
m_scene.RegionInfo.RegionSettings.ClearSpawnPoints();
|
||||
scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
|
||||
scene.RegionInfo.RegionSettings.ClearSpawnPoints();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load serialized parcels.
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="serialisedParcels"></param>
|
||||
protected void LoadParcels(List<string> serialisedParcels)
|
||||
protected void LoadParcels(Scene scene, List<string> serialisedParcels)
|
||||
{
|
||||
// Reload serialized parcels
|
||||
m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
|
||||
@@ -386,8 +552,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
|
||||
// Validate User and Group UUID's
|
||||
|
||||
if (!ResolveUserUuid(parcel.OwnerID))
|
||||
parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
if (!ResolveUserUuid(scene, parcel.OwnerID))
|
||||
parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
|
||||
|
||||
if (!ResolveGroupUuid(parcel.GroupID))
|
||||
{
|
||||
@@ -398,7 +564,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
List<LandAccessEntry> accessList = new List<LandAccessEntry>();
|
||||
foreach (LandAccessEntry entry in parcel.ParcelAccessList)
|
||||
{
|
||||
if (ResolveUserUuid(entry.AgentID))
|
||||
if (ResolveUserUuid(scene, entry.AgentID))
|
||||
accessList.Add(entry);
|
||||
// else, drop this access rule
|
||||
}
|
||||
@@ -414,23 +580,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
if (!m_merge)
|
||||
{
|
||||
bool setupDefaultParcel = (landData.Count == 0);
|
||||
m_scene.LandChannel.Clear(setupDefaultParcel);
|
||||
scene.LandChannel.Clear(setupDefaultParcel);
|
||||
}
|
||||
|
||||
m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
|
||||
scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
|
||||
m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Look up the given user id to check whether it's one that is valid for this grid.
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="uuid"></param>
|
||||
/// <returns></returns>
|
||||
private bool ResolveUserUuid(UUID uuid)
|
||||
private bool ResolveUserUuid(Scene scene, UUID uuid)
|
||||
{
|
||||
if (!m_validUserUuids.ContainsKey(uuid))
|
||||
{
|
||||
UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
|
||||
UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid);
|
||||
m_validUserUuids.Add(uuid, account != null);
|
||||
}
|
||||
|
||||
@@ -485,7 +652,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
string extension = filename.Substring(i);
|
||||
string uuid = filename.Remove(filename.Length - extension.Length);
|
||||
|
||||
if (m_scene.AssetService.GetMetadata(uuid) != null)
|
||||
if (m_assetService.GetMetadata(uuid) != null)
|
||||
{
|
||||
// m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
|
||||
return true;
|
||||
@@ -505,7 +672,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
|
||||
// We're relying on the asset service to do the sensible thing and not store the asset if it already
|
||||
// exists.
|
||||
m_scene.AssetService.Store(asset);
|
||||
m_assetService.Store(asset);
|
||||
|
||||
/**
|
||||
* Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
|
||||
@@ -533,12 +700,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
/// <summary>
|
||||
/// Load region settings data
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="settingsPath"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="dearchivedScenes"></param>
|
||||
/// <returns>
|
||||
/// true if settings were loaded successfully, false otherwise
|
||||
/// </returns>
|
||||
private bool LoadRegionSettings(string settingsPath, byte[] data)
|
||||
private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes)
|
||||
{
|
||||
RegionSettings loadedRegionSettings;
|
||||
|
||||
@@ -554,7 +723,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
return false;
|
||||
}
|
||||
|
||||
RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings;
|
||||
RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings;
|
||||
|
||||
currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
|
||||
currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
|
||||
@@ -591,12 +760,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
|
||||
currentRegionSettings.AddSpawnPoint(sp);
|
||||
|
||||
currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime;
|
||||
currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString();
|
||||
|
||||
currentRegionSettings.Save();
|
||||
|
||||
m_scene.TriggerEstateSunUpdate();
|
||||
scene.TriggerEstateSunUpdate();
|
||||
|
||||
IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
|
||||
|
||||
IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
|
||||
if (estateModule != null)
|
||||
estateModule.sendRegionHandshakeToAll();
|
||||
|
||||
@@ -606,14 +777,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
/// <summary>
|
||||
/// Load terrain data
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="terrainPath"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns>
|
||||
/// true if terrain was resolved successfully, false otherwise.
|
||||
/// </returns>
|
||||
private bool LoadTerrain(string terrainPath, byte[] data)
|
||||
private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
|
||||
{
|
||||
ITerrainModule terrainModule = m_scene.RequestModuleInterface<ITerrainModule>();
|
||||
ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
|
||||
|
||||
MemoryStream ms = new MemoryStream(data);
|
||||
terrainModule.LoadFromStream(terrainPath, ms);
|
||||
@@ -629,17 +801,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="data"></param>
|
||||
public void LoadControlFile(string path, byte[] data)
|
||||
/// <param name="dearchivedScenes"></param>
|
||||
public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes)
|
||||
{
|
||||
XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
|
||||
XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
|
||||
XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
|
||||
|
||||
RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings;
|
||||
// Loaded metadata will be empty if no information exists in the archive
|
||||
dearchivedScenes.LoadedCreationDateTime = 0;
|
||||
dearchivedScenes.DefaultOriginalID = "";
|
||||
|
||||
// Loaded metadata will empty if no information exists in the archive
|
||||
currentRegionSettings.LoadedCreationDateTime = 0;
|
||||
currentRegionSettings.LoadedCreationID = "";
|
||||
bool multiRegion = false;
|
||||
|
||||
while (xtr.Read())
|
||||
{
|
||||
@@ -665,18 +838,44 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
int value;
|
||||
if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
|
||||
currentRegionSettings.LoadedCreationDateTime = value;
|
||||
dearchivedScenes.LoadedCreationDateTime = value;
|
||||
}
|
||||
else if (xtr.Name.ToString() == "id")
|
||||
else if (xtr.Name.ToString() == "row")
|
||||
{
|
||||
currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString();
|
||||
multiRegion = true;
|
||||
dearchivedScenes.StartRow();
|
||||
}
|
||||
else if (xtr.Name.ToString() == "region")
|
||||
{
|
||||
dearchivedScenes.StartRegion();
|
||||
}
|
||||
else if (xtr.Name.ToString() == "id")
|
||||
{
|
||||
string id = xtr.ReadElementContentAsString();
|
||||
dearchivedScenes.DefaultOriginalID = id;
|
||||
if (multiRegion)
|
||||
dearchivedScenes.SetRegionOriginalID(id);
|
||||
}
|
||||
else if (xtr.Name.ToString() == "dir")
|
||||
{
|
||||
dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentRegionSettings.Save();
|
||||
|
||||
|
||||
dearchivedScenes.MultiRegionFormat = multiRegion;
|
||||
if (!multiRegion)
|
||||
{
|
||||
// Add the single scene
|
||||
dearchivedScenes.StartRow();
|
||||
dearchivedScenes.StartRegion();
|
||||
dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
|
||||
dearchivedScenes.SetRegionDirectory("");
|
||||
}
|
||||
|
||||
ControlFileLoaded = true;
|
||||
|
||||
return dearchivedScenes;
|
||||
}
|
||||
}
|
||||
}
|
||||
176
OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
Normal file
176
OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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.Linq;
|
||||
using System.Text;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenMetaverse;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
/// <summary>
|
||||
/// A group of regions arranged in a rectangle, possibly with holes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The regions usually (but not necessarily) belong to an archive file, in which case we
|
||||
/// store additional information used to create the archive (e.g., each region's
|
||||
/// directory within the archive).
|
||||
/// </remarks>
|
||||
public class ArchiveScenesGroup
|
||||
{
|
||||
/// <summary>
|
||||
/// All the regions. The outer dictionary contains rows (key: Y coordinate).
|
||||
/// The inner dictionaries contain each row's regions (key: X coordinate).
|
||||
/// </summary>
|
||||
public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The subdirectory where each region is stored in the archive.
|
||||
/// </summary>
|
||||
protected Dictionary<UUID, string> m_regionDirs;
|
||||
|
||||
/// <summary>
|
||||
/// The grid coordinates of the regions' bounding box.
|
||||
/// </summary>
|
||||
public Rectangle Rect { get; set; }
|
||||
|
||||
|
||||
public ArchiveScenesGroup()
|
||||
{
|
||||
Regions = new SortedDictionary<uint, SortedDictionary<uint, Scene>>();
|
||||
m_regionDirs = new Dictionary<UUID, string>();
|
||||
Rect = new Rectangle(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public void AddScene(Scene scene)
|
||||
{
|
||||
uint x = scene.RegionInfo.RegionLocX;
|
||||
uint y = scene.RegionInfo.RegionLocY;
|
||||
|
||||
SortedDictionary<uint, Scene> row;
|
||||
if (!Regions.TryGetValue(y, out row))
|
||||
{
|
||||
row = new SortedDictionary<uint, Scene>();
|
||||
Regions[y] = row;
|
||||
}
|
||||
|
||||
row[x] = scene;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after all the scenes have been added. Performs calculations that require
|
||||
/// knowledge of all the scenes.
|
||||
/// </summary>
|
||||
public void CalcSceneLocations()
|
||||
{
|
||||
if (Regions.Count == 0)
|
||||
return;
|
||||
|
||||
// Find the bounding rectangle
|
||||
|
||||
uint firstY = Regions.First().Key;
|
||||
uint lastY = Regions.Last().Key;
|
||||
|
||||
uint? firstX = null;
|
||||
uint? lastX = null;
|
||||
|
||||
foreach (SortedDictionary<uint, Scene> row in Regions.Values)
|
||||
{
|
||||
uint curFirstX = row.First().Key;
|
||||
uint curLastX = row.Last().Key;
|
||||
|
||||
firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX;
|
||||
lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX;
|
||||
}
|
||||
|
||||
Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastY - firstY + 1), (int)(lastX - firstX + 1));
|
||||
|
||||
|
||||
// Calculate the subdirectory in which each region will be stored in the archive
|
||||
|
||||
m_regionDirs.Clear();
|
||||
ForEachScene(delegate(Scene scene)
|
||||
{
|
||||
// We add the region's coordinates to ensure uniqueness even if multiple regions have the same name
|
||||
string path = string.Format("{0}_{1}_{2}",
|
||||
scene.RegionInfo.RegionLocX - Rect.X + 1,
|
||||
scene.RegionInfo.RegionLocY - Rect.Y + 1,
|
||||
scene.RegionInfo.RegionName.Replace(' ', '_'));
|
||||
m_regionDirs[scene.RegionInfo.RegionID] = path;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the subdirectory where the region is stored.
|
||||
/// </summary>
|
||||
/// <param name="regionID"></param>
|
||||
/// <returns></returns>
|
||||
public string GetRegionDir(UUID regionID)
|
||||
{
|
||||
return m_regionDirs[regionID];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an action on all the scenes in this order: rows from South to North,
|
||||
/// and within each row West to East.
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
public void ForEachScene(Action<Scene> action)
|
||||
{
|
||||
foreach (SortedDictionary<uint, Scene> row in Regions.Values)
|
||||
{
|
||||
foreach (Scene scene in row.Values)
|
||||
{
|
||||
action(scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scene at position 'location'.
|
||||
/// </summary>
|
||||
/// <param name="location">A location in the grid</param>
|
||||
/// <param name="scene">The scene at this location</param>
|
||||
/// <returns>Whether the scene was found</returns>
|
||||
public bool TryGetScene(Point location, out Scene scene)
|
||||
{
|
||||
SortedDictionary<uint, Scene> row;
|
||||
if (Regions.TryGetValue((uint)location.Y, out row))
|
||||
{
|
||||
if (row.TryGetValue((uint)location.X, out scene))
|
||||
return true;
|
||||
}
|
||||
|
||||
scene = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
634
OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
Normal file
634
OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
Normal file
@@ -0,0 +1,634 @@
|
||||
/*
|
||||
* 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.IO.Compression;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Serialization;
|
||||
using OpenSim.Region.CoreModules.World.Terrain;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using Ionic.Zlib;
|
||||
using GZipStream = Ionic.Zlib.GZipStream;
|
||||
using CompressionMode = Ionic.Zlib.CompressionMode;
|
||||
using OpenSim.Framework.Serialization.External;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
/// <summary>
|
||||
/// Prepare to write out an archive.
|
||||
/// </summary>
|
||||
public class ArchiveWriteRequest
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// The minimum major version of OAR that we can write.
|
||||
/// </summary>
|
||||
public static int MIN_MAJOR_VERSION = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum major version of OAR that we can write.
|
||||
/// </summary>
|
||||
public static int MAX_MAJOR_VERSION = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Whether we're saving a multi-region archive.
|
||||
/// </summary>
|
||||
public bool MultiRegionFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether this archive will save assets. Default is true.
|
||||
/// </summary>
|
||||
public bool SaveAssets { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines which objects will be included in the archive, according to their permissions.
|
||||
/// Default is null, meaning no permission checks.
|
||||
/// </summary>
|
||||
public string CheckPermissions { get; set; }
|
||||
|
||||
protected Scene m_rootScene;
|
||||
protected Stream m_saveStream;
|
||||
protected TarArchiveWriter m_archiveWriter;
|
||||
protected Guid m_requestId;
|
||||
protected Dictionary<string, object> m_options;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="module">Calling module</param>
|
||||
/// <param name="savePath">The path to which to save data.</param>
|
||||
/// <param name="requestId">The id associated with this request</param>
|
||||
/// <exception cref="System.IO.IOException">
|
||||
/// If there was a problem opening a stream for the file specified by the savePath
|
||||
/// </exception>
|
||||
public ArchiveWriteRequest(Scene scene, string savePath, Guid requestId) : this(scene, requestId)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
|
||||
}
|
||||
catch (EntryPointNotFoundException e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
|
||||
+ "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
|
||||
m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="scene">The root scene to archive</param>
|
||||
/// <param name="saveStream">The stream to which to save data.</param>
|
||||
/// <param name="requestId">The id associated with this request</param>
|
||||
public ArchiveWriteRequest(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId)
|
||||
{
|
||||
m_saveStream = saveStream;
|
||||
}
|
||||
|
||||
protected ArchiveWriteRequest(Scene scene, Guid requestId)
|
||||
{
|
||||
m_rootScene = scene;
|
||||
m_requestId = requestId;
|
||||
m_archiveWriter = null;
|
||||
|
||||
MultiRegionFormat = false;
|
||||
SaveAssets = true;
|
||||
CheckPermissions = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Archive the region requested.
|
||||
/// </summary>
|
||||
/// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
|
||||
public void ArchiveRegion(Dictionary<string, object> options)
|
||||
{
|
||||
m_options = options;
|
||||
|
||||
if (options.ContainsKey("all") && (bool)options["all"])
|
||||
MultiRegionFormat = true;
|
||||
|
||||
if (options.ContainsKey("noassets") && (bool)options["noassets"])
|
||||
SaveAssets = false;
|
||||
|
||||
Object temp;
|
||||
if (options.TryGetValue("checkPermissions", out temp))
|
||||
CheckPermissions = (string)temp;
|
||||
|
||||
|
||||
// Find the regions to archive
|
||||
ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
|
||||
if (MultiRegionFormat)
|
||||
{
|
||||
m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count);
|
||||
SceneManager.Instance.ForEachScene(delegate(Scene scene)
|
||||
{
|
||||
scenesGroup.AddScene(scene);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
scenesGroup.AddScene(m_rootScene);
|
||||
}
|
||||
scenesGroup.CalcSceneLocations();
|
||||
|
||||
|
||||
m_archiveWriter = new TarArchiveWriter(m_saveStream);
|
||||
|
||||
try
|
||||
{
|
||||
// Write out control file. It should be first so that it will be found ASAP when loading the file.
|
||||
m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup));
|
||||
m_log.InfoFormat("[ARCHIVER]: Added control file to archive.");
|
||||
|
||||
// Archive the regions
|
||||
|
||||
Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>();
|
||||
|
||||
scenesGroup.ForEachScene(delegate(Scene scene)
|
||||
{
|
||||
string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
|
||||
ArchiveOneRegion(scene, regionDir, assetUuids);
|
||||
});
|
||||
|
||||
// Archive the assets
|
||||
|
||||
if (SaveAssets)
|
||||
{
|
||||
m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count);
|
||||
|
||||
// Asynchronously request all the assets required to perform this archive operation
|
||||
AssetsRequest ar
|
||||
= new AssetsRequest(
|
||||
new AssetsArchiver(m_archiveWriter), assetUuids,
|
||||
m_rootScene.AssetService, m_rootScene.UserAccountService,
|
||||
m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets);
|
||||
|
||||
Util.FireAndForget(o => ar.Execute());
|
||||
|
||||
// CloseArchive() will be called from ReceivedAllAssets()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
|
||||
CloseArchive(string.Empty);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
CloseArchive(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids)
|
||||
{
|
||||
m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
|
||||
|
||||
EntityBase[] entities = scene.GetEntities();
|
||||
List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
|
||||
|
||||
int numObjectsSkippedPermissions = 0;
|
||||
|
||||
// Filter entities so that we only have scene objects.
|
||||
// FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
|
||||
// end up having to do this
|
||||
IPermissionsModule permissionsModule = scene.RequestModuleInterface<IPermissionsModule>();
|
||||
foreach (EntityBase entity in entities)
|
||||
{
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
|
||||
|
||||
if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
|
||||
{
|
||||
if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule))
|
||||
{
|
||||
// The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
|
||||
++numObjectsSkippedPermissions;
|
||||
}
|
||||
else
|
||||
{
|
||||
sceneObjects.Add(sceneObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SaveAssets)
|
||||
{
|
||||
UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService);
|
||||
int prevAssets = assetUuids.Count;
|
||||
|
||||
foreach (SceneObjectGroup sceneObject in sceneObjects)
|
||||
{
|
||||
assetGatherer.GatherAssetUuids(sceneObject, assetUuids);
|
||||
}
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
|
||||
sceneObjects.Count, assetUuids.Count - prevAssets);
|
||||
}
|
||||
|
||||
if (numObjectsSkippedPermissions > 0)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
|
||||
numObjectsSkippedPermissions);
|
||||
}
|
||||
|
||||
// Make sure that we also request terrain texture assets
|
||||
RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
|
||||
|
||||
if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
|
||||
assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
|
||||
|
||||
if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
|
||||
assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
|
||||
|
||||
if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
|
||||
assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
|
||||
|
||||
if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
|
||||
assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
|
||||
|
||||
Save(scene, sceneObjects, regionDir);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the user has permission to export an object group to an OAR.
|
||||
/// </summary>
|
||||
/// <param name="user">The user</param>
|
||||
/// <param name="objGroup">The object group</param>
|
||||
/// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
|
||||
/// <param name="permissionsModule">The scene's permissions module</param>
|
||||
/// <returns>Whether the user is allowed to export the object to an OAR</returns>
|
||||
private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule)
|
||||
{
|
||||
if (checkPermissions == null)
|
||||
return true;
|
||||
|
||||
if (permissionsModule == null)
|
||||
return true; // this shouldn't happen
|
||||
|
||||
// Check whether the user is permitted to export all of the parts in the SOG. If any
|
||||
// part can't be exported then the entire SOG can't be exported.
|
||||
|
||||
bool permitted = true;
|
||||
//int primNumber = 1;
|
||||
|
||||
foreach (SceneObjectPart obj in objGroup.Parts)
|
||||
{
|
||||
uint perm;
|
||||
PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj);
|
||||
switch (permissionClass)
|
||||
{
|
||||
case PermissionClass.Owner:
|
||||
perm = obj.BaseMask;
|
||||
break;
|
||||
case PermissionClass.Group:
|
||||
perm = obj.GroupMask | obj.EveryoneMask;
|
||||
break;
|
||||
case PermissionClass.Everyone:
|
||||
default:
|
||||
perm = obj.EveryoneMask;
|
||||
break;
|
||||
}
|
||||
|
||||
bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
|
||||
bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
|
||||
|
||||
// Special case: if Everyone can copy the object then this implies it can also be
|
||||
// Transferred.
|
||||
// However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
|
||||
// always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
|
||||
// does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
|
||||
if (permissionClass != PermissionClass.Owner)
|
||||
canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
|
||||
|
||||
bool partPermitted = true;
|
||||
if (checkPermissions.Contains("C") && !canCopy)
|
||||
partPermitted = false;
|
||||
if (checkPermissions.Contains("T") && !canTransfer)
|
||||
partPermitted = false;
|
||||
|
||||
// If the user is the Creator of the object then it can always be included in the OAR
|
||||
bool creator = (obj.CreatorID.Guid == user.Guid);
|
||||
if (creator)
|
||||
partPermitted = true;
|
||||
|
||||
//string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
|
||||
//m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
|
||||
// name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
|
||||
// permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
|
||||
|
||||
if (!partPermitted)
|
||||
{
|
||||
permitted = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//++primNumber;
|
||||
}
|
||||
|
||||
return permitted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the control file.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string CreateControlFile(ArchiveScenesGroup scenesGroup)
|
||||
{
|
||||
int majorVersion;
|
||||
int minorVersion;
|
||||
|
||||
if (MultiRegionFormat)
|
||||
{
|
||||
majorVersion = MAX_MAJOR_VERSION;
|
||||
minorVersion = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// To support older versions of OpenSim, we continue to create single-region OARs
|
||||
// using the old file format. In the future this format will be discontinued.
|
||||
majorVersion = 0;
|
||||
minorVersion = 8;
|
||||
}
|
||||
//
|
||||
// if (m_options.ContainsKey("version"))
|
||||
// {
|
||||
// string[] parts = m_options["version"].ToString().Split('.');
|
||||
// if (parts.Length >= 1)
|
||||
// {
|
||||
// majorVersion = Int32.Parse(parts[0]);
|
||||
//
|
||||
// if (parts.Length >= 2)
|
||||
// minorVersion = Int32.Parse(parts[1]);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
|
||||
// {
|
||||
// throw new Exception(
|
||||
// string.Format(
|
||||
// "OAR version number for save must be between {0} and {1}",
|
||||
// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
|
||||
// }
|
||||
// else if (majorVersion == MAX_MAJOR_VERSION)
|
||||
// {
|
||||
// // Force 1.0
|
||||
// minorVersion = 0;
|
||||
// }
|
||||
// else if (majorVersion == MIN_MAJOR_VERSION)
|
||||
// {
|
||||
// // Force 0.4
|
||||
// minorVersion = 4;
|
||||
// }
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
|
||||
if (majorVersion == 1)
|
||||
{
|
||||
m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR");
|
||||
}
|
||||
|
||||
String s;
|
||||
|
||||
using (StringWriter sw = new StringWriter())
|
||||
{
|
||||
using (XmlTextWriter xtw = new XmlTextWriter(sw))
|
||||
{
|
||||
xtw.Formatting = Formatting.Indented;
|
||||
xtw.WriteStartDocument();
|
||||
xtw.WriteStartElement("archive");
|
||||
xtw.WriteAttributeString("major_version", majorVersion.ToString());
|
||||
xtw.WriteAttributeString("minor_version", minorVersion.ToString());
|
||||
|
||||
xtw.WriteStartElement("creation_info");
|
||||
DateTime now = DateTime.UtcNow;
|
||||
TimeSpan t = now - new DateTime(1970, 1, 1);
|
||||
xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
|
||||
if (!MultiRegionFormat)
|
||||
xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString());
|
||||
xtw.WriteEndElement();
|
||||
|
||||
xtw.WriteElementString("assets_included", SaveAssets.ToString());
|
||||
|
||||
if (MultiRegionFormat)
|
||||
{
|
||||
WriteRegionsManifest(scenesGroup, xtw);
|
||||
}
|
||||
else
|
||||
{
|
||||
xtw.WriteStartElement("region_info");
|
||||
WriteRegionInfo(m_rootScene, xtw);
|
||||
xtw.WriteEndElement();
|
||||
}
|
||||
|
||||
xtw.WriteEndElement();
|
||||
|
||||
xtw.Flush();
|
||||
}
|
||||
|
||||
s = sw.ToString();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the list of regions included in a multi-region OAR.
|
||||
/// </summary>
|
||||
private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw)
|
||||
{
|
||||
xtw.WriteStartElement("regions");
|
||||
|
||||
// Write the regions in order: rows from South to North, then regions from West to East.
|
||||
// The list of regions can have "holes"; we write empty elements in their position.
|
||||
|
||||
for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y)
|
||||
{
|
||||
SortedDictionary<uint, Scene> row;
|
||||
if (scenesGroup.Regions.TryGetValue(y, out row))
|
||||
{
|
||||
xtw.WriteStartElement("row");
|
||||
|
||||
for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x)
|
||||
{
|
||||
Scene scene;
|
||||
if (row.TryGetValue(x, out scene))
|
||||
{
|
||||
xtw.WriteStartElement("region");
|
||||
xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString());
|
||||
xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID));
|
||||
WriteRegionInfo(scene, xtw);
|
||||
xtw.WriteEndElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write a placeholder for a missing region
|
||||
xtw.WriteElementString("region", "");
|
||||
}
|
||||
}
|
||||
|
||||
xtw.WriteEndElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write a placeholder for a missing row
|
||||
xtw.WriteElementString("row", "");
|
||||
}
|
||||
}
|
||||
|
||||
xtw.WriteEndElement(); // "regions"
|
||||
}
|
||||
|
||||
protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw)
|
||||
{
|
||||
bool isMegaregion;
|
||||
Vector2 size;
|
||||
|
||||
IRegionCombinerModule rcMod = scene.RequestModuleInterface<IRegionCombinerModule>();
|
||||
|
||||
if (rcMod != null)
|
||||
isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID);
|
||||
else
|
||||
isMegaregion = false;
|
||||
|
||||
if (isMegaregion)
|
||||
size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
|
||||
else
|
||||
size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
|
||||
|
||||
xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
|
||||
xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
|
||||
}
|
||||
|
||||
|
||||
protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir)
|
||||
{
|
||||
if (regionDir != string.Empty)
|
||||
regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/";
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive.");
|
||||
|
||||
// Write out region settings
|
||||
string settingsPath = String.Format("{0}{1}{2}.xml",
|
||||
regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName);
|
||||
m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings));
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
|
||||
|
||||
// Write out land data (aka parcel) settings
|
||||
List<ILandObject> landObjects = scene.LandChannel.AllParcels();
|
||||
foreach (ILandObject lo in landObjects)
|
||||
{
|
||||
LandData landData = lo.LandData;
|
||||
string landDataPath = String.Format("{0}{1}{2}.xml",
|
||||
regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString());
|
||||
m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
|
||||
|
||||
// Write out terrain
|
||||
string terrainPath = String.Format("{0}{1}{2}.r32",
|
||||
regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName);
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
scene.RequestModuleInterface<ITerrainModule>().SaveToStream(terrainPath, ms);
|
||||
m_archiveWriter.WriteFile(terrainPath, ms.ToArray());
|
||||
ms.Close();
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive.");
|
||||
|
||||
// Write out scene object metadata
|
||||
IRegionSerialiserModule serializer = scene.RequestModuleInterface<IRegionSerialiserModule>();
|
||||
foreach (SceneObjectGroup sceneObject in sceneObjects)
|
||||
{
|
||||
//m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
|
||||
|
||||
string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options);
|
||||
string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
|
||||
m_archiveWriter.WriteFile(objectPath, serializedObject);
|
||||
}
|
||||
}
|
||||
|
||||
protected void ReceivedAllAssets(
|
||||
ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
|
||||
{
|
||||
foreach (UUID uuid in assetsNotFoundUuids)
|
||||
{
|
||||
m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
|
||||
}
|
||||
|
||||
// m_log.InfoFormat(
|
||||
// "[ARCHIVER]: Received {0} of {1} assets requested",
|
||||
// assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
|
||||
|
||||
CloseArchive(String.Empty);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Closes the archive and notifies that we're done.
|
||||
/// </summary>
|
||||
/// <param name="errorMessage">The error that occurred, or empty for success</param>
|
||||
protected void CloseArchive(string errorMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m_archiveWriter != null)
|
||||
m_archiveWriter.Close();
|
||||
m_saveStream.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e);
|
||||
if (errorMessage == string.Empty)
|
||||
errorMessage = e.Message;
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName);
|
||||
|
||||
m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* 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.Reflection;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Serialization;
|
||||
using OpenSim.Framework.Serialization.External;
|
||||
using OpenSim.Region.CoreModules.World.Terrain;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
/// <summary>
|
||||
/// Method called when all the necessary assets for an archive request have been received.
|
||||
/// </summary>
|
||||
public delegate void AssetsRequestCallback(
|
||||
ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids);
|
||||
|
||||
/// <summary>
|
||||
/// Execute the write of an archive once we have received all the necessary data
|
||||
/// </summary>
|
||||
public class ArchiveWriteRequestExecution
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected ITerrainModule m_terrainModule;
|
||||
protected IRegionSerialiserModule m_serialiser;
|
||||
protected List<SceneObjectGroup> m_sceneObjects;
|
||||
protected Scene m_scene;
|
||||
protected TarArchiveWriter m_archiveWriter;
|
||||
protected Guid m_requestId;
|
||||
protected Dictionary<string, object> m_options;
|
||||
|
||||
public ArchiveWriteRequestExecution(
|
||||
List<SceneObjectGroup> sceneObjects,
|
||||
ITerrainModule terrainModule,
|
||||
IRegionSerialiserModule serialiser,
|
||||
Scene scene,
|
||||
TarArchiveWriter archiveWriter,
|
||||
Guid requestId,
|
||||
Dictionary<string, object> options)
|
||||
{
|
||||
m_sceneObjects = sceneObjects;
|
||||
m_terrainModule = terrainModule;
|
||||
m_serialiser = serialiser;
|
||||
m_scene = scene;
|
||||
m_archiveWriter = archiveWriter;
|
||||
m_requestId = requestId;
|
||||
m_options = options;
|
||||
}
|
||||
|
||||
protected internal void ReceivedAllAssets(
|
||||
ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
|
||||
{
|
||||
try
|
||||
{
|
||||
Save(assetsFoundUuids, assetsNotFoundUuids);
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_archiveWriter.Close();
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName);
|
||||
|
||||
m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty);
|
||||
}
|
||||
|
||||
protected internal void Save(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
|
||||
{
|
||||
foreach (UUID uuid in assetsNotFoundUuids)
|
||||
{
|
||||
m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
|
||||
}
|
||||
|
||||
// m_log.InfoFormat(
|
||||
// "[ARCHIVER]: Received {0} of {1} assets requested",
|
||||
// assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive.");
|
||||
|
||||
// Write out region settings
|
||||
string settingsPath
|
||||
= String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName);
|
||||
m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings));
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
|
||||
|
||||
// Write out land data (aka parcel) settings
|
||||
List<ILandObject>landObjects = m_scene.LandChannel.AllParcels();
|
||||
foreach (ILandObject lo in landObjects)
|
||||
{
|
||||
LandData landData = lo.LandData;
|
||||
string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH,
|
||||
landData.GlobalID.ToString());
|
||||
m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
|
||||
|
||||
// Write out terrain
|
||||
string terrainPath
|
||||
= String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName);
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
m_terrainModule.SaveToStream(terrainPath, ms);
|
||||
m_archiveWriter.WriteFile(terrainPath, ms.ToArray());
|
||||
ms.Close();
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive.");
|
||||
|
||||
// Write out scene object metadata
|
||||
foreach (SceneObjectGroup sceneObject in m_sceneObjects)
|
||||
{
|
||||
//m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
|
||||
|
||||
string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject, m_options);
|
||||
m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,438 +0,0 @@
|
||||
/*
|
||||
* 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.IO.Compression;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Serialization;
|
||||
using OpenSim.Region.CoreModules.World.Terrain;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using Ionic.Zlib;
|
||||
using GZipStream = Ionic.Zlib.GZipStream;
|
||||
using CompressionMode = Ionic.Zlib.CompressionMode;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
/// <summary>
|
||||
/// Prepare to write out an archive.
|
||||
/// </summary>
|
||||
public class ArchiveWriteRequestPreparation
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// The minimum major version of OAR that we can write.
|
||||
/// </summary>
|
||||
public static int MIN_MAJOR_VERSION = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum major version of OAR that we can write.
|
||||
/// </summary>
|
||||
public static int MAX_MAJOR_VERSION = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether this archive will save assets. Default is true.
|
||||
/// </summary>
|
||||
public bool SaveAssets { get; set; }
|
||||
|
||||
protected ArchiverModule m_module;
|
||||
protected Scene m_scene;
|
||||
protected Stream m_saveStream;
|
||||
protected Guid m_requestId;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="module">Calling module</param>
|
||||
/// <param name="savePath">The path to which to save data.</param>
|
||||
/// <param name="requestId">The id associated with this request</param>
|
||||
/// <exception cref="System.IO.IOException">
|
||||
/// If there was a problem opening a stream for the file specified by the savePath
|
||||
/// </exception>
|
||||
public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
|
||||
}
|
||||
catch (EntryPointNotFoundException e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
|
||||
+ "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
|
||||
m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="module">Calling module</param>
|
||||
/// <param name="saveStream">The stream to which to save data.</param>
|
||||
/// <param name="requestId">The id associated with this request</param>
|
||||
public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId)
|
||||
{
|
||||
m_saveStream = saveStream;
|
||||
}
|
||||
|
||||
protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId)
|
||||
{
|
||||
m_module = module;
|
||||
|
||||
// FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
|
||||
// this.
|
||||
if (m_module != null)
|
||||
m_scene = m_module.Scene;
|
||||
|
||||
m_requestId = requestId;
|
||||
|
||||
SaveAssets = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Archive the region requested.
|
||||
/// </summary>
|
||||
/// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
|
||||
public void ArchiveRegion(Dictionary<string, object> options)
|
||||
{
|
||||
if (options.ContainsKey("noassets") && (bool)options["noassets"])
|
||||
SaveAssets = false;
|
||||
|
||||
try
|
||||
{
|
||||
Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>();
|
||||
|
||||
EntityBase[] entities = m_scene.GetEntities();
|
||||
List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
|
||||
|
||||
string checkPermissions = null;
|
||||
int numObjectsSkippedPermissions = 0;
|
||||
Object temp;
|
||||
if (options.TryGetValue("checkPermissions", out temp))
|
||||
checkPermissions = (string)temp;
|
||||
|
||||
// Filter entities so that we only have scene objects.
|
||||
// FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
|
||||
// end up having to do this
|
||||
foreach (EntityBase entity in entities)
|
||||
{
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
|
||||
|
||||
if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
|
||||
{
|
||||
if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions))
|
||||
{
|
||||
// The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
|
||||
++numObjectsSkippedPermissions;
|
||||
}
|
||||
else
|
||||
{
|
||||
sceneObjects.Add(sceneObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SaveAssets)
|
||||
{
|
||||
UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService);
|
||||
|
||||
foreach (SceneObjectGroup sceneObject in sceneObjects)
|
||||
{
|
||||
assetGatherer.GatherAssetUuids(sceneObject, assetUuids);
|
||||
}
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
|
||||
sceneObjects.Count, assetUuids.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
|
||||
}
|
||||
|
||||
if (numObjectsSkippedPermissions > 0)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
|
||||
numObjectsSkippedPermissions);
|
||||
}
|
||||
|
||||
// Make sure that we also request terrain texture assets
|
||||
RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
|
||||
|
||||
if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
|
||||
assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
|
||||
|
||||
if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
|
||||
assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
|
||||
|
||||
if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
|
||||
assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
|
||||
|
||||
if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
|
||||
assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
|
||||
|
||||
TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream);
|
||||
|
||||
// Asynchronously request all the assets required to perform this archive operation
|
||||
ArchiveWriteRequestExecution awre
|
||||
= new ArchiveWriteRequestExecution(
|
||||
sceneObjects,
|
||||
m_scene.RequestModuleInterface<ITerrainModule>(),
|
||||
m_scene.RequestModuleInterface<IRegionSerialiserModule>(),
|
||||
m_scene,
|
||||
archiveWriter,
|
||||
m_requestId,
|
||||
options);
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time.");
|
||||
|
||||
// Write out control file. This has to be done first so that subsequent loaders will see this file first
|
||||
// XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this
|
||||
archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options));
|
||||
m_log.InfoFormat("[ARCHIVER]: Added control file to archive.");
|
||||
|
||||
if (SaveAssets)
|
||||
{
|
||||
AssetsRequest ar
|
||||
= new AssetsRequest(
|
||||
new AssetsArchiver(archiveWriter), assetUuids,
|
||||
m_scene.AssetService, m_scene.UserAccountService,
|
||||
m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets);
|
||||
|
||||
Util.FireAndForget(o => ar.Execute());
|
||||
}
|
||||
else
|
||||
{
|
||||
awre.ReceivedAllAssets(new List<UUID>(), new List<UUID>());
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
m_saveStream.Close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the user has permission to export an object group to an OAR.
|
||||
/// </summary>
|
||||
/// <param name="user">The user</param>
|
||||
/// <param name="objGroup">The object group</param>
|
||||
/// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
|
||||
/// <returns>Whether the user is allowed to export the object to an OAR</returns>
|
||||
private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions)
|
||||
{
|
||||
if (checkPermissions == null)
|
||||
return true;
|
||||
|
||||
IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>();
|
||||
if (module == null)
|
||||
return true; // this shouldn't happen
|
||||
|
||||
// Check whether the user is permitted to export all of the parts in the SOG. If any
|
||||
// part can't be exported then the entire SOG can't be exported.
|
||||
|
||||
bool permitted = true;
|
||||
//int primNumber = 1;
|
||||
|
||||
foreach (SceneObjectPart obj in objGroup.Parts)
|
||||
{
|
||||
uint perm;
|
||||
PermissionClass permissionClass = module.GetPermissionClass(user, obj);
|
||||
switch (permissionClass)
|
||||
{
|
||||
case PermissionClass.Owner:
|
||||
perm = obj.BaseMask;
|
||||
break;
|
||||
case PermissionClass.Group:
|
||||
perm = obj.GroupMask | obj.EveryoneMask;
|
||||
break;
|
||||
case PermissionClass.Everyone:
|
||||
default:
|
||||
perm = obj.EveryoneMask;
|
||||
break;
|
||||
}
|
||||
|
||||
bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
|
||||
bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
|
||||
|
||||
// Special case: if Everyone can copy the object then this implies it can also be
|
||||
// Transferred.
|
||||
// However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
|
||||
// always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
|
||||
// does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
|
||||
if (permissionClass != PermissionClass.Owner)
|
||||
canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
|
||||
|
||||
bool partPermitted = true;
|
||||
if (checkPermissions.Contains("C") && !canCopy)
|
||||
partPermitted = false;
|
||||
if (checkPermissions.Contains("T") && !canTransfer)
|
||||
partPermitted = false;
|
||||
|
||||
// If the user is the Creator of the object then it can always be included in the OAR
|
||||
bool creator = (obj.CreatorID.Guid == user.Guid);
|
||||
if (creator)
|
||||
partPermitted = true;
|
||||
|
||||
//string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
|
||||
//m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
|
||||
// name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
|
||||
// permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
|
||||
|
||||
if (!partPermitted)
|
||||
{
|
||||
permitted = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//++primNumber;
|
||||
}
|
||||
|
||||
return permitted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the control file for the most up to date archive
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string CreateControlFile(Dictionary<string, object> options)
|
||||
{
|
||||
int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8;
|
||||
//
|
||||
// if (options.ContainsKey("version"))
|
||||
// {
|
||||
// string[] parts = options["version"].ToString().Split('.');
|
||||
// if (parts.Length >= 1)
|
||||
// {
|
||||
// majorVersion = Int32.Parse(parts[0]);
|
||||
//
|
||||
// if (parts.Length >= 2)
|
||||
// minorVersion = Int32.Parse(parts[1]);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
|
||||
// {
|
||||
// throw new Exception(
|
||||
// string.Format(
|
||||
// "OAR version number for save must be between {0} and {1}",
|
||||
// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
|
||||
// }
|
||||
// else if (majorVersion == MAX_MAJOR_VERSION)
|
||||
// {
|
||||
// // Force 1.0
|
||||
// minorVersion = 0;
|
||||
// }
|
||||
// else if (majorVersion == MIN_MAJOR_VERSION)
|
||||
// {
|
||||
// // Force 0.4
|
||||
// minorVersion = 4;
|
||||
// }
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
|
||||
//if (majorVersion == 1)
|
||||
//{
|
||||
// m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR");
|
||||
//}
|
||||
|
||||
String s;
|
||||
|
||||
using (StringWriter sw = new StringWriter())
|
||||
{
|
||||
using (XmlTextWriter xtw = new XmlTextWriter(sw))
|
||||
{
|
||||
xtw.Formatting = Formatting.Indented;
|
||||
xtw.WriteStartDocument();
|
||||
xtw.WriteStartElement("archive");
|
||||
xtw.WriteAttributeString("major_version", majorVersion.ToString());
|
||||
xtw.WriteAttributeString("minor_version", minorVersion.ToString());
|
||||
|
||||
xtw.WriteStartElement("creation_info");
|
||||
DateTime now = DateTime.UtcNow;
|
||||
TimeSpan t = now - new DateTime(1970, 1, 1);
|
||||
xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
|
||||
xtw.WriteElementString("id", UUID.Random().ToString());
|
||||
xtw.WriteEndElement();
|
||||
|
||||
xtw.WriteStartElement("region_info");
|
||||
|
||||
bool isMegaregion;
|
||||
Vector2 size;
|
||||
IRegionCombinerModule rcMod = null;
|
||||
|
||||
// FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
|
||||
// this, possibly by doing control file creation somewhere else.
|
||||
if (m_module != null)
|
||||
rcMod = m_module.RegionCombinerModule;
|
||||
|
||||
if (rcMod != null)
|
||||
isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID);
|
||||
else
|
||||
isMegaregion = false;
|
||||
|
||||
if (isMegaregion)
|
||||
size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
|
||||
else
|
||||
size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
|
||||
|
||||
xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
|
||||
xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
|
||||
|
||||
xtw.WriteEndElement();
|
||||
|
||||
xtw.WriteElementString("assets_included", SaveAssets.ToString());
|
||||
|
||||
xtw.WriteEndElement();
|
||||
|
||||
xtw.Flush();
|
||||
}
|
||||
|
||||
s = sw.ToString();
|
||||
}
|
||||
|
||||
// if (m_scene != null)
|
||||
// Console.WriteLine(
|
||||
// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,6 +146,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
|
||||
ops.Add("publish", v => options["wipe-owners"] = v != null);
|
||||
ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
|
||||
ops.Add("all", delegate(string v) { options["all"] = v != null; });
|
||||
|
||||
List<string> mainParams = ops.Parse(cmdparams);
|
||||
|
||||
@@ -169,7 +170,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
m_log.InfoFormat(
|
||||
"[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
|
||||
|
||||
new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options);
|
||||
new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options);
|
||||
}
|
||||
|
||||
public void ArchiveRegion(Stream saveStream)
|
||||
@@ -184,7 +185,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
|
||||
public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options)
|
||||
{
|
||||
new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options);
|
||||
new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options);
|
||||
}
|
||||
|
||||
public void DearchiveRegion(string loadPath)
|
||||
|
||||
@@ -46,6 +46,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Method called when all the necessary assets for an archive request have been received.
|
||||
/// </summary>
|
||||
public delegate void AssetsRequestCallback(
|
||||
ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids);
|
||||
|
||||
enum RequestState
|
||||
{
|
||||
Initial,
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* 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.Linq;
|
||||
using System.Text;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenMetaverse;
|
||||
using System.Drawing;
|
||||
using log4net;
|
||||
using System.Reflection;
|
||||
using OpenSim.Framework.Serialization;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
/// <summary>
|
||||
/// The regions included in an OAR file.
|
||||
/// </summary>
|
||||
public class DearchiveScenesInfo
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// One region in the archive.
|
||||
/// </summary>
|
||||
public class RegionInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The subdirectory in which the region is stored.
|
||||
/// </summary>
|
||||
public string Directory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The region's coordinates (relative to the South-West corner of the block).
|
||||
/// </summary>
|
||||
public Point Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The UUID of the original scene from which this archived region was saved.
|
||||
/// </summary>
|
||||
public string OriginalID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The scene in the current simulator into which this region is loaded.
|
||||
/// If null then the region doesn't have a corresponding scene, and it won't be loaded.
|
||||
/// </summary>
|
||||
public Scene Scene { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this archive uses the multi-region format.
|
||||
/// </summary>
|
||||
public Boolean MultiRegionFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maps (Region directory -> region)
|
||||
/// </summary>
|
||||
protected Dictionary<string, RegionInfo> m_directory2region = new Dictionary<string, RegionInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// Maps (UUID of the scene in the simulator where the region will be loaded -> region)
|
||||
/// </summary>
|
||||
protected Dictionary<UUID, RegionInfo> m_newId2region = new Dictionary<UUID, RegionInfo>();
|
||||
|
||||
public int LoadedCreationDateTime { get; set; }
|
||||
public string DefaultOriginalID { get; set; }
|
||||
|
||||
// These variables are used while reading the archive control file
|
||||
protected int? m_curY = null;
|
||||
protected int? m_curX = null;
|
||||
protected RegionInfo m_curRegion;
|
||||
|
||||
|
||||
public DearchiveScenesInfo()
|
||||
{
|
||||
MultiRegionFormat = false;
|
||||
}
|
||||
|
||||
|
||||
// The following methods are used while reading the archive control file
|
||||
|
||||
public void StartRow()
|
||||
{
|
||||
m_curY = (m_curY == null) ? 0 : m_curY + 1;
|
||||
m_curX = null;
|
||||
}
|
||||
|
||||
public void StartRegion()
|
||||
{
|
||||
m_curX = (m_curX == null) ? 0 : m_curX + 1;
|
||||
// Note: this doesn't mean we have a real region in this location; this could just be a "hole"
|
||||
}
|
||||
|
||||
public void SetRegionOriginalID(string id)
|
||||
{
|
||||
m_curRegion = new RegionInfo();
|
||||
m_curRegion.Location = new Point((int)m_curX, (int)m_curY);
|
||||
m_curRegion.OriginalID = id;
|
||||
// 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called
|
||||
}
|
||||
|
||||
public void SetRegionDirectory(string directory)
|
||||
{
|
||||
m_curRegion.Directory = directory;
|
||||
m_directory2region[directory] = m_curRegion;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets all the scenes present in the simulator.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method matches regions in the archive to scenes in the simulator according to
|
||||
/// their relative position. We only load regions if there's an existing Scene in the
|
||||
/// grid location where the region should be loaded.
|
||||
/// </remarks>
|
||||
/// <param name="rootScene">The scene where the Load OAR operation was run</param>
|
||||
/// <param name="simulatorScenes">All the scenes in the simulator</param>
|
||||
public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes)
|
||||
{
|
||||
foreach (RegionInfo archivedRegion in m_directory2region.Values)
|
||||
{
|
||||
Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY);
|
||||
location.Offset(archivedRegion.Location);
|
||||
|
||||
Scene scene;
|
||||
if (simulatorScenes.TryGetScene(location, out scene))
|
||||
{
|
||||
archivedRegion.Scene = scene;
|
||||
m_newId2region[scene.RegionInfo.RegionID] = archivedRegion;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}",
|
||||
archivedRegion.Directory, location.X, location.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the archived region according to the path of a file in the archive.
|
||||
/// Also, converts the full path into a path that is relative to the region's directory.
|
||||
/// </summary>
|
||||
/// <param name="fullPath">The path of a file in the archive</param>
|
||||
/// <param name="scene">The corresponding Scene, or null if none</param>
|
||||
/// <param name="relativePath">The path relative to the region's directory. (Or the original
|
||||
/// path, if this file doesn't belong to a region.)</param>
|
||||
/// <returns>True: use this file; False: skip it</returns>
|
||||
public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath)
|
||||
{
|
||||
scene = null;
|
||||
relativePath = fullPath;
|
||||
|
||||
if (!MultiRegionFormat)
|
||||
{
|
||||
if (m_newId2region.Count > 0)
|
||||
scene = m_newId2region.First().Value.Scene;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH))
|
||||
return true; // this file doesn't belong to a region
|
||||
|
||||
string[] parts = fullPath.Split(new Char[] { '/' }, 3);
|
||||
if (parts.Length != 3)
|
||||
return false;
|
||||
string regionDirectory = parts[1];
|
||||
relativePath = parts[2];
|
||||
|
||||
RegionInfo region;
|
||||
if (m_directory2region.TryGetValue(regionDirectory, out region))
|
||||
{
|
||||
scene = region.Scene;
|
||||
return (scene != null);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the original UUID of a region (from the simulator where the OAR was saved),
|
||||
/// given the UUID of the scene it was loaded into in the current simulator.
|
||||
/// </summary>
|
||||
/// <param name="newID"></param>
|
||||
/// <returns></returns>
|
||||
public string GetOriginalRegionID(UUID newID)
|
||||
{
|
||||
RegionInfo region;
|
||||
if (m_newId2region.TryGetValue(newID, out region))
|
||||
return region.OriginalID;
|
||||
else
|
||||
return DefaultOriginalID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scenes that have been (or will be) loaded.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<UUID> GetLoadedScenes()
|
||||
{
|
||||
return m_newId2region.Keys.ToList();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -47,32 +47,38 @@ using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants;
|
||||
using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader;
|
||||
using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter;
|
||||
using RegionSettings = OpenSim.Framework.RegionSettings;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ArchiverTests
|
||||
public class ArchiverTests : OpenSimTestCase
|
||||
{
|
||||
private Guid m_lastRequestId;
|
||||
private string m_lastErrorMessage;
|
||||
|
||||
protected SceneHelpers m_sceneHelpers;
|
||||
protected TestScene m_scene;
|
||||
protected ArchiverModule m_archiverModule;
|
||||
protected SerialiserModule m_serialiserModule;
|
||||
|
||||
protected TaskInventoryItem m_soundItem;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
new SceneManager();
|
||||
|
||||
m_archiverModule = new ArchiverModule();
|
||||
SerialiserModule serialiserModule = new SerialiserModule();
|
||||
m_serialiserModule = new SerialiserModule();
|
||||
TerrainModule terrainModule = new TerrainModule();
|
||||
|
||||
m_scene = new SceneHelpers().SetupScene();
|
||||
SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule);
|
||||
m_sceneHelpers = new SceneHelpers();
|
||||
m_scene = m_sceneHelpers.SetupScene();
|
||||
SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule);
|
||||
}
|
||||
|
||||
private void LoadCompleted(Guid requestId, string errorMessage)
|
||||
|
||||
private void LoadCompleted(Guid requestId, List<UUID> loadedScenes, string errorMessage)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
@@ -128,26 +134,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
SceneObjectPart part1 = CreateSceneObjectPart1();
|
||||
SceneObjectGroup sog1 = new SceneObjectGroup(part1);
|
||||
m_scene.AddNewSceneObject(sog1, false);
|
||||
|
||||
SceneObjectPart part2 = CreateSceneObjectPart2();
|
||||
|
||||
AssetNotecard nc = new AssetNotecard();
|
||||
nc.BodyText = "Hello World!";
|
||||
nc.Encode();
|
||||
UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
|
||||
UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
|
||||
AssetBase ncAsset
|
||||
= AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
|
||||
m_scene.AssetService.Store(ncAsset);
|
||||
SceneObjectGroup sog2 = new SceneObjectGroup(part2);
|
||||
TaskInventoryItem ncItem
|
||||
= new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
|
||||
part2.Inventory.AddInventoryItem(ncItem, true);
|
||||
|
||||
m_scene.AddNewSceneObject(sog2, false);
|
||||
SceneObjectGroup sog1;
|
||||
SceneObjectGroup sog2;
|
||||
UUID ncAssetUuid;
|
||||
CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid);
|
||||
|
||||
MemoryStream archiveWriteStream = new MemoryStream();
|
||||
m_scene.EventManager.OnOarFileSaved += SaveCompleted;
|
||||
@@ -186,7 +176,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
||||
|
||||
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
|
||||
arr.LoadControlFile(filePath, data);
|
||||
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
||||
|
||||
Assert.That(arr.ControlFileLoaded, Is.True);
|
||||
|
||||
@@ -211,6 +201,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
// TODO: Test presence of more files and contents of files.
|
||||
}
|
||||
|
||||
private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
|
||||
{
|
||||
SceneObjectPart part1 = CreateSceneObjectPart1();
|
||||
sog1 = new SceneObjectGroup(part1);
|
||||
scene.AddNewSceneObject(sog1, false);
|
||||
|
||||
AssetNotecard nc = new AssetNotecard();
|
||||
nc.BodyText = "Hello World!";
|
||||
nc.Encode();
|
||||
ncAssetUuid = UUID.Random();
|
||||
UUID ncItemUuid = UUID.Random();
|
||||
AssetBase ncAsset
|
||||
= AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
|
||||
m_scene.AssetService.Store(ncAsset);
|
||||
|
||||
TaskInventoryItem ncItem
|
||||
= new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
|
||||
SceneObjectPart part2 = CreateSceneObjectPart2();
|
||||
sog2 = new SceneObjectGroup(part2);
|
||||
part2.Inventory.AddInventoryItem(ncItem, true);
|
||||
|
||||
scene.AddNewSceneObject(sog2, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test saving an OpenSim Region Archive with the no assets option
|
||||
/// </summary>
|
||||
@@ -270,7 +284,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
||||
|
||||
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
|
||||
arr.LoadControlFile(filePath, data);
|
||||
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
||||
|
||||
Assert.That(arr.ControlFileLoaded, Is.True);
|
||||
|
||||
@@ -307,7 +321,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
|
||||
tar.WriteFile(
|
||||
ArchiveConstants.CONTROL_FILE_PATH,
|
||||
new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
|
||||
new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
|
||||
|
||||
SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
|
||||
SceneObjectPart sop2
|
||||
@@ -362,11 +376,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
// Also check that direct entries which will also have a file entry containing that directory doesn't
|
||||
// upset load
|
||||
tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
|
||||
|
||||
|
||||
tar.WriteFile(
|
||||
ArchiveConstants.CONTROL_FILE_PATH,
|
||||
new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
|
||||
|
||||
new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
|
||||
SceneObjectPart part1 = CreateSceneObjectPart1();
|
||||
|
||||
part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
|
||||
@@ -389,31 +402,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
Assert.That(soundDataResourceName, Is.Not.Null);
|
||||
|
||||
byte[] soundData;
|
||||
Console.WriteLine("Loading " + soundDataResourceName);
|
||||
using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(resource))
|
||||
{
|
||||
// FIXME: Use the inspector instead
|
||||
soundData = br.ReadBytes(99999999);
|
||||
UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
|
||||
string soundAssetFileName
|
||||
= ArchiveConstants.ASSETS_PATH + soundUuid
|
||||
+ ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
|
||||
tar.WriteFile(soundAssetFileName, soundData);
|
||||
|
||||
/*
|
||||
AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
|
||||
scene.AssetService.Store(soundAsset);
|
||||
asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
|
||||
*/
|
||||
|
||||
TaskInventoryItem item1
|
||||
= new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
|
||||
part1.Inventory.AddInventoryItem(item1, true);
|
||||
}
|
||||
}
|
||||
|
||||
UUID soundUuid;
|
||||
CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
|
||||
|
||||
TaskInventoryItem item1
|
||||
= new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
|
||||
part1.Inventory.AddInventoryItem(item1, true);
|
||||
m_scene.AddNewSceneObject(object1, false);
|
||||
|
||||
string object1FileName = string.Format(
|
||||
@@ -435,6 +429,34 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
|
||||
Assert.That(m_lastErrorMessage, Is.Null);
|
||||
|
||||
TestLoadedRegion(part1, soundItemName, soundData);
|
||||
}
|
||||
|
||||
private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid)
|
||||
{
|
||||
using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(resource))
|
||||
{
|
||||
// FIXME: Use the inspector instead
|
||||
soundData = br.ReadBytes(99999999);
|
||||
soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
|
||||
string soundAssetFileName
|
||||
= ArchiveConstants.ASSETS_PATH + soundUuid
|
||||
+ ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
|
||||
tar.WriteFile(soundAssetFileName, soundData);
|
||||
|
||||
/*
|
||||
AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
|
||||
scene.AssetService.Store(soundAsset);
|
||||
asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
|
||||
{
|
||||
SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
|
||||
|
||||
Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
|
||||
@@ -454,9 +476,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
|
||||
|
||||
Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
|
||||
|
||||
// Temporary
|
||||
Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -516,7 +535,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
SerialiserModule serialiserModule = new SerialiserModule();
|
||||
TerrainModule terrainModule = new TerrainModule();
|
||||
|
||||
TestScene scene2 = new SceneHelpers().SetupScene();
|
||||
m_sceneHelpers = new SceneHelpers();
|
||||
TestScene scene2 = m_sceneHelpers.SetupScene();
|
||||
SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
|
||||
|
||||
// Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
|
||||
@@ -554,7 +574,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
|
||||
tar.WriteFile(
|
||||
ArchiveConstants.CONTROL_FILE_PATH,
|
||||
new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
|
||||
new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
|
||||
|
||||
RegionSettings rs = new RegionSettings();
|
||||
rs.AgentLimit = 17;
|
||||
@@ -664,7 +684,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
SerialiserModule serialiserModule = new SerialiserModule();
|
||||
TerrainModule terrainModule = new TerrainModule();
|
||||
|
||||
Scene scene = new SceneHelpers().SetupScene();
|
||||
Scene scene = m_sceneHelpers.SetupScene();
|
||||
SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
|
||||
|
||||
m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
|
||||
@@ -700,5 +720,258 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test saving a multi-region OAR.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSaveMultiRegionOar()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
// Create test regions
|
||||
|
||||
int WIDTH = 2;
|
||||
int HEIGHT = 2;
|
||||
|
||||
List<Scene> scenes = new List<Scene>();
|
||||
|
||||
// Maps (Directory in OAR file -> scene)
|
||||
Dictionary<string, Scene> regionPaths = new Dictionary<string, Scene>();
|
||||
|
||||
// Maps (Scene -> expected object paths)
|
||||
Dictionary<UUID, List<string>> expectedPaths = new Dictionary<UUID, List<string>>();
|
||||
|
||||
// List of expected assets
|
||||
List<UUID> expectedAssets = new List<UUID>();
|
||||
|
||||
for (uint y = 0; y < HEIGHT; y++)
|
||||
{
|
||||
for (uint x = 0; x < WIDTH; x++)
|
||||
{
|
||||
Scene scene;
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
scene = m_scene; // this scene was already created in SetUp()
|
||||
}
|
||||
else
|
||||
{
|
||||
scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
|
||||
SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
|
||||
}
|
||||
scenes.Add(scene);
|
||||
|
||||
string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_"));
|
||||
regionPaths[dir] = scene;
|
||||
|
||||
SceneObjectGroup sog1;
|
||||
SceneObjectGroup sog2;
|
||||
UUID ncAssetUuid;
|
||||
|
||||
CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid);
|
||||
|
||||
expectedPaths[scene.RegionInfo.RegionID] = new List<string>();
|
||||
expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1));
|
||||
expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2));
|
||||
|
||||
expectedAssets.Add(ncAssetUuid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Save OAR
|
||||
|
||||
MemoryStream archiveWriteStream = new MemoryStream();
|
||||
m_scene.EventManager.OnOarFileSaved += SaveCompleted;
|
||||
|
||||
Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
|
||||
|
||||
Dictionary<string, Object> options = new Dictionary<string, Object>();
|
||||
options.Add("all", true);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
|
||||
Monitor.Wait(this, 60000);
|
||||
}
|
||||
|
||||
|
||||
// Check that the OAR contains the expected data
|
||||
|
||||
Assert.That(m_lastRequestId, Is.EqualTo(requestId));
|
||||
|
||||
byte[] archive = archiveWriteStream.ToArray();
|
||||
MemoryStream archiveReadStream = new MemoryStream(archive);
|
||||
TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
|
||||
|
||||
Dictionary<UUID, List<string>> foundPaths = new Dictionary<UUID, List<string>>();
|
||||
List<UUID> foundAssets = new List<UUID>();
|
||||
|
||||
foreach (Scene scene in scenes)
|
||||
{
|
||||
foundPaths[scene.RegionInfo.RegionID] = new List<string>();
|
||||
}
|
||||
|
||||
string filePath;
|
||||
TarArchiveReader.TarEntryType tarEntryType;
|
||||
|
||||
byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
|
||||
Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
|
||||
|
||||
ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
|
||||
arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
|
||||
|
||||
Assert.That(arr.ControlFileLoaded, Is.True);
|
||||
|
||||
while (tar.ReadEntry(out filePath, out tarEntryType) != null)
|
||||
{
|
||||
if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
|
||||
{
|
||||
// Assets are shared, so this file doesn't belong to any specific region.
|
||||
string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
|
||||
if (fileName.EndsWith("_notecard.txt"))
|
||||
foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// This file belongs to one of the regions. Find out which one.
|
||||
Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH));
|
||||
string[] parts = filePath.Split(new Char[] { '/' }, 3);
|
||||
Assert.AreEqual(3, parts.Length);
|
||||
string regionDirectory = parts[1];
|
||||
string relativePath = parts[2];
|
||||
Scene scene = regionPaths[regionDirectory];
|
||||
|
||||
if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
|
||||
{
|
||||
foundPaths[scene.RegionInfo.RegionID].Add(relativePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.AreEqual(scenes.Count, foundPaths.Count);
|
||||
foreach (Scene scene in scenes)
|
||||
{
|
||||
Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID]));
|
||||
}
|
||||
|
||||
Assert.That(foundAssets, Is.EquivalentTo(expectedAssets));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test loading a multi-region OAR.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestLoadMultiRegionOar()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
// Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file.
|
||||
|
||||
int WIDTH = 2;
|
||||
int HEIGHT = 2;
|
||||
|
||||
for (uint y = 0; y < HEIGHT; y++)
|
||||
{
|
||||
for (uint x = 0; x < WIDTH; x++)
|
||||
{
|
||||
Scene scene;
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
scene = m_scene; // this scene was already created in SetUp()
|
||||
}
|
||||
else
|
||||
{
|
||||
scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
|
||||
SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
|
||||
SceneManager.Instance.ForEachScene(delegate(Scene scene)
|
||||
{
|
||||
scenesGroup.AddScene(scene);
|
||||
});
|
||||
scenesGroup.CalcSceneLocations();
|
||||
|
||||
// Generate the OAR file
|
||||
|
||||
MemoryStream archiveWriteStream = new MemoryStream();
|
||||
TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
|
||||
|
||||
ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty);
|
||||
writeRequest.MultiRegionFormat = true;
|
||||
tar.WriteFile(
|
||||
ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup));
|
||||
|
||||
SceneObjectPart part1 = CreateSceneObjectPart1();
|
||||
part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
|
||||
part1.SitTargetPosition = new Vector3(1, 2, 3);
|
||||
|
||||
SceneObjectGroup object1 = new SceneObjectGroup(part1);
|
||||
|
||||
// Let's put some inventory items into our object
|
||||
string soundItemName = "sound-item1";
|
||||
UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
|
||||
Type type = GetType();
|
||||
Assembly assembly = type.Assembly;
|
||||
string soundDataResourceName = null;
|
||||
string[] names = assembly.GetManifestResourceNames();
|
||||
foreach (string name in names)
|
||||
{
|
||||
if (name.EndsWith(".Resources.test-sound.wav"))
|
||||
soundDataResourceName = name;
|
||||
}
|
||||
Assert.That(soundDataResourceName, Is.Not.Null);
|
||||
|
||||
byte[] soundData;
|
||||
UUID soundUuid;
|
||||
CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
|
||||
|
||||
TaskInventoryItem item1
|
||||
= new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
|
||||
part1.Inventory.AddInventoryItem(item1, true);
|
||||
m_scene.AddNewSceneObject(object1, false);
|
||||
|
||||
string object1FileName = string.Format(
|
||||
"{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
|
||||
part1.Name,
|
||||
Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
|
||||
part1.UUID);
|
||||
string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName;
|
||||
tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1));
|
||||
|
||||
tar.Close();
|
||||
|
||||
|
||||
// Delete the current objects, to test that they're loaded from the OAR and didn't
|
||||
// just remain in the scene.
|
||||
SceneManager.Instance.ForEachScene(delegate(Scene scene)
|
||||
{
|
||||
scene.DeleteAllSceneObjects();
|
||||
});
|
||||
|
||||
// Create a "hole", to test that that the corresponding region isn't loaded from the OAR
|
||||
SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]);
|
||||
|
||||
|
||||
// Check thay the OAR file contains the expected data
|
||||
|
||||
MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
|
||||
|
||||
lock (this)
|
||||
{
|
||||
m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
|
||||
m_archiverModule.DearchiveRegion(archiveReadStream);
|
||||
}
|
||||
|
||||
Assert.That(m_lastErrorMessage, Is.Null);
|
||||
|
||||
Assert.AreEqual(3, SceneManager.Instance.Scenes.Count);
|
||||
|
||||
TestLoadedRegion(part1, soundItemName, soundData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||
/// without recounting the whole sim.
|
||||
///
|
||||
/// We start out tainted so that the first get call resets the various prim counts.
|
||||
/// <value>
|
||||
/// </value>
|
||||
private bool m_Tainted = true;
|
||||
|
||||
private Object m_TaintLock = new Object();
|
||||
|
||||
@@ -208,6 +208,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
|
||||
}
|
||||
|
||||
// XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
|
||||
// afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
|
||||
// then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
|
||||
// this map tile simply takes a lot of memory.
|
||||
GC.Collect();
|
||||
m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using OpenMetaverse;
|
||||
|
||||
@@ -33,7 +35,14 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
public interface IDynamicTextureManager
|
||||
{
|
||||
void RegisterRender(string handleType, IDynamicTextureRender render);
|
||||
void ReturnData(UUID id, byte[] data, bool isReuseable);
|
||||
|
||||
/// <summary>
|
||||
/// Used by IDynamicTextureRender implementations to return renders
|
||||
/// </summary>
|
||||
/// <param name='id'></param>
|
||||
/// <param name='data'></param>
|
||||
/// <param name='isReuseable'></param>
|
||||
void ReturnData(UUID id, IDynamicTexture texture);
|
||||
|
||||
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
|
||||
int updateTimer);
|
||||
@@ -125,11 +134,53 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
// /// <param name='extraParams'></param>
|
||||
// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
|
||||
|
||||
byte[] ConvertUrl(string url, string extraParams);
|
||||
byte[] ConvertData(string bodyData, string extraParams);
|
||||
IDynamicTexture ConvertUrl(string url, string extraParams);
|
||||
IDynamicTexture ConvertData(string bodyData, string extraParams);
|
||||
|
||||
bool AsyncConvertUrl(UUID id, string url, string extraParams);
|
||||
bool AsyncConvertData(UUID id, string bodyData, string extraParams);
|
||||
|
||||
void GetDrawStringSize(string text, string fontName, int fontSize,
|
||||
out double xSize, out double ySize);
|
||||
}
|
||||
|
||||
public interface IDynamicTexture
|
||||
{
|
||||
/// <summary>
|
||||
/// Input commands used to generate this data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Null if input commands were not used.
|
||||
/// </remarks>
|
||||
string InputCommands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Uri used to generate this data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Null if a uri was not used.
|
||||
/// </remarks>
|
||||
Uri InputUri { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Extra input params used to generate this data.
|
||||
/// </summary>
|
||||
string InputParams { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Texture data.
|
||||
/// </summary>
|
||||
byte[] Data { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of texture.
|
||||
/// </summary>
|
||||
Size Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same
|
||||
/// texture).
|
||||
/// </summary>
|
||||
bool IsReuseable { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,11 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// </summary>
|
||||
void sendRegionHandshakeToAll();
|
||||
|
||||
/// <summary>
|
||||
/// Fires the OnRegionInfoChange event.
|
||||
/// </summary>
|
||||
void TriggerRegionInfoChange();
|
||||
|
||||
void setEstateTerrainBaseTexture(int level, UUID texture);
|
||||
void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
|
||||
public interface IJsonStoreModule
|
||||
{
|
||||
bool CreateStore(string value, out UUID result);
|
||||
bool CreateStore(string value, ref UUID result);
|
||||
bool DestroyStore(UUID storeID);
|
||||
bool TestPath(UUID storeID, string path, bool useJson);
|
||||
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
||||
|
||||
@@ -47,26 +47,71 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public delegate void OnFrameDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered on each sim frame.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Update"/>
|
||||
/// Core uses it for things like Sun, Wind & Clouds
|
||||
/// The MRM module also uses it.
|
||||
/// </remarks>
|
||||
public event OnFrameDelegate OnFrame;
|
||||
|
||||
public delegate void ClientMovement(ScenePresence client);
|
||||
|
||||
/// <summary>
|
||||
/// Trigerred when an agent moves.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.HandleAgentUpdate"/>
|
||||
/// prior to <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.TriggerScenePresenceUpdated"/>
|
||||
/// </remarks>
|
||||
public event ClientMovement OnClientMovement;
|
||||
|
||||
public delegate void OnTerrainTaintedDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered if the terrain has been edited
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.CoreModules.World.Terrain.CheckForTerrainUpdates"/>
|
||||
/// after it determines that an update has been made.
|
||||
/// </remarks>
|
||||
public event OnTerrainTaintedDelegate OnTerrainTainted;
|
||||
|
||||
public delegate void OnTerrainTickDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered if the terrain has been edited
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.UpdateTerrain"/>
|
||||
/// but is used by core solely to update the physics engine.
|
||||
/// </remarks>
|
||||
public event OnTerrainTickDelegate OnTerrainTick;
|
||||
|
||||
public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a region is backed up/persisted to storage
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Backup"/>
|
||||
/// and is fired before the persistence occurs.
|
||||
/// </remarks>
|
||||
public event OnBackupDelegate OnBackup;
|
||||
|
||||
public delegate void OnClientConnectCoreDelegate(IClientCore client);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a new client connects to the scene.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="TriggerOnNewClient"/>,
|
||||
/// which checks if an instance of <see cref="OpenSim.Framework.IClientAPI"/>
|
||||
/// also implements <see cref="OpenSim.Framework.Client.IClientCore"/> and as such,
|
||||
/// is not triggered by <see cref="OpenSim.Region.OptionalModules.World.NPC">NPCs</see>.
|
||||
/// </remarks>
|
||||
public event OnClientConnectCoreDelegate OnClientConnect;
|
||||
|
||||
public delegate void OnNewClientDelegate(IClientAPI client);
|
||||
@@ -87,18 +132,54 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public delegate void OnNewPresenceDelegate(ScenePresence presence);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a new presence is added to the scene
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
|
||||
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
|
||||
/// </remarks>
|
||||
public event OnNewPresenceDelegate OnNewPresence;
|
||||
|
||||
public delegate void OnRemovePresenceDelegate(UUID agentId);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a presence is removed from the scene
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
|
||||
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
|
||||
/// </remarks>
|
||||
public event OnRemovePresenceDelegate OnRemovePresence;
|
||||
|
||||
public delegate void OnParcelPrimCountUpdateDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered whenever the prim count may have been altered, or prior
|
||||
/// to an action that requires the current prim count to be accurate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerParcelPrimCountUpdate"/> in
|
||||
/// <see cref="OpenSim.OpenSimBase.CreateRegion"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnRequestParcelPrimCountUpdate"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelObjectOwnerRequest"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.GetPrimsFree"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.UpdateLandSold"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.DeedToGroup"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.SendLandUpdateToClient"/>
|
||||
/// </remarks>
|
||||
public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate;
|
||||
|
||||
public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered in response to <see cref="OnParcelPrimCountUpdate"/> for
|
||||
/// objects that actually contribute to parcel prim count.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerParcelPrimCountAdd"/> in
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnParcelPrimCountUpdate"/>
|
||||
/// </remarks>
|
||||
public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd;
|
||||
|
||||
public delegate void OnPluginConsoleDelegate(string[] args);
|
||||
@@ -119,6 +200,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public event OnSetRootAgentSceneDelegate OnSetRootAgentScene;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after parcel properties have been updated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerOnParcelPropertiesUpdateRequest"/> in
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelPropertiesUpdateRequest"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ProcessPropertiesUpdate"/>
|
||||
/// </remarks>
|
||||
public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
|
||||
|
||||
/// <summary>
|
||||
@@ -369,6 +458,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate;
|
||||
|
||||
public delegate void ParcelPrimCountTainted();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the parcel prim count has been altered.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerParcelPrimCountTainted"/> in
|
||||
/// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.DetachSingleAttachmentToGround"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.AttachToAgent"/>,
|
||||
/// <see cref="Scene.DeleteSceneObject"/>,
|
||||
/// <see cref="Scene.SelectPrim"/>,
|
||||
/// <see cref="Scene.DeselectPrim"/>,
|
||||
/// <see cref="SceneObjectGroup.UpdatePrimFlags"/>,
|
||||
/// <see cref="SceneObjectGroup.AbsolutePosition"/>
|
||||
/// </remarks>
|
||||
public event ParcelPrimCountTainted OnParcelPrimCountTainted;
|
||||
public event GetScriptRunning OnGetScriptRunning;
|
||||
|
||||
@@ -428,7 +531,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// the scripts may not have started yet
|
||||
/// Message is non empty string if there were problems loading the oar file
|
||||
/// </summary>
|
||||
public delegate void OarFileLoaded(Guid guid, string message);
|
||||
public delegate void OarFileLoaded(Guid guid, List<UUID> loadedScenes, string message);
|
||||
public event OarFileLoaded OnOarFileLoaded;
|
||||
|
||||
/// <summary>
|
||||
@@ -481,6 +584,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <param name="copy"></param>
|
||||
/// <param name="original"></param>
|
||||
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.SceneObjectPart.Copy"/>
|
||||
/// </remarks>
|
||||
public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
|
||||
public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
|
||||
|
||||
@@ -589,8 +695,29 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public delegate void LandBuy(Object sender, LandBuyArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an attempt to transfer grid currency occurs
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
|
||||
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
|
||||
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
|
||||
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/>
|
||||
/// </remarks>
|
||||
public event MoneyTransferEvent OnMoneyTransfer;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after after <see cref="OnValidateLandBuy"/>
|
||||
/// </summary>
|
||||
public event LandBuy OnLandBuy;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered to allow or prevent a real estate transaction
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessParcelBuy"/>
|
||||
/// <seealso cref="OpenSim.Region.OptionalModules.World.MoneyModule.SampleMoneyModule.ValidateLandBuy"/>
|
||||
/// </remarks>
|
||||
public event LandBuy OnValidateLandBuy;
|
||||
|
||||
public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
|
||||
@@ -2068,7 +2195,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return 6;
|
||||
}
|
||||
|
||||
public void TriggerOarFileLoaded(Guid requestId, string message)
|
||||
public void TriggerOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message)
|
||||
{
|
||||
OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded;
|
||||
if (handlerOarFileLoaded != null)
|
||||
@@ -2077,7 +2204,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
try
|
||||
{
|
||||
d(requestId, message);
|
||||
d(requestId, loadedScenes, message);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -123,6 +123,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </summary>
|
||||
public float m_maxPhys = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Max prims an object will hold
|
||||
/// </summary>
|
||||
public int m_linksetCapacity = 0;
|
||||
|
||||
public bool m_clampPrimSize;
|
||||
public bool m_trustBinaries;
|
||||
public bool m_allowScriptCrossings;
|
||||
@@ -772,6 +777,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
m_clampPrimSize = true;
|
||||
}
|
||||
|
||||
m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
|
||||
if (RegionInfo.LinksetCapacity > 0)
|
||||
{
|
||||
m_linksetCapacity = RegionInfo.LinksetCapacity;
|
||||
}
|
||||
|
||||
m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete);
|
||||
m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
|
||||
m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
|
||||
@@ -4334,6 +4345,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return LandChannel.GetLandObject(x, y).LandData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get LandData by position.
|
||||
/// </summary>
|
||||
/// <param name="pos"></param>
|
||||
/// <returns></returns>
|
||||
public LandData GetLandData(Vector3 pos)
|
||||
{
|
||||
return GetLandData(pos.X, pos.Y);
|
||||
}
|
||||
|
||||
public LandData GetLandData(uint x, uint y)
|
||||
{
|
||||
m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
|
||||
@@ -4581,6 +4602,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return m_sceneGraph.GetSceneObjectGroup(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get the SOG via its UUID
|
||||
/// </summary>
|
||||
/// <param name="fullID"></param>
|
||||
/// <param name="sog"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
|
||||
{
|
||||
sog = GetSceneObjectGroup(fullID);
|
||||
return sog != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a prim by name from the scene (will return the first
|
||||
/// found, if there are more than one prim with the same name)
|
||||
@@ -4612,6 +4645,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return m_sceneGraph.GetSceneObjectPart(fullID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get a prim via its UUID
|
||||
/// </summary>
|
||||
/// <param name="fullID"></param>
|
||||
/// <param name="sop"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
|
||||
{
|
||||
sop = GetSceneObjectPart(fullID);
|
||||
return sop != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a scene object group that contains the prim with the given local id
|
||||
/// </summary>
|
||||
|
||||
@@ -92,7 +92,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
private static SceneManager m_instance = null;
|
||||
public static SceneManager Instance
|
||||
{
|
||||
get { return m_instance; }
|
||||
get {
|
||||
if (m_instance == null)
|
||||
m_instance = new SceneManager();
|
||||
return m_instance;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Scene> m_localScenes = new List<Scene>();
|
||||
|
||||
@@ -2014,6 +2014,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
if (objectGroup == this)
|
||||
return;
|
||||
|
||||
// If the configured linkset capacity is greater than zero,
|
||||
// and the new linkset would have a prim count higher than this
|
||||
// value, do not link it.
|
||||
if (m_scene.m_linksetCapacity > 0 &&
|
||||
(PrimCount + objectGroup.PrimCount) >
|
||||
m_scene.m_linksetCapacity)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[SCENE OBJECT GROUP]: Cannot link group with root" +
|
||||
" part {0}, {1} ({2} prims) to group with root part" +
|
||||
" {3}, {4} ({5} prims) because the new linkset" +
|
||||
" would exceed the configured maximum of {6}",
|
||||
objectGroup.RootPart.Name, objectGroup.RootPart.UUID,
|
||||
objectGroup.PrimCount, RootPart.Name, RootPart.UUID,
|
||||
PrimCount, m_scene.m_linksetCapacity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 'linkPart' == the root of the group being linked into this group
|
||||
SceneObjectPart linkPart = objectGroup.m_rootPart;
|
||||
|
||||
|
||||
@@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||
// settings allow voice, then whether parcel allows
|
||||
// voice, if all do retrieve or obtain the parcel
|
||||
// voice channel
|
||||
LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
|
||||
LandData land = scene.GetLandData(avatar.AbsolutePosition);
|
||||
|
||||
//m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
|
||||
// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
|
||||
|
||||
@@ -623,7 +623,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
|
||||
// settings allow voice, then whether parcel allows
|
||||
// voice, if all do retrieve or obtain the parcel
|
||||
// voice channel
|
||||
LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
|
||||
LandData land = scene.GetLandData(avatar.AbsolutePosition);
|
||||
|
||||
m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
|
||||
scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
|
||||
|
||||
@@ -175,14 +175,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
public bool CreateStore(string value, out UUID result)
|
||||
public bool CreateStore(string value, ref UUID result)
|
||||
{
|
||||
result = UUID.Zero;
|
||||
if (result == UUID.Zero)
|
||||
result = UUID.Random();
|
||||
|
||||
JsonStore map = null;
|
||||
|
||||
if (! m_enabled) return false;
|
||||
|
||||
UUID uuid = UUID.Random();
|
||||
JsonStore map = null;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -195,9 +196,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
}
|
||||
|
||||
lock (m_JsonValueStore)
|
||||
m_JsonValueStore.Add(uuid,map);
|
||||
m_JsonValueStore.Add(result,map);
|
||||
|
||||
result = uuid;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||
{
|
||||
m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
|
||||
{
|
||||
UUID uuid = UUID.Zero;
|
||||
if (! m_store.CreateStore(value, out uuid))
|
||||
if (! m_store.CreateStore(value, ref uuid))
|
||||
GenerateRuntimeError("Failed to create Json store");
|
||||
|
||||
return uuid;
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
|
||||
}
|
||||
}
|
||||
|
||||
void OnOarFileLoaded(Guid requestId, string message)
|
||||
void OnOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message)
|
||||
{
|
||||
m_oarFileLoading = true;
|
||||
|
||||
|
||||
@@ -73,7 +73,8 @@ public class BSCharacter : BSPhysObject
|
||||
private bool _kinematic;
|
||||
private float _buoyancy;
|
||||
|
||||
public override BulletBody Body { get; set; }
|
||||
public override BulletBody BSBody { get; set; }
|
||||
public override BulletShape BSShape { get; set; }
|
||||
public override BSLinkset Linkset { get; set; }
|
||||
|
||||
private int _subscribedEventsMs = 0;
|
||||
@@ -92,6 +93,7 @@ public class BSCharacter : BSPhysObject
|
||||
_localID = localID;
|
||||
_avName = avName;
|
||||
Scene = parent_scene;
|
||||
_physicsActorType = (int)ActorTypes.Agent;
|
||||
_position = pos;
|
||||
_size = size;
|
||||
_flying = isFlying;
|
||||
@@ -128,9 +130,9 @@ public class BSCharacter : BSPhysObject
|
||||
// Set the buoyancy for flying. This will be refactored when all the settings happen in C#
|
||||
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
|
||||
BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
|
||||
// avatars get all collisions no matter what (makes walking on ground and such work)
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -440,7 +442,7 @@ public class BSCharacter : BSPhysObject
|
||||
Scene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
||||
BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
|
||||
BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -465,7 +467,7 @@ public class BSCharacter : BSPhysObject
|
||||
|
||||
Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
|
||||
{
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,10 @@ public abstract class BSConstraint : IDisposable
|
||||
{
|
||||
// m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}",
|
||||
// BSScene.DetailLogZero, Body1.ID, Body2.ID);
|
||||
|
||||
// Setting an object's mass to zero (making it static like when it's selected)
|
||||
// automatically disables the constraints.
|
||||
// If enabled, be sure to set the constraint itself to enabled.
|
||||
BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -233,7 +233,7 @@ public class BSLinkset
|
||||
foreach (BSPhysObject child in m_children)
|
||||
{
|
||||
BSConstraint constrain;
|
||||
if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
|
||||
if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
|
||||
{
|
||||
// DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
|
||||
// LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
|
||||
@@ -245,8 +245,8 @@ public class BSLinkset
|
||||
// their constraints have not been created yet.
|
||||
// Caused by the fact that m_children is built at run time but building constraints
|
||||
// happens at taint time.
|
||||
// m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}",
|
||||
// m_linksetRoot.Body.ID, child.Body.ID);
|
||||
// m_physicsScene.Logger.ErrorFormat("{0} RecomputeLinksetConstraintVariables: constraint not found for root={1}, child={2}",
|
||||
// LogHeader, m_linksetRoot.Body.ID, child.Body.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,7 +327,7 @@ public class BSLinkset
|
||||
DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
|
||||
rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
|
||||
BS6DofConstraint constrain = new BS6DofConstraint(
|
||||
m_physicsScene.World, rootPrim.Body, childPrim.Body,
|
||||
m_physicsScene.World, rootPrim.BSBody, childPrim.BSBody,
|
||||
midPoint,
|
||||
true,
|
||||
true
|
||||
@@ -388,10 +388,10 @@ public class BSLinkset
|
||||
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
||||
|
||||
// Find the constraint for this link and get rid of it from the overall collection and from my list
|
||||
m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
|
||||
m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody);
|
||||
|
||||
// Make the child refresh its location
|
||||
BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
|
||||
BulletSimAPI.PushUpdate2(childPrim.BSBody.Ptr);
|
||||
}
|
||||
|
||||
// Remove linkage between myself and any possible children I might have
|
||||
@@ -400,7 +400,7 @@ public class BSLinkset
|
||||
{
|
||||
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
||||
|
||||
m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
|
||||
m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody);
|
||||
}
|
||||
|
||||
// Invoke the detailed logger and output something if it's enabled.
|
||||
|
||||
@@ -48,7 +48,11 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
// Return the object mass without calculating it or side effects
|
||||
public abstract float MassRaw { get; }
|
||||
|
||||
public abstract BulletBody Body { get; set; }
|
||||
// Reference to the physical body (btCollisionObject) of this object
|
||||
public abstract BulletBody BSBody { get; set; }
|
||||
// Reference to the physical shape (btCollisionShape) of this object
|
||||
public abstract BulletShape BSShape { get; set; }
|
||||
|
||||
public abstract void ZeroMotion();
|
||||
|
||||
public virtual void StepVehicle(float timeStep) { }
|
||||
|
||||
@@ -94,8 +94,10 @@ public sealed class BSPrim : BSPhysObject
|
||||
private int _nextCollisionOkTime = 0;
|
||||
long _collidingStep;
|
||||
long _collidingGroundStep;
|
||||
CollisionFlags m_currentCollisionFlags = 0;
|
||||
|
||||
public override BulletBody Body { get; set; }
|
||||
public override BulletBody BSBody { get; set; }
|
||||
public override BulletShape BSShape { get; set; }
|
||||
|
||||
private BSDynamics _vehicle;
|
||||
|
||||
@@ -113,6 +115,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
// m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
|
||||
_localID = localID;
|
||||
_avName = primName;
|
||||
_physicsActorType = (int)ActorTypes.Prim;
|
||||
_scene = parent_scene;
|
||||
_position = pos;
|
||||
_size = size;
|
||||
@@ -142,7 +145,9 @@ public sealed class BSPrim : BSPhysObject
|
||||
// Get the pointer to the physical body for this object.
|
||||
// At the moment, we're still letting BulletSim manage the creation and destruction
|
||||
// of the object. Someday we'll move that into the C# code.
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
|
||||
m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -258,10 +263,10 @@ public sealed class BSPrim : BSPhysObject
|
||||
_rotationalVelocity = OMV.Vector3.Zero;
|
||||
|
||||
// Zero some other properties directly into the physics engine
|
||||
BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
BulletSimAPI.ClearForces2(Body.Ptr);
|
||||
BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
BulletSimAPI.ClearForces2(BSBody.Ptr);
|
||||
}
|
||||
|
||||
public override void LockAngularMotion(OMV.Vector3 axis)
|
||||
@@ -324,7 +329,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
|
||||
// BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
|
||||
BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
|
||||
BulletSimAPI.SetObjectForce2(BSBody.Ptr, _force);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -442,8 +447,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
}
|
||||
public override int PhysicsActorType {
|
||||
get { return _physicsActorType; }
|
||||
set { _physicsActorType = value;
|
||||
}
|
||||
set { _physicsActorType = value; }
|
||||
}
|
||||
public override bool IsPhysical {
|
||||
get { return _isPhysical; }
|
||||
@@ -470,6 +474,11 @@ public sealed class BSPrim : BSPhysObject
|
||||
|
||||
// Make gravity work if the object is physical and not selected
|
||||
// No locking here because only called when it is safe
|
||||
// There are four flags we're interested in:
|
||||
// IsStatic: Object does not move, otherwise the object has mass and moves
|
||||
// isSolid: other objects bounce off of this object
|
||||
// isVolumeDetect: other objects pass through but can generate collisions
|
||||
// collisionEvents: whether this object returns collision events
|
||||
private void SetObjectDynamic()
|
||||
{
|
||||
// If it's becoming dynamic, it will need hullness
|
||||
@@ -479,12 +488,66 @@ public sealed class BSPrim : BSPhysObject
|
||||
float mass = IsStatic ? 0f : _mass;
|
||||
|
||||
BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
|
||||
/*
|
||||
BulletSimAPI.RemoveObjectFromWorld2(Scene.World.Ptr, BSBody.Ptr);
|
||||
|
||||
// recompute any linkset parameters
|
||||
// Set up the object physicalness (static or dynamic)
|
||||
MakeDynamic();
|
||||
|
||||
// Make solid or not and arrange for collisions, etc
|
||||
MakeSolid();
|
||||
|
||||
m_currentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.Ptr);
|
||||
|
||||
BulletSimAPI.AddObjectToWorld2(Scene.World.Ptr, BSBody.Ptr);
|
||||
*/
|
||||
|
||||
// Recompute any linkset parameters.
|
||||
// When going from non-physical to physical, this re-enables the constraints that
|
||||
// had been automatically disabled when the mass was set to zero.
|
||||
Linkset.Refresh(this);
|
||||
|
||||
CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
|
||||
DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
|
||||
DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, m_currentCollisionFlags);
|
||||
}
|
||||
|
||||
// "Making dynamic" means changing to and from static.
|
||||
// When static, gravity does not effect the object and it is fixed in space.
|
||||
// When dynamic, the object can fall and be pushed by others.
|
||||
// This is independent of its 'solidness' which controls what passes through
|
||||
// this object and what interacts with it.
|
||||
private void MakeDynamic()
|
||||
{
|
||||
if (IsStatic)
|
||||
{
|
||||
// Become a Bullet 'static' object type
|
||||
BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||
// Stop all movement
|
||||
BulletSimAPI.ClearAllForces2(BSBody.Ptr);
|
||||
// Mass is zero which disables a bunch of physics stuff in Bullet
|
||||
BulletSimAPI.SetMassProps2(BSBody.Ptr, 0f, OMV.Vector3.Zero);
|
||||
// There is no inertia in a static object
|
||||
BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
|
||||
// The activation state is 'sleeping' so Bullet will not try to act on it
|
||||
BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.ISLAND_SLEEPING);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a Bullet static object
|
||||
BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||
// A dynamic object has mass
|
||||
BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, OMV.Vector3.Zero);
|
||||
// The shape is interesting and has mass and a center of gravity
|
||||
IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr);
|
||||
BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, _mass, OMV.Vector3.Zero);
|
||||
// Inertia is based on our new mass
|
||||
BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
|
||||
// Force activation of the object so Bullet will act on it.
|
||||
BulletSimAPI.Activate2(BSBody.Ptr, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeSolid()
|
||||
{
|
||||
}
|
||||
|
||||
// prims don't fly
|
||||
@@ -609,7 +672,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
|
||||
m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
|
||||
return;
|
||||
}
|
||||
_scene.TaintedObject("BSPrim.AddForce", delegate()
|
||||
@@ -624,7 +687,8 @@ public sealed class BSPrim : BSPhysObject
|
||||
m_accumulatedForces.Clear();
|
||||
}
|
||||
DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
|
||||
BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
|
||||
// For unknown reason, "ApplyCentralForce" is really additive.
|
||||
BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -644,7 +708,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
|
||||
Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
|
||||
{
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -652,7 +716,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
_subscribedEventsMs = 0;
|
||||
Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
|
||||
{
|
||||
BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
}
|
||||
public override bool SubscribedEvents() {
|
||||
@@ -1237,7 +1301,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
|
||||
|
||||
// the CreateObject() may have recreated the rigid body. Make sure we have the latest.
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -403,13 +403,13 @@ public class BSTerrainManager
|
||||
{
|
||||
float regionX = tX - offsetX;
|
||||
float regionY = tY - offsetY;
|
||||
if (regionX > mapInfo.sizeX) regionX = 0;
|
||||
if (regionY > mapInfo.sizeY) regionY = 0;
|
||||
if (regionX >= mapInfo.sizeX || regionX < 0f) regionX = 0;
|
||||
if (regionY >= mapInfo.sizeY || regionY < 0f) regionY = 0;
|
||||
int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
|
||||
ret = mapInfo.heightMap[mapIndex];
|
||||
m_terrainModified = false;
|
||||
DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
|
||||
BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
|
||||
// DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
|
||||
// BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -218,7 +218,20 @@ public struct ConfigurationParameters
|
||||
public const float numericFalse = 0f;
|
||||
}
|
||||
|
||||
// Values used by Bullet and BulletSim to control collisions
|
||||
|
||||
// The states a bullet collision object can have
|
||||
public enum ActivationState : uint
|
||||
{
|
||||
ACTIVE_TAG = 1,
|
||||
ISLAND_SLEEPING,
|
||||
WANTS_DEACTIVATION,
|
||||
DISABLE_DEACTIVATION,
|
||||
DISABLE_SIMULATION
|
||||
}
|
||||
|
||||
// Values used by Bullet and BulletSim to control object properties.
|
||||
// Bullet's "CollisionFlags" has more to do with operations on the
|
||||
// object (if collisions happen, if gravity effects it, ...).
|
||||
public enum CollisionFlags : uint
|
||||
{
|
||||
CF_STATIC_OBJECT = 1 << 0,
|
||||
@@ -233,8 +246,75 @@ public enum CollisionFlags : uint
|
||||
BS_VOLUME_DETECT_OBJECT = 1 << 11,
|
||||
BS_PHANTOM_OBJECT = 1 << 12,
|
||||
BS_PHYSICAL_OBJECT = 1 << 13,
|
||||
BS_TERRAIN_OBJECT = 1 << 14,
|
||||
BS_NONE = 0,
|
||||
BS_ALL = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
// Values for collisions groups and masks
|
||||
public enum CollisionFilterGroups : uint
|
||||
{
|
||||
NoneFilter = 0,
|
||||
DefaultFilter = 1 << 0,
|
||||
StaticFilter = 1 << 1,
|
||||
KinematicFilter = 1 << 2,
|
||||
DebrisFilter = 1 << 3,
|
||||
SensorTrigger = 1 << 4,
|
||||
CharacterFilter = 1 << 5,
|
||||
AllFilter = 0xFFFFFFFF,
|
||||
// Filter groups defined by BulletSim
|
||||
GroundPlaneFilter = 1 << 10,
|
||||
TerrainFilter = 1 << 11,
|
||||
RaycastFilter = 1 << 12,
|
||||
SolidFilter = 1 << 13,
|
||||
};
|
||||
|
||||
// For each type, we first clear and then set the collision flags
|
||||
public enum ClearCollisionFlag : uint
|
||||
{
|
||||
Terrain = CollisionFlags.BS_ALL,
|
||||
Phantom = CollisionFlags.BS_ALL,
|
||||
VolumeDetect = CollisionFlags.BS_ALL,
|
||||
PhysicalObject = CollisionFlags.BS_ALL,
|
||||
StaticObject = CollisionFlags.BS_ALL
|
||||
}
|
||||
|
||||
public enum SetCollisionFlag : uint
|
||||
{
|
||||
Terrain = CollisionFlags.CF_STATIC_OBJECT
|
||||
| CollisionFlags.BS_TERRAIN_OBJECT,
|
||||
Phantom = CollisionFlags.CF_STATIC_OBJECT
|
||||
| CollisionFlags.BS_PHANTOM_OBJECT
|
||||
| CollisionFlags.CF_NO_CONTACT_RESPONSE,
|
||||
VolumeDetect = CollisionFlags.CF_STATIC_OBJECT
|
||||
| CollisionFlags.BS_VOLUME_DETECT_OBJECT
|
||||
| CollisionFlags.CF_NO_CONTACT_RESPONSE,
|
||||
PhysicalObject = CollisionFlags.BS_PHYSICAL_OBJECT,
|
||||
StaticObject = CollisionFlags.CF_STATIC_OBJECT,
|
||||
}
|
||||
|
||||
// Collision filters used for different types of objects
|
||||
public enum SetCollisionFilter : uint
|
||||
{
|
||||
Terrain = CollisionFilterGroups.AllFilter,
|
||||
Phantom = CollisionFilterGroups.GroundPlaneFilter
|
||||
| CollisionFilterGroups.TerrainFilter,
|
||||
VolumeDetect = CollisionFilterGroups.AllFilter,
|
||||
PhysicalObject = CollisionFilterGroups.AllFilter,
|
||||
StaticObject = CollisionFilterGroups.AllFilter,
|
||||
}
|
||||
|
||||
// Collision masks used for different types of objects
|
||||
public enum SetCollisionMask : uint
|
||||
{
|
||||
Terrain = CollisionFilterGroups.AllFilter,
|
||||
Phantom = CollisionFilterGroups.GroundPlaneFilter
|
||||
| CollisionFilterGroups.TerrainFilter,
|
||||
VolumeDetect = CollisionFilterGroups.AllFilter,
|
||||
PhysicalObject = CollisionFilterGroups.AllFilter,
|
||||
StaticObject = CollisionFilterGroups.AllFilter
|
||||
}
|
||||
|
||||
// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
|
||||
// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
|
||||
public enum ConstraintParams : int
|
||||
@@ -347,6 +427,7 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity);
|
||||
|
||||
// Set the current force acting on the object
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force);
|
||||
|
||||
@@ -403,6 +484,7 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback);
|
||||
// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
|
||||
// and the old code is removed.
|
||||
|
||||
// Functions use while converting from API1 to API2. Can be removed when totally converted.
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr GetSimHandle2(uint worldID);
|
||||
|
||||
@@ -413,6 +495,7 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
|
||||
public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
|
||||
|
||||
// ===============================================================================
|
||||
// Initialization and simulation
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
|
||||
int maxCollisions, IntPtr collisionArray,
|
||||
@@ -438,6 +521,7 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt
|
||||
public static extern bool PushUpdate2(IntPtr obj);
|
||||
|
||||
// =====================================================================================
|
||||
// Mesh, hull, shape and body creation helper routines
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateMeshShape2(IntPtr world,
|
||||
int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
|
||||
@@ -460,12 +544,26 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape);
|
||||
public static extern IntPtr AllocateBodyInfo2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ReleaseBodyInfo2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
|
||||
|
||||
// =====================================================================================
|
||||
// Terrain creation and helper routines
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpMapInfo(IntPtr sim, IntPtr manInfo);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||
@@ -484,6 +582,7 @@ public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float
|
||||
public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
|
||||
|
||||
// =====================================================================================
|
||||
// Constraint creation and helper routines
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||
Vector3 frame1loc, Quaternion frame1rot,
|
||||
@@ -536,16 +635,108 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams
|
||||
public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
|
||||
|
||||
// =====================================================================================
|
||||
// btCollisionWorld entries
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void UpdateAabbs2(IntPtr world);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
|
||||
|
||||
// =====================================================================================
|
||||
// btDynamicsWorld entries
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
|
||||
// =====================================================================================
|
||||
// btCollisionObject entries
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool HasAnisotripicFriction2(IntPtr constrain);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetContactProcessingThreshold2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsStaticObject2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsKinematicObject2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool HasContactResponse2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr GetCollisionShape2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int GetActivationState2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetActivationState2(IntPtr obj, int state);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetDeactivationTime2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void Activate2(IntPtr obj, bool forceActivation);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsActive2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetRestitution2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetRestitution2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetFriction2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetFriction2(IntPtr obj);
|
||||
|
||||
/* Haven't defined the type 'Transform'
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Transform GetWorldTransform2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void setWorldTransform2(IntPtr obj, Transform trans);
|
||||
*/
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetPosition2(IntPtr obj);
|
||||
|
||||
@@ -553,89 +744,288 @@ public static extern Vector3 GetPosition2(IntPtr obj);
|
||||
public static extern Quaternion GetOrientation2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
|
||||
public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity);
|
||||
public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
|
||||
public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
|
||||
|
||||
/*
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
|
||||
public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
|
||||
*/
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool AddObjectForce2(IntPtr obj, Vector3 force);
|
||||
public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
|
||||
public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val);
|
||||
public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
|
||||
public static extern float GetHitFraction2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetDeactivationTime2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetFriction2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetHitFraction2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetRestitution2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
|
||||
public static extern void SetHitFraction2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
|
||||
public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
|
||||
public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
|
||||
public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
|
||||
public static extern float GetCcdMotionThreshold2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool UpdateInertiaTensor2(IntPtr obj);
|
||||
public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetGravity2(IntPtr obj, Vector3 val);
|
||||
public static extern float GetCcdSweepSphereRadius2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr ClearForces2(IntPtr obj);
|
||||
public static extern void SetCcdSweepSphereRadius2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr ClearAllForces2(IntPtr obj);
|
||||
public static extern IntPtr GetUserPointer2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetMargin2(IntPtr obj, float val);
|
||||
public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
|
||||
|
||||
// =====================================================================================
|
||||
// btRigidBody entries
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ApplyGravity2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
|
||||
public static extern void SetGravity2(IntPtr obj, Vector3 val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool DestroyObject2(IntPtr world, IntPtr obj);
|
||||
public static extern Vector3 GetGravity2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetLinearDamping2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetAngularDamping2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetLinearSleepingThreshold2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetAngularSleepingThreshold2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ApplyDamping2(IntPtr obj, float timeStep);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetLinearFactor2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
|
||||
|
||||
/*
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
|
||||
*/
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
|
||||
|
||||
// Add a force to the object as if its mass is one.
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
|
||||
|
||||
// Set the force being applied to the object as if its mass is one.
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetTotalForce2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetTotalTorque2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
|
||||
|
||||
// Apply force at the given point. Will add torque to the object.
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos);
|
||||
|
||||
// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp);
|
||||
|
||||
// Apply impulse to the object's torque. Force is scaled by object's mass.
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp);
|
||||
|
||||
// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ClearForces2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void ClearAllForces2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void UpdateInertiaTensor2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj);
|
||||
|
||||
/*
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Transform GetCenterOfMassTransform2(IntPtr obj);
|
||||
*/
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetLinearVelocity2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetAngularVelocity2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void Translate2(IntPtr obj, Vector3 trans);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool WantsSleeping2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetAngularFactor2(IntPtr obj, float factor);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetAngularFactor2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsInWorld2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int GetNumConstraintRefs2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetPushVelocity2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetTurnVelocity2(IntPtr obj);
|
||||
|
||||
// =====================================================================================
|
||||
// btCollisionShape entries
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetAngularMotionDisc2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsPolyhedral2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsConvex2d2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsConvex2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsNonMoving2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsConcave2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsCompound2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsSoftBody2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsInfinite2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetLocalScaling2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void CalculateLocalInertia2(IntPtr shape, float mass, Vector3 inertia);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int GetShapeType2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetMargin2(IntPtr shape, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern float GetMargin2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetCollisionFilterMask(IntPtr shape, uint filter, uint mask);
|
||||
|
||||
// =====================================================================================
|
||||
// Debugging
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpPhysicsStatistics2(IntPtr sim);
|
||||
|
||||
|
||||
@@ -39,11 +39,8 @@ using OpenSim.Framework.Console;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
using Mono.Addins;
|
||||
|
||||
[assembly: Addin("RegionCombinerModule", "0.1")]
|
||||
[assembly: AddinDependency("OpenSim", "0.5")]
|
||||
namespace OpenSim.Region.RegionCombinerModule
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||
public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<Addin id="OpenSim.RegionModules.RegionCombinerModule" version="0.3">
|
||||
<Runtime>
|
||||
<Import assembly="OpenSim.Region.RegionCombinerModule.dll"/>
|
||||
</Runtime>
|
||||
|
||||
<Dependencies>
|
||||
<Addin id="OpenSim" version="0.5" />
|
||||
</Dependencies>
|
||||
|
||||
<Extension path = "/OpenSim/RegionModules">
|
||||
<RegionModule id="RegionCombinerModule" type="OpenSim.Region.RegionCombinerModule.RegionCombinerModule" />
|
||||
</Extension>
|
||||
|
||||
</Addin>
|
||||
@@ -1948,7 +1948,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
|
||||
pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
|
||||
pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
|
||||
pos.z > 4096 // return FALSE if altitude than 4096m
|
||||
pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
|
||||
)
|
||||
)
|
||||
{
|
||||
@@ -1959,8 +1959,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
// this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
|
||||
|
||||
Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
|
||||
LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y);
|
||||
LandData there = World.GetLandData((float)pos.x, (float)pos.y);
|
||||
LandData here = World.GetLandData(objectPos);
|
||||
LandData there = World.GetLandData(pos);
|
||||
|
||||
// we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
|
||||
|
||||
@@ -9770,20 +9770,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
switch ((ParcelMediaCommandEnum) aList.Data[i])
|
||||
{
|
||||
case ParcelMediaCommandEnum.Url:
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
|
||||
break;
|
||||
case ParcelMediaCommandEnum.Desc:
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description));
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description));
|
||||
break;
|
||||
case ParcelMediaCommandEnum.Texture:
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString()));
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString()));
|
||||
break;
|
||||
case ParcelMediaCommandEnum.Type:
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType));
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType));
|
||||
break;
|
||||
case ParcelMediaCommandEnum.Size:
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth));
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight));
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth));
|
||||
list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight));
|
||||
break;
|
||||
default:
|
||||
ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
|
||||
@@ -10398,7 +10398,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
LandData land = World.GetLandData((float)pos.x, (float)pos.y);
|
||||
LandData land = World.GetLandData(pos);
|
||||
if (land == null)
|
||||
{
|
||||
return new LSL_List(0);
|
||||
|
||||
@@ -254,7 +254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
object[] convertedParms = new object[parms.Length];
|
||||
for (int i = 0; i < parms.Length; i++)
|
||||
convertedParms[i] = ConvertFromLSL(parms[i],signature[i]);
|
||||
convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname);
|
||||
|
||||
// now call the function, the contract with the function is that it will always return
|
||||
// non-null but don't trust it completely
|
||||
@@ -294,7 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
protected object ConvertFromLSL(object lslparm, Type type)
|
||||
protected object ConvertFromLSL(object lslparm, Type type, string fname)
|
||||
{
|
||||
// ---------- String ----------
|
||||
if (lslparm is LSL_String)
|
||||
@@ -374,14 +374,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
(LSL_Vector)plist[i]);
|
||||
}
|
||||
else
|
||||
MODError("unknown LSL list element type");
|
||||
MODError(String.Format("{0}: unknown LSL list element type", fname));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
MODError(String.Format("parameter type mismatch; expecting {0}",type.Name));
|
||||
MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -2941,7 +2941,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
ScenePresence presence = World.GetScenePresence(avatarId);
|
||||
if (presence != null)
|
||||
{
|
||||
LandData land = World.GetLandData((float)pos.X, (float)pos.Y);
|
||||
LandData land = World.GetLandData(pos);
|
||||
if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage)
|
||||
{
|
||||
float health = presence.Health;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
@@ -71,10 +72,17 @@ namespace OpenSim.Server.Base
|
||||
//
|
||||
private string m_pidFile = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which this server was started
|
||||
/// </summary>
|
||||
protected DateTime m_startuptime;
|
||||
|
||||
// Handle all the automagical stuff
|
||||
//
|
||||
public ServicesServerBase(string prompt, string[] args)
|
||||
{
|
||||
m_startuptime = DateTime.Now;
|
||||
|
||||
// Save raw arguments
|
||||
//
|
||||
m_Arguments = args;
|
||||
@@ -250,6 +258,10 @@ namespace OpenSim.Server.Base
|
||||
"command-script <script>",
|
||||
"Run a command script from file", HandleScript);
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand("General", false, "show uptime",
|
||||
"show uptime",
|
||||
"Show server uptime", HandleShow);
|
||||
|
||||
|
||||
// Allow derived classes to perform initialization that
|
||||
// needs to be done after the console has opened
|
||||
@@ -345,5 +357,34 @@ namespace OpenSim.Server.Base
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void HandleShow(string module, string[] cmd)
|
||||
{
|
||||
List<string> args = new List<string>(cmd);
|
||||
|
||||
args.RemoveAt(0);
|
||||
|
||||
string[] showParams = args.ToArray();
|
||||
|
||||
switch (showParams[0])
|
||||
{
|
||||
case "uptime":
|
||||
MainConsole.Instance.Output(GetUptimeReport());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a report about the uptime of this server
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected string GetUptimeReport()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
|
||||
sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
|
||||
sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,8 @@ namespace OpenSim.Server.Handlers.Avatar
|
||||
if (!UUID.TryParse(request["UserID"].ToString(), out user))
|
||||
return FailureResult();
|
||||
|
||||
RemoveRequestParamsNotForStorage(request);
|
||||
|
||||
AvatarData avatar = new AvatarData(request);
|
||||
if (m_AvatarService.SetAvatar(user, avatar))
|
||||
return SuccessResult();
|
||||
@@ -153,11 +155,25 @@ namespace OpenSim.Server.Handlers.Avatar
|
||||
if (!UUID.TryParse(request["UserID"].ToString(), out user))
|
||||
return FailureResult();
|
||||
|
||||
RemoveRequestParamsNotForStorage(request);
|
||||
|
||||
if (m_AvatarService.ResetAvatar(user))
|
||||
return SuccessResult();
|
||||
|
||||
return FailureResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove parameters that were used to invoke the method and should not in themselves be persisted.
|
||||
/// </summary>
|
||||
/// <param name='request'></param>
|
||||
private void RemoveRequestParamsNotForStorage(Dictionary<string, object> request)
|
||||
{
|
||||
request.Remove("VERSIONMAX");
|
||||
request.Remove("VERSIONMIN");
|
||||
request.Remove("METHOD");
|
||||
request.Remove("UserID");
|
||||
}
|
||||
|
||||
byte[] SetItems(Dictionary<string, object> request)
|
||||
{
|
||||
@@ -173,6 +189,8 @@ namespace OpenSim.Server.Handlers.Avatar
|
||||
if (!(request["Names"] is List<string> || request["Values"] is List<string>))
|
||||
return FailureResult();
|
||||
|
||||
RemoveRequestParamsNotForStorage(request);
|
||||
|
||||
List<string> _names = (List<string>)request["Names"];
|
||||
names = _names.ToArray();
|
||||
List<string> _values = (List<string>)request["Values"];
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||
public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
|
||||
{
|
||||
Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
|
||||
Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0);
|
||||
Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
|
||||
|
||||
OSDMap extraData = new OSDMap
|
||||
{
|
||||
@@ -286,7 +286,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||
List<GridRegion> foundRegions = new List<GridRegion>();
|
||||
|
||||
Vector3d minPosition = new Vector3d(xmin, ymin, 0.0);
|
||||
Vector3d maxPosition = new Vector3d(xmax, ymax, 4096.0);
|
||||
Vector3d maxPosition = new Vector3d(xmax, ymax, Constants.RegionHeight);
|
||||
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
{
|
||||
|
||||
@@ -56,10 +56,12 @@ namespace OpenSim.Services.HypergridService
|
||||
|
||||
private string m_HomeURL;
|
||||
private IUserAccountService m_UserAccountService;
|
||||
private IAvatarService m_AvatarService;
|
||||
|
||||
// private UserAccountCache m_Cache;
|
||||
|
||||
private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>();
|
||||
private ExpiringCache<UUID, AvatarAppearance> m_Appearances = new ExpiringCache<UUID, AvatarAppearance>();
|
||||
|
||||
public HGSuitcaseInventoryService(IConfigSource config, string configName)
|
||||
: base(config, configName)
|
||||
@@ -77,7 +79,6 @@ namespace OpenSim.Services.HypergridService
|
||||
IConfig invConfig = config.Configs[m_ConfigName];
|
||||
if (invConfig != null)
|
||||
{
|
||||
// realm = authConfig.GetString("Realm", realm);
|
||||
string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty);
|
||||
if (userAccountsDll == string.Empty)
|
||||
throw new Exception("Please specify UserAccountsService in HGInventoryService configuration");
|
||||
@@ -87,8 +88,14 @@ namespace OpenSim.Services.HypergridService
|
||||
if (m_UserAccountService == null)
|
||||
throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll));
|
||||
|
||||
// legacy configuration [obsolete]
|
||||
m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty);
|
||||
string avatarDll = invConfig.GetString("AvatarService", string.Empty);
|
||||
if (avatarDll == string.Empty)
|
||||
throw new Exception("Please specify AvatarService in HGInventoryService configuration");
|
||||
|
||||
m_AvatarService = ServerUtils.LoadPlugin<IAvatarService>(avatarDll, args);
|
||||
if (m_AvatarService == null)
|
||||
throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll));
|
||||
|
||||
// Preferred
|
||||
m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL);
|
||||
|
||||
@@ -394,7 +401,7 @@ namespace OpenSim.Services.HypergridService
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsWithinSuitcaseTree(it.Owner, it.Folder))
|
||||
if (!IsWithinSuitcaseTree(it.Owner, it.Folder) && !IsPartOfAppearance(it.Owner, it.ID))
|
||||
{
|
||||
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase",
|
||||
it.Name, it.Folder);
|
||||
@@ -549,6 +556,51 @@ namespace OpenSim.Services.HypergridService
|
||||
else return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Avatar Appearance
|
||||
|
||||
private AvatarAppearance GetAppearance(UUID principalID)
|
||||
{
|
||||
AvatarAppearance a = null;
|
||||
if (m_Appearances.TryGetValue(principalID, out a))
|
||||
return a;
|
||||
|
||||
a = m_AvatarService.GetAppearance(principalID);
|
||||
m_Appearances.AddOrUpdate(principalID, a, 5 * 60); // 5minutes
|
||||
return a;
|
||||
}
|
||||
|
||||
private bool IsPartOfAppearance(UUID principalID, UUID itemID)
|
||||
{
|
||||
AvatarAppearance a = GetAppearance(principalID);
|
||||
if (a == null)
|
||||
return false;
|
||||
|
||||
// Check wearables (body parts and clothes)
|
||||
for (int i = 0; i < a.Wearables.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < a.Wearables[i].Count; j++)
|
||||
{
|
||||
if (a.Wearables[i][j].ItemID == itemID)
|
||||
{
|
||||
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is a wearable", itemID);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check attachments
|
||||
if (a.GetAttachmentForItem(itemID) != null)
|
||||
{
|
||||
m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is an attachment", itemID);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
Welcome to OpenSim!
|
||||
|
||||
==================
|
||||
==== OVERVIEW ====
|
||||
==================
|
||||
# Overview
|
||||
|
||||
OpenSim is a BSD Licensed Open Source project to develop a functioning
|
||||
virtual worlds server platform capable of supporting multiple clients
|
||||
@@ -12,16 +10,12 @@ C#, and can run under Mono or the Microsoft .NET runtimes.
|
||||
This is considered an alpha release. Some stuff works, a lot doesn't.
|
||||
If it breaks, you get to keep *both* pieces.
|
||||
|
||||
=========================
|
||||
=== Compiling OpenSim ===
|
||||
=========================
|
||||
# Compiling OpenSim
|
||||
|
||||
Please see BUILDING.txt if you downloaded a source distribution and
|
||||
Please see BUILDING.md if you downloaded a source distribution and
|
||||
need to build OpenSim before running it.
|
||||
|
||||
==================================
|
||||
=== Running OpenSim on Windows ===
|
||||
==================================
|
||||
# Running OpenSim on Windows
|
||||
|
||||
We recommend that you run OpenSim from a command prompt on Windows in order
|
||||
to capture any errors.
|
||||
@@ -33,9 +27,7 @@ To run OpenSim from a command prompt
|
||||
|
||||
Now see the "Configuring OpenSim" section
|
||||
|
||||
================================
|
||||
=== Running OpenSim on Linux ===
|
||||
================================
|
||||
# Running OpenSim on Linux
|
||||
|
||||
You will need Mono >= 2.4.3 to run OpenSim. On some Linux distributions you
|
||||
may need to install additional packages. See http://opensimulator.org/wiki/Dependencies
|
||||
@@ -48,14 +40,12 @@ To run OpenSim, from the unpacked distribution type:
|
||||
|
||||
Now see the "Configuring OpenSim" section
|
||||
|
||||
===========================
|
||||
=== Configuring OpenSim ===
|
||||
===========================
|
||||
# Configuring OpenSim
|
||||
|
||||
When OpenSim starts for the first time, you will be prompted with a
|
||||
series of questions that look something like:
|
||||
|
||||
[09-17 03:54:40] DEFAULT REGION CONFIG: Simulator Name [OpenSim Test]:
|
||||
[09-17 03:54:40] DEFAULT REGION CONFIG: Simulator Name [OpenSim Test]:
|
||||
|
||||
For all the options except simulator name, you can safely hit enter to accept
|
||||
the default if you want to connect using a client on the same machine or over
|
||||
@@ -72,7 +62,7 @@ in-world. You can also use these details to perform your first login.
|
||||
|
||||
Once you are presented with a prompt that looks like:
|
||||
|
||||
Region (My region name) #
|
||||
Region (My region name) #
|
||||
|
||||
You have successfully started OpenSim.
|
||||
|
||||
@@ -83,9 +73,7 @@ Helpful resources:
|
||||
* http://opensimulator.org/wiki/Configuration
|
||||
* http://opensimulator.org/wiki/Configuring_Regions
|
||||
|
||||
==================================
|
||||
=== Connecting to your OpenSim ===
|
||||
==================================
|
||||
# Connecting to your OpenSim
|
||||
|
||||
By default your sim will be available for login on port 9000. You can login by
|
||||
adding -loginuri http://127.0.0.1:9000 to the command that starts Second Life
|
||||
@@ -96,15 +84,11 @@ http://192.168.1.2:9000)
|
||||
To login, use the avatar details that you gave for your estate ownership or the
|
||||
one you set up using the "create user" command.
|
||||
|
||||
===================
|
||||
=== Bug reports ===
|
||||
===================
|
||||
# Bug reports
|
||||
|
||||
In the very likely event of bugs biting you (err, your OpenSim) we
|
||||
encourage you to see whether the problem has already been reported on
|
||||
the OpenSim mantis system. You can find the OpenSim mantis system at
|
||||
|
||||
http://opensimulator.org/mantis/main_page.php
|
||||
the [OpenSim mantis system](http://opensimulator.org/mantis/main_page.php).
|
||||
|
||||
If your bug has already been reported, you might want to add to the
|
||||
bug description and supply additional information.
|
||||
@@ -119,9 +103,7 @@ mantis"). Useful information to include:
|
||||
|
||||
mono --debug OpenSim.exe
|
||||
|
||||
===================================
|
||||
=== More Information on OpenSim ===
|
||||
===================================
|
||||
# More Information on OpenSim
|
||||
|
||||
More extensive information on building, running, and configuring
|
||||
OpenSim, as well as how to report bugs, and participate in the OpenSim
|
||||
@@ -107,6 +107,11 @@
|
||||
;; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
|
||||
;; This can be overriden in the region config file.
|
||||
; ClampPrimSize = false
|
||||
|
||||
;# {LinksetPrims} {} {Max prims an object will hold?} {} 0
|
||||
;; Maximum number of prims allowable in a linkset. Affects creating new linksets. Ignored if less than or equal to zero.
|
||||
;; This can be overriden in the region config file.
|
||||
; LinksetPrims = 0
|
||||
|
||||
;# {AllowScriptCrossing} {} {Allow scripts to cross into this region} {true false} true
|
||||
;; Allow scripts to keep running when they cross region boundaries, rather than being restarted. State is reloaded on the destination region.
|
||||
|
||||
@@ -94,6 +94,10 @@
|
||||
; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
|
||||
; This can be overriden in the region config file.
|
||||
ClampPrimSize = false
|
||||
|
||||
; Maximum number of prims allowable in a linkset. Affects creating new linksets. Ignored if less than or equal to zero.
|
||||
; This can be overriden in the region config file.
|
||||
LinksetPrims = 0
|
||||
|
||||
; Allow scripts to keep running when they cross region boundaries, rather than being restarted. State is reloaded on the destination region.
|
||||
; This only applies when crossing to a region running in a different simulator.
|
||||
@@ -703,6 +707,13 @@
|
||||
; Default is false.
|
||||
ReuseDynamicTextures = false
|
||||
|
||||
; If true, then textures generated dynamically that have a low data size relative to their pixel size are not reused
|
||||
; This is to workaround an apparent LL 3.3.4 and earlier viewer bug where such textures are not redisplayed properly when pulled from the viewer cache.
|
||||
; Only set this to true if you are sure that all the viewers using your simulator will not suffer from this problem.
|
||||
; This setting only has an affect is ReuseDynamicTextures = true
|
||||
; Default is false
|
||||
ReuseDynamicLowDataTextures = false
|
||||
|
||||
|
||||
[ODEPhysicsSettings]
|
||||
; ##
|
||||
|
||||
@@ -104,6 +104,12 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
|
||||
; Region_Welcome_Area = "DefaultRegion, FallbackRegion"
|
||||
; (replace spaces with underscore)
|
||||
|
||||
;; Allow Hyperlinks to be created at the console
|
||||
HypergridLinker = true
|
||||
|
||||
Gatekeeper = "http://127.0.0.1:8002"
|
||||
|
||||
|
||||
; * This is the configuration for the freeswitch server in grid mode
|
||||
[FreeswitchService]
|
||||
LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService"
|
||||
|
||||
@@ -54,10 +54,3 @@
|
||||
|
||||
; Warning level for cache directory size
|
||||
;CacheWarnAt = 30000
|
||||
|
||||
; Perform a deep scan of all assets within all regions, looking for all assets
|
||||
; present or referenced. Mark all assets found that are already present in the
|
||||
; cache, and request all assets that are found that are not already cached (this
|
||||
; will cause those assets to be cached)
|
||||
;
|
||||
DeepScanBeforePurge = true
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
SimulationServiceInConnector = true
|
||||
MapImageServiceInConnector = true
|
||||
|
||||
[Profile]
|
||||
Module = "BasicProfileModule"
|
||||
|
||||
[Messaging]
|
||||
MessageTransferModule = HGMessageTransferModule
|
||||
@@ -97,6 +95,10 @@
|
||||
GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService"
|
||||
GridService = "OpenSim.Services.GridService.dll:GridService"
|
||||
InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService"
|
||||
AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
|
||||
|
||||
;; 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
|
||||
|
||||
[GridUserService]
|
||||
LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user