Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cfd63d0b4 | ||
|
|
a6f7328216 | ||
|
|
b36ef60aca | ||
|
|
8d7b1f8aa0 | ||
|
|
b0da4b8d13 | ||
|
|
cfa022700d | ||
|
|
9ab5c5040d | ||
|
|
5df3944607 | ||
|
|
fb2ace6fff | ||
|
|
f931c0a868 | ||
|
|
f4cc19968c | ||
|
|
b542622b3a | ||
|
|
5f97b3e1d9 | ||
|
|
e379566e6e | ||
|
|
80f486c778 | ||
|
|
632a42e2b1 | ||
|
|
bceef401fa | ||
|
|
1b0abf8f0c | ||
|
|
e29d563557 | ||
|
|
33aa6d172f | ||
|
|
3089b6d824 | ||
|
|
a5b3989e5d | ||
|
|
387a1bb283 | ||
|
|
b481a78234 | ||
|
|
d667f9d260 | ||
|
|
696b3f66c4 | ||
|
|
49e2872f9e | ||
|
|
61f4523e01 | ||
|
|
a74167bb06 | ||
|
|
f2a9d26118 | ||
|
|
e50b6b5334 | ||
|
|
967d42d393 | ||
|
|
e50155ebca | ||
|
|
f99278c956 | ||
|
|
95809cabd9 | ||
|
|
9d973ec3b3 | ||
|
|
d29fc53052 | ||
|
|
91312daeb2 | ||
|
|
0e5f5538bc | ||
|
|
f9721573d9 | ||
|
|
c7948a669a | ||
|
|
5e626ce55d | ||
|
|
380962d359 | ||
|
|
daa4745fb7 | ||
|
|
de69a24574 | ||
|
|
b602b476ad | ||
|
|
c77be802d2 | ||
|
|
1826b2b18e | ||
|
|
f35bd6eb7d | ||
|
|
dcb94b8a24 | ||
|
|
6632eb7c05 | ||
|
|
f0a098924e | ||
|
|
7c347f4c5c | ||
|
|
d86cbe6379 | ||
|
|
c0fec70b1a | ||
|
|
2c5ff93990 | ||
|
|
1ec84ac8b1 | ||
|
|
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
|
||||
@@ -728,7 +728,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
responseData["success"] = true;
|
||||
responseData["region_name"] = region.RegionName;
|
||||
responseData["region_id"] = region.RegionID.ToString();
|
||||
responseData["region_uuid"] = region.RegionID.ToString(); //Deprecate July 2012
|
||||
|
||||
m_log.Info("[RADMIN]: CreateRegion: request complete");
|
||||
}
|
||||
@@ -1369,6 +1368,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 +1426,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)
|
||||
@@ -1874,29 +1880,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
{
|
||||
return;
|
||||
}
|
||||
#region Deprecate July 2012
|
||||
//region_ID, regionid, region_uuid will be deprecated in July 2012!!!!!!
|
||||
else if (requestData.ContainsKey("regionid") &&
|
||||
!String.IsNullOrEmpty((string)requestData["regionid"]))
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Use of parameter regionid will be deprecated as of July 2012. Use region_id instead");
|
||||
}
|
||||
else if (requestData.ContainsKey("region_ID") &&
|
||||
!String.IsNullOrEmpty((string)requestData["region_ID"]))
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Use of parameter region_ID will be deprecated as of July 2012. Use region_id instead");
|
||||
}
|
||||
else if (requestData.ContainsKey("regionID") &&
|
||||
!String.IsNullOrEmpty((string)requestData["regionID"]))
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Use of parameter regionID will be deprecated as of July 2012. Use region_id instead");
|
||||
}
|
||||
else if (requestData.ContainsKey("region_uuid") &&
|
||||
!String.IsNullOrEmpty((string)requestData["region_uuid"]))
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Use of parameter region_uuid will be deprecated as of July 2012. Use region_id instead");
|
||||
}
|
||||
#endregion
|
||||
else
|
||||
{
|
||||
responseData["accepted"] = false;
|
||||
@@ -1918,56 +1901,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||
throw new Exception(String.Format("Region ID {0} not found", regionID));
|
||||
}
|
||||
}
|
||||
#region Deprecate July 2012
|
||||
else if (requestData.ContainsKey("regionid") &&
|
||||
!String.IsNullOrEmpty((string)requestData["regionid"]))
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Use of parameter regionid will be deprecated as of July 2012. Use region_id instead");
|
||||
|
||||
UUID regionID = (UUID)(string)requestData["regionid"];
|
||||
if (!m_application.SceneManager.TryGetScene(regionID, out scene))
|
||||
{
|
||||
responseData["error"] = String.Format("Region ID {0} not found", regionID);
|
||||
throw new Exception(String.Format("Region ID {0} not found", regionID));
|
||||
}
|
||||
}
|
||||
else if (requestData.ContainsKey("region_ID") &&
|
||||
!String.IsNullOrEmpty((string)requestData["region_ID"]))
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Use of parameter region_ID will be deprecated as of July 2012. Use region_id instead");
|
||||
|
||||
UUID regionID = (UUID)(string)requestData["region_ID"];
|
||||
if (!m_application.SceneManager.TryGetScene(regionID, out scene))
|
||||
{
|
||||
responseData["error"] = String.Format("Region ID {0} not found", regionID);
|
||||
throw new Exception(String.Format("Region ID {0} not found", regionID));
|
||||
}
|
||||
}
|
||||
else if (requestData.ContainsKey("regionID") &&
|
||||
!String.IsNullOrEmpty((string)requestData["regionID"]))
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Use of parameter regionID will be deprecated as of July 2012. Use region_id instead");
|
||||
|
||||
UUID regionID = (UUID)(string)requestData["regionID"];
|
||||
if (!m_application.SceneManager.TryGetScene(regionID, out scene))
|
||||
{
|
||||
responseData["error"] = String.Format("Region ID {0} not found", regionID);
|
||||
throw new Exception(String.Format("Region ID {0} not found", regionID));
|
||||
}
|
||||
}
|
||||
else if (requestData.ContainsKey("region_uuid") &&
|
||||
!String.IsNullOrEmpty((string)requestData["region_uuid"]))
|
||||
{
|
||||
m_log.WarnFormat("[RADMIN]: Use of parameter region_uuid will be deprecated as of July 2012. Use region_id instead");
|
||||
|
||||
UUID regionID = (UUID)(string)requestData["region_uuid"];
|
||||
if (!m_application.SceneManager.TryGetScene(regionID, out scene))
|
||||
{
|
||||
responseData["error"] = String.Format("Region ID {0} not found", regionID);
|
||||
throw new Exception(String.Format("Region ID {0} not found", regionID));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
else if (requestData.ContainsKey("region_name") &&
|
||||
!String.IsNullOrEmpty((string)requestData["region_name"]))
|
||||
{
|
||||
|
||||
@@ -312,14 +312,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||
// Now that everything is setup we can proceed to
|
||||
// add THIS agent to the HTTP server's handler list
|
||||
|
||||
if (!AddAgentHandler(Rest.Name,this))
|
||||
{
|
||||
Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId);
|
||||
foreach (IRest handler in handlers)
|
||||
{
|
||||
handler.Close();
|
||||
}
|
||||
}
|
||||
// FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will
|
||||
// have to be handled through the AddHttpHandler interface.
|
||||
// if (!AddAgentHandler(Rest.Name,this))
|
||||
// {
|
||||
// Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId);
|
||||
// foreach (IRest handler in handlers)
|
||||
// {
|
||||
// handler.Close();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -342,11 +344,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||
{
|
||||
Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId);
|
||||
|
||||
try
|
||||
{
|
||||
RemoveAgentHandler(Rest.Name, this);
|
||||
}
|
||||
catch (KeyNotFoundException){}
|
||||
// FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will
|
||||
// have to be handled through the AddHttpHandler interface.
|
||||
// try
|
||||
// {
|
||||
// RemoveAgentHandler(Rest.Name, this);
|
||||
// }
|
||||
// catch (KeyNotFoundException){}
|
||||
|
||||
foreach (IRest handler in handlers)
|
||||
{
|
||||
|
||||
@@ -297,7 +297,9 @@ namespace OpenSim.ApplicationPlugins.Rest
|
||||
{
|
||||
if (!IsEnabled) return false;
|
||||
_agents.Add(agentName, handler);
|
||||
return _httpd.AddAgentHandler(agentName, handler);
|
||||
// return _httpd.AddAgentHandler(agentName, handler);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -316,7 +318,7 @@ namespace OpenSim.ApplicationPlugins.Rest
|
||||
if (_agents[agentName] == handler)
|
||||
{
|
||||
_agents.Remove(agentName);
|
||||
return _httpd.RemoveAgentHandler(agentName, handler);
|
||||
// return _httpd.RemoveAgentHandler(agentName, handler);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -358,10 +360,10 @@ namespace OpenSim.ApplicationPlugins.Rest
|
||||
_httpd.RemoveStreamHandler(h.HttpMethod, h.Path);
|
||||
}
|
||||
_handlers = null;
|
||||
foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents)
|
||||
{
|
||||
_httpd.RemoveAgentHandler(h.Key, h.Value);
|
||||
}
|
||||
// foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents)
|
||||
// {
|
||||
// _httpd.RemoveAgentHandler(h.Key, h.Value);
|
||||
// }
|
||||
_agents = 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;
|
||||
|
||||
84
OpenSim/Framework/AssetPermissions.cs
Normal file
84
OpenSim/Framework/AssetPermissions.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
using Nini.Config;
|
||||
using log4net;
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public class AssetPermissions
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(
|
||||
MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private bool[] m_DisallowExport, m_DisallowImport;
|
||||
private string[] m_AssetTypeNames;
|
||||
|
||||
public AssetPermissions(IConfig config)
|
||||
{
|
||||
Type enumType = typeof(AssetType);
|
||||
m_AssetTypeNames = Enum.GetNames(enumType);
|
||||
for (int i = 0; i < m_AssetTypeNames.Length; i++)
|
||||
m_AssetTypeNames[i] = m_AssetTypeNames[i].ToLower();
|
||||
int n = Enum.GetValues(enumType).Length;
|
||||
m_DisallowExport = new bool[n];
|
||||
m_DisallowImport = new bool[n];
|
||||
|
||||
LoadPermsFromConfig(config, "DisallowExport", m_DisallowExport);
|
||||
LoadPermsFromConfig(config, "DisallowImport", m_DisallowImport);
|
||||
|
||||
}
|
||||
|
||||
private void LoadPermsFromConfig(IConfig assetConfig, string variable, bool[] bitArray)
|
||||
{
|
||||
if (assetConfig == null)
|
||||
return;
|
||||
|
||||
string perms = assetConfig.GetString(variable, String.Empty);
|
||||
string[] parts = perms.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (string s in parts)
|
||||
{
|
||||
int index = Array.IndexOf(m_AssetTypeNames, s.Trim().ToLower());
|
||||
if (index >= 0)
|
||||
bitArray[index] = true;
|
||||
else
|
||||
m_log.WarnFormat("[Asset Permissions]: Invalid AssetType {0}", s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool AllowedExport(sbyte type)
|
||||
{
|
||||
string assetTypeName = ((AssetType)type).ToString();
|
||||
|
||||
int index = Array.IndexOf(m_AssetTypeNames, assetTypeName.ToLower());
|
||||
if (index >= 0 && m_DisallowExport[index])
|
||||
{
|
||||
m_log.DebugFormat("[Asset Permissions]: Export denied: configuration does not allow export of AssetType {0}", assetTypeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool AllowedImport(sbyte type)
|
||||
{
|
||||
string assetTypeName = ((AssetType)type).ToString();
|
||||
|
||||
int index = Array.IndexOf(m_AssetTypeNames, assetTypeName.ToLower());
|
||||
if (index >= 0 && m_DisallowImport[index])
|
||||
{
|
||||
m_log.DebugFormat("[Asset Permissions]: Import denied: configuration does not allow import of AssetType {0}", assetTypeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
@@ -637,11 +643,11 @@ namespace OpenSim.Framework
|
||||
|
||||
#region Prim stuff
|
||||
|
||||
m_nonphysPrimMin = config.GetFloat("NonphysicalPrimMin", 0);
|
||||
allKeys.Remove("NonphysicalPrimMin");
|
||||
m_nonphysPrimMin = config.GetFloat("NonPhysicalPrimMin", 0);
|
||||
allKeys.Remove("NonPhysicalPrimMin");
|
||||
|
||||
m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0);
|
||||
allKeys.Remove("NonphysicalPrimMax");
|
||||
m_nonphysPrimMax = config.GetInt("NonPhysicalPrimMax", 0);
|
||||
allKeys.Remove("NonPhysicalPrimMax");
|
||||
|
||||
m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0);
|
||||
allKeys.Remove("PhysicalPrimMin");
|
||||
@@ -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>
|
||||
|
||||
@@ -54,8 +54,23 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the debug level.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// See MainServer.DebugLevel.
|
||||
/// </value>
|
||||
public int DebugLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Request number for diagnostic purposes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an internal number. In some debug situations an external number may also be supplied in the
|
||||
/// opensim-request-id header but we are not currently logging this.
|
||||
/// </remarks>
|
||||
public int RequestNumber { get; private set; }
|
||||
|
||||
private volatile int NotSocketErrors = 0;
|
||||
public volatile bool HTTPDRunning = false;
|
||||
|
||||
@@ -67,7 +82,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
|
||||
protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>();
|
||||
protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>();
|
||||
protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>();
|
||||
// protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>();
|
||||
protected Dictionary<string, PollServiceEventArgs> m_pollHandlers =
|
||||
new Dictionary<string, PollServiceEventArgs>();
|
||||
|
||||
@@ -245,29 +260,29 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
return new List<string>(m_pollHandlers.Keys);
|
||||
}
|
||||
|
||||
// Note that the agent string is provided simply to differentiate
|
||||
// the handlers - it is NOT required to be an actual agent header
|
||||
// value.
|
||||
public bool AddAgentHandler(string agent, IHttpAgentHandler handler)
|
||||
{
|
||||
lock (m_agentHandlers)
|
||||
{
|
||||
if (!m_agentHandlers.ContainsKey(agent))
|
||||
{
|
||||
m_agentHandlers.Add(agent, handler);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//must already have a handler for that path so return false
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<string> GetAgentHandlerKeys()
|
||||
{
|
||||
lock (m_agentHandlers)
|
||||
return new List<string>(m_agentHandlers.Keys);
|
||||
}
|
||||
// // Note that the agent string is provided simply to differentiate
|
||||
// // the handlers - it is NOT required to be an actual agent header
|
||||
// // value.
|
||||
// public bool AddAgentHandler(string agent, IHttpAgentHandler handler)
|
||||
// {
|
||||
// lock (m_agentHandlers)
|
||||
// {
|
||||
// if (!m_agentHandlers.ContainsKey(agent))
|
||||
// {
|
||||
// m_agentHandlers.Add(agent, handler);
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// //must already have a handler for that path so return false
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// public List<string> GetAgentHandlerKeys()
|
||||
// {
|
||||
// lock (m_agentHandlers)
|
||||
// return new List<string>(m_agentHandlers.Keys);
|
||||
// }
|
||||
|
||||
public bool AddLLSDHandler(string path, LLSDMethod handler)
|
||||
{
|
||||
@@ -296,6 +311,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
private void OnRequest(object source, RequestEventArgs args)
|
||||
{
|
||||
RequestNumber++;
|
||||
|
||||
try
|
||||
{
|
||||
IHttpClientContext context = (IHttpClientContext)source;
|
||||
@@ -405,7 +422,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
string requestMethod = request.HttpMethod;
|
||||
string uriString = request.RawUrl;
|
||||
|
||||
// string reqnum = "unknown";
|
||||
int requestStartTick = Environment.TickCount;
|
||||
|
||||
// Will be adjusted later on.
|
||||
@@ -422,22 +438,22 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true);
|
||||
|
||||
// This is the REST agent interface. We require an agent to properly identify
|
||||
// itself. If the REST handler recognizes the prefix it will attempt to
|
||||
// satisfy the request. If it is not recognizable, and no damage has occurred
|
||||
// the request can be passed through to the other handlers. This is a low
|
||||
// probability event; if a request is matched it is normally expected to be
|
||||
// handled
|
||||
IHttpAgentHandler agentHandler;
|
||||
|
||||
if (TryGetAgentHandler(request, response, out agentHandler))
|
||||
{
|
||||
if (HandleAgentRequest(agentHandler, request, response))
|
||||
{
|
||||
requestEndTick = Environment.TickCount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// // This is the REST agent interface. We require an agent to properly identify
|
||||
// // itself. If the REST handler recognizes the prefix it will attempt to
|
||||
// // satisfy the request. If it is not recognizable, and no damage has occurred
|
||||
// // the request can be passed through to the other handlers. This is a low
|
||||
// // probability event; if a request is matched it is normally expected to be
|
||||
// // handled
|
||||
// IHttpAgentHandler agentHandler;
|
||||
//
|
||||
// if (TryGetAgentHandler(request, response, out agentHandler))
|
||||
// {
|
||||
// if (HandleAgentRequest(agentHandler, request, response))
|
||||
// {
|
||||
// requestEndTick = Environment.TickCount;
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
//response.KeepAlive = true;
|
||||
response.SendChunked = false;
|
||||
@@ -449,9 +465,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.
|
||||
|
||||
@@ -531,8 +545,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
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);
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
|
||||
RequestNumber, Port, request.ContentType, request.HttpMethod, request.Url.PathAndQuery, request.RemoteIPEndPoint);
|
||||
|
||||
buffer = HandleHTTPRequest(request, response);
|
||||
break;
|
||||
@@ -543,8 +557,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
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);
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
|
||||
RequestNumber, Port, request.ContentType, request.HttpMethod, request.Url.PathAndQuery, request.RemoteIPEndPoint);
|
||||
|
||||
buffer = HandleLLSDRequests(request, response);
|
||||
break;
|
||||
@@ -563,9 +577,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 +585,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);
|
||||
@@ -643,14 +651,90 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (tickdiff > 3000)
|
||||
{
|
||||
m_log.InfoFormat(
|
||||
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms",
|
||||
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
|
||||
RequestNumber,
|
||||
requestMethod,
|
||||
uriString,
|
||||
requestHandler != null ? requestHandler.Name : "",
|
||||
requestHandler != null ? requestHandler.Description : "",
|
||||
request.RemoteIPEndPoint.ToString(),
|
||||
request.RemoteIPEndPoint,
|
||||
tickdiff);
|
||||
}
|
||||
else if (DebugLevel >= 4)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms",
|
||||
RequestNumber,
|
||||
Port,
|
||||
tickdiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}",
|
||||
RequestNumber,
|
||||
Port,
|
||||
request.HttpMethod,
|
||||
request.Url.PathAndQuery,
|
||||
requestHandler.Name,
|
||||
requestHandler.Description,
|
||||
request.RemoteIPEndPoint);
|
||||
|
||||
if (DebugLevel >= 5)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingToContentTypeHandler(OSHttpRequest request)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
|
||||
RequestNumber,
|
||||
Port,
|
||||
request.ContentType,
|
||||
request.HttpMethod,
|
||||
request.Url.PathAndQuery,
|
||||
request.RemoteIPEndPoint);
|
||||
|
||||
if (DebugLevel >= 5)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}",
|
||||
RequestNumber,
|
||||
Port,
|
||||
request.HttpMethod,
|
||||
request.Url.PathAndQuery,
|
||||
request.RemoteIPEndPoint);
|
||||
|
||||
if (DebugLevel >= 5)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingInDetail(OSHttpRequest request)
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8))
|
||||
{
|
||||
string output;
|
||||
|
||||
if (DebugLevel == 5)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,24 +830,24 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler)
|
||||
{
|
||||
agentHandler = null;
|
||||
|
||||
lock (m_agentHandlers)
|
||||
{
|
||||
foreach (IHttpAgentHandler handler in m_agentHandlers.Values)
|
||||
{
|
||||
if (handler.Match(request, response))
|
||||
{
|
||||
agentHandler = handler;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler)
|
||||
// {
|
||||
// agentHandler = null;
|
||||
//
|
||||
// lock (m_agentHandlers)
|
||||
// {
|
||||
// foreach (IHttpAgentHandler handler in m_agentHandlers.Values)
|
||||
// {
|
||||
// if (handler.Match(request, response))
|
||||
// {
|
||||
// agentHandler = handler;
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Try all the registered xmlrpc handlers when an xmlrpc request is received.
|
||||
@@ -1688,21 +1772,21 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
m_pollHandlers.Remove(path);
|
||||
}
|
||||
|
||||
public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler)
|
||||
{
|
||||
lock (m_agentHandlers)
|
||||
{
|
||||
IHttpAgentHandler foundHandler;
|
||||
|
||||
if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler)
|
||||
{
|
||||
m_agentHandlers.Remove(agent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler)
|
||||
// {
|
||||
// lock (m_agentHandlers)
|
||||
// {
|
||||
// IHttpAgentHandler foundHandler;
|
||||
//
|
||||
// if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler)
|
||||
// {
|
||||
// m_agentHandlers.Remove(agent);
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
|
||||
public void RemoveXmlRPCHandler(string method)
|
||||
{
|
||||
|
||||
@@ -41,10 +41,10 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
uint Port { get; }
|
||||
bool UseSSL { get; }
|
||||
|
||||
// Note that the agent string is provided simply to differentiate
|
||||
// the handlers - it is NOT required to be an actual agent header
|
||||
// value.
|
||||
bool AddAgentHandler(string agent, IHttpAgentHandler handler);
|
||||
// // Note that the agent string is provided simply to differentiate
|
||||
// // the handlers - it is NOT required to be an actual agent header
|
||||
// // value.
|
||||
// bool AddAgentHandler(string agent, IHttpAgentHandler handler);
|
||||
|
||||
/// <summary>
|
||||
/// Add a handler for an HTTP request.
|
||||
@@ -106,13 +106,13 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
|
||||
bool SetDefaultLLSDHandler(DefaultLLSDMethod handler);
|
||||
|
||||
/// <summary>
|
||||
/// Remove the agent if it is registered.
|
||||
/// </summary>
|
||||
/// <param name="agent"></param>
|
||||
/// <param name="handler"></param>
|
||||
/// <returns></returns>
|
||||
bool RemoveAgentHandler(string agent, IHttpAgentHandler handler);
|
||||
// /// <summary>
|
||||
// /// Remove the agent if it is registered.
|
||||
// /// </summary>
|
||||
// /// <param name="agent"></param>
|
||||
// /// <param name="handler"></param>
|
||||
// /// <returns></returns>
|
||||
// bool RemoveAgentHandler(string agent, IHttpAgentHandler handler);
|
||||
|
||||
/// <summary>
|
||||
/// Remove an HTTP handler
|
||||
|
||||
@@ -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;
|
||||
@@ -47,9 +48,12 @@ namespace OpenSim.Framework.Servers
|
||||
/// Control the printing of certain debug messages.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If DebugLevel >= 1, then short warnings are logged when receiving bad input data.
|
||||
/// If DebugLevel >= 2, then long warnings are logged when receiving bad input data.
|
||||
/// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged.
|
||||
/// If DebugLevel >= 1 then short warnings are logged when receiving bad input data.
|
||||
/// If DebugLevel >= 2 then long warnings are logged when receiving bad input data.
|
||||
/// If DebugLevel >= 3 then short notices about all incoming non-poll HTTP requests are logged.
|
||||
/// If DebugLevel >= 4 then the time taken to fulfill the request is logged.
|
||||
/// If DebugLevel >= 5 then the start of the body of incoming non-poll HTTP requests will be logged.
|
||||
/// If DebugLevel >= 6 then the entire body of incoming non-poll HTTP requests will be logged.
|
||||
/// </remarks>
|
||||
public static int DebugLevel
|
||||
{
|
||||
@@ -101,17 +105,28 @@ namespace OpenSim.Framework.Servers
|
||||
get { return new Dictionary<uint, BaseHttpServer>(m_Servers); }
|
||||
}
|
||||
|
||||
|
||||
public static void RegisterHttpConsoleCommands(ICommandConsole console)
|
||||
{
|
||||
console.Commands.AddCommand(
|
||||
"Debug", false, "debug http", "debug http [<level>]",
|
||||
"Turn on inbound non-poll http request debugging.",
|
||||
"If level <= 0, then no extra logging is done.\n"
|
||||
+ "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 no level is specified then the current level is returned.",
|
||||
"Comms", false, "show http-handlers",
|
||||
"show http-handlers",
|
||||
"Show all registered http handlers", HandleShowHttpHandlersCommand);
|
||||
|
||||
console.Commands.AddCommand(
|
||||
"Debug", false, "debug http", "debug http <in|out|all> [<level>]",
|
||||
"Turn on http request logging.",
|
||||
"If in or all and\n"
|
||||
+ " level <= 0 then no extra logging is done.\n"
|
||||
+ " level >= 1 then short warnings are logged when receiving bad input data.\n"
|
||||
+ " level >= 2 then long warnings are logged when receiving bad input data.\n"
|
||||
+ " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n"
|
||||
+ " level >= 4 then the time taken to fulfill the request is logged.\n"
|
||||
+ " level >= 5 then a sample from the beginning of the incoming data is logged.\n"
|
||||
+ " level >= 6 then the entire incoming data is logged.\n"
|
||||
+ " no level is specified then the current level is returned.\n\n"
|
||||
+ "If out or all and\n"
|
||||
+ " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n"
|
||||
+ " level >= 4 then the time taken to fulfill the request is logged.\n",
|
||||
HandleDebugHttpCommand);
|
||||
}
|
||||
|
||||
@@ -119,25 +134,120 @@ namespace OpenSim.Framework.Servers
|
||||
/// Turn on some debugging values for OpenSim.
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
private static void HandleDebugHttpCommand(string module, string[] args)
|
||||
private static void HandleDebugHttpCommand(string module, string[] cmdparams)
|
||||
{
|
||||
if (args.Length == 3)
|
||||
if (cmdparams.Length < 3)
|
||||
{
|
||||
int newDebug;
|
||||
if (int.TryParse(args[2], out newDebug))
|
||||
{
|
||||
MainServer.DebugLevel = newDebug;
|
||||
MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
|
||||
}
|
||||
MainConsole.Instance.Output("Usage: debug http <in|out|all> 0..6");
|
||||
return;
|
||||
}
|
||||
else if (args.Length == 2)
|
||||
|
||||
bool inReqs = false;
|
||||
bool outReqs = false;
|
||||
bool allReqs = false;
|
||||
|
||||
string subCommand = cmdparams[2];
|
||||
|
||||
if (subCommand.ToLower() == "in")
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel);
|
||||
inReqs = true;
|
||||
}
|
||||
else if (subCommand.ToLower() == "out")
|
||||
{
|
||||
outReqs = true;
|
||||
}
|
||||
else if (subCommand.ToLower() == "all")
|
||||
{
|
||||
allReqs = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: debug http 0..3");
|
||||
MainConsole.Instance.Output("You must specify in, out or all");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmdparams.Length >= 4)
|
||||
{
|
||||
string rawNewDebug = cmdparams[3];
|
||||
int newDebug;
|
||||
|
||||
if (!int.TryParse(rawNewDebug, out newDebug))
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("{0} is not a valid debug level", rawNewDebug);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newDebug < 0 || newDebug > 5)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("{0} is outside the valid debug level range of 0..5", newDebug);
|
||||
return;
|
||||
}
|
||||
|
||||
if (allReqs || inReqs)
|
||||
{
|
||||
MainServer.DebugLevel = newDebug;
|
||||
MainConsole.Instance.OutputFormat("IN debug level set to {0}", newDebug);
|
||||
}
|
||||
|
||||
if (allReqs || outReqs)
|
||||
{
|
||||
WebUtil.DebugLevel = newDebug;
|
||||
MainConsole.Instance.OutputFormat("OUT debug level set to {0}", newDebug);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (allReqs || inReqs)
|
||||
MainConsole.Instance.OutputFormat("Current IN debug level is {0}", MainServer.DebugLevel);
|
||||
|
||||
if (allReqs || outReqs)
|
||||
MainConsole.Instance.OutputFormat("Current OUT debug level is {0}", WebUtil.DebugLevel);
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -53,10 +53,18 @@ namespace OpenSim.Framework
|
||||
LogManager.GetLogger(
|
||||
MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Control the printing of certain debug messages.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If DebugLevel >= 3 then short notices about outgoing HTTP requests are logged.
|
||||
/// </remarks>
|
||||
public static int DebugLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Request number for diagnostic purposes.
|
||||
/// </summary>
|
||||
public static int RequestNumber = 0;
|
||||
public static int RequestNumber { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// this is the header field used to communicate the local request id
|
||||
@@ -146,7 +154,11 @@ namespace OpenSim.Framework
|
||||
private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
|
||||
{
|
||||
int reqnum = RequestNumber++;
|
||||
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
||||
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} ServiceOSD {1} {2} (timeout {3}, compressed {4})",
|
||||
reqnum, method, url, timeout, compressed);
|
||||
|
||||
string errorMessage = "unknown error";
|
||||
int tickstart = Util.EnvironmentTickCount();
|
||||
@@ -229,7 +241,7 @@ namespace OpenSim.Framework
|
||||
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||
if (tickdiff > LongCallTime)
|
||||
m_log.InfoFormat(
|
||||
"[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
"[WEB UTIL]: Slow ServiceOSD request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
reqnum,
|
||||
method,
|
||||
url,
|
||||
@@ -238,10 +250,14 @@ namespace OpenSim.Framework
|
||||
strBuffer != null
|
||||
? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
|
||||
: "");
|
||||
else if (DebugLevel >= 4)
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
|
||||
reqnum, tickdiff, tickdata);
|
||||
}
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage);
|
||||
"[WEB UTIL]: ServiceOSD request {0} {1} {2} FAILED: {3}", reqnum, url, method, errorMessage);
|
||||
|
||||
return ErrorResponseMap(errorMessage);
|
||||
}
|
||||
@@ -317,7 +333,11 @@ namespace OpenSim.Framework
|
||||
{
|
||||
int reqnum = RequestNumber++;
|
||||
string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
|
||||
// m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
|
||||
|
||||
if (DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} ServiceForm {1} {2} (timeout {3})",
|
||||
reqnum, method, url, timeout);
|
||||
|
||||
string errorMessage = "unknown error";
|
||||
int tickstart = Util.EnvironmentTickCount();
|
||||
@@ -380,7 +400,7 @@ namespace OpenSim.Framework
|
||||
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||
if (tickdiff > LongCallTime)
|
||||
m_log.InfoFormat(
|
||||
"[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
"[WEB UTIL]: Slow ServiceForm request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
reqnum,
|
||||
method,
|
||||
url,
|
||||
@@ -389,9 +409,13 @@ namespace OpenSim.Framework
|
||||
queryString != null
|
||||
? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
|
||||
: "");
|
||||
else if (DebugLevel >= 4)
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
|
||||
reqnum, tickdiff, tickdata);
|
||||
}
|
||||
|
||||
m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
|
||||
m_log.WarnFormat("[WEB UTIL]: ServiceForm request {0} {1} {2} failed: {2}", reqnum, method, url, errorMessage);
|
||||
|
||||
return ErrorResponseMap(errorMessage);
|
||||
}
|
||||
@@ -643,7 +667,6 @@ namespace OpenSim.Framework
|
||||
/// <returns></returns>
|
||||
public static string[] GetPreferredImageTypes(string accept)
|
||||
{
|
||||
|
||||
if (accept == null || accept == string.Empty)
|
||||
return new string[0];
|
||||
|
||||
@@ -695,13 +718,15 @@ namespace OpenSim.Framework
|
||||
string requestUrl, TRequest obj, Action<TResponse> action)
|
||||
{
|
||||
int reqnum = WebUtil.RequestNumber++;
|
||||
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
||||
|
||||
if (WebUtil.DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} AsynchronousRequestObject {1} {2}",
|
||||
reqnum, verb, requestUrl);
|
||||
|
||||
int tickstart = Util.EnvironmentTickCount();
|
||||
int tickdata = 0;
|
||||
|
||||
// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
|
||||
|
||||
Type type = typeof(TRequest);
|
||||
|
||||
WebRequest request = WebRequest.Create(requestUrl);
|
||||
@@ -854,7 +879,7 @@ namespace OpenSim.Framework
|
||||
}
|
||||
|
||||
m_log.InfoFormat(
|
||||
"[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
"[ASYNC REQUEST]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
reqnum,
|
||||
verb,
|
||||
requestUrl,
|
||||
@@ -862,6 +887,12 @@ namespace OpenSim.Framework
|
||||
tickdata,
|
||||
originalRequest);
|
||||
}
|
||||
else if (WebUtil.DebugLevel >= 4)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
|
||||
reqnum, tickdiff, tickdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -882,7 +913,11 @@ namespace OpenSim.Framework
|
||||
public static string MakeRequest(string verb, string requestUrl, string obj)
|
||||
{
|
||||
int reqnum = WebUtil.RequestNumber++;
|
||||
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
||||
|
||||
if (WebUtil.DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} SynchronousRestForms {1} {2}",
|
||||
reqnum, verb, requestUrl);
|
||||
|
||||
int tickstart = Util.EnvironmentTickCount();
|
||||
int tickdata = 0;
|
||||
@@ -967,13 +1002,17 @@ namespace OpenSim.Framework
|
||||
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||
if (tickdiff > WebUtil.LongCallTime)
|
||||
m_log.InfoFormat(
|
||||
"[FORMS]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
"[FORMS]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
reqnum,
|
||||
verb,
|
||||
requestUrl,
|
||||
tickdiff,
|
||||
tickdata,
|
||||
obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
|
||||
else if (WebUtil.DebugLevel >= 4)
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
|
||||
reqnum, tickdiff, tickdata);
|
||||
|
||||
return respstring;
|
||||
}
|
||||
@@ -998,7 +1037,11 @@ namespace OpenSim.Framework
|
||||
public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj)
|
||||
{
|
||||
int reqnum = WebUtil.RequestNumber++;
|
||||
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
||||
|
||||
if (WebUtil.DebugLevel >= 3)
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} SynchronousRestObject {1} {2}",
|
||||
reqnum, verb, requestUrl);
|
||||
|
||||
int tickstart = Util.EnvironmentTickCount();
|
||||
int tickdata = 0;
|
||||
@@ -1111,7 +1154,7 @@ namespace OpenSim.Framework
|
||||
}
|
||||
|
||||
m_log.InfoFormat(
|
||||
"[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
"[SynchronousRestObjectRequester]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||
reqnum,
|
||||
verb,
|
||||
requestUrl,
|
||||
@@ -1119,6 +1162,12 @@ namespace OpenSim.Framework
|
||||
tickdata,
|
||||
originalRequest);
|
||||
}
|
||||
else if (WebUtil.DebugLevel >= 4)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
|
||||
reqnum, tickdiff, tickdata);
|
||||
}
|
||||
|
||||
return deserial;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
public class AttachmentsModuleTests : OpenSimTestCase
|
||||
{
|
||||
private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
|
||||
private OSChatMessage m_osChatMessageReceived;
|
||||
// private OSChatMessage m_osChatMessageReceived;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureInit()
|
||||
@@ -83,7 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
{
|
||||
// Console.WriteLine("Got chat [{0}]", oscm.Message);
|
||||
|
||||
m_osChatMessageReceived = oscm;
|
||||
// m_osChatMessageReceived = oscm;
|
||||
m_chatEvent.Set();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -323,6 +323,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate assorted conditions
|
||||
string reason = string.Empty;
|
||||
if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
|
||||
{
|
||||
sp.ControllingClient.SendTeleportFailed(reason);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// This is it
|
||||
//
|
||||
@@ -354,6 +362,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing to validate here
|
||||
protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
|
||||
{
|
||||
reason = String.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance is within the max transfer distance.
|
||||
/// </summary>
|
||||
@@ -568,7 +583,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
|
||||
|
||||
if (!UpdateAgent(reg, finalDestination, agent))
|
||||
if (!UpdateAgent(reg, finalDestination, agent, sp))
|
||||
{
|
||||
// Region doesn't take it
|
||||
m_log.WarnFormat(
|
||||
@@ -695,7 +710,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
return success;
|
||||
}
|
||||
|
||||
protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent)
|
||||
protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp)
|
||||
{
|
||||
return Scene.SimulationService.UpdateAgent(finalDestination, agent);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
|
||||
private GatekeeperServiceConnector m_GatekeeperConnector;
|
||||
|
||||
protected bool m_RestrictAppearanceAbroad;
|
||||
protected string m_AccountName;
|
||||
protected List<AvatarAppearance> m_ExportedAppearances;
|
||||
protected List<AvatarAttachment> m_Attachs;
|
||||
|
||||
protected List<AvatarAppearance> ExportedAppearance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_ExportedAppearances != null)
|
||||
return m_ExportedAppearances;
|
||||
|
||||
m_ExportedAppearances = new List<AvatarAppearance>();
|
||||
m_Attachs = new List<AvatarAttachment>();
|
||||
|
||||
string[] names = m_AccountName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (string name in names)
|
||||
{
|
||||
string[] parts = name.Trim().Split();
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", name);
|
||||
return null;
|
||||
}
|
||||
UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]);
|
||||
if (account == null)
|
||||
{
|
||||
m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName);
|
||||
return null;
|
||||
}
|
||||
AvatarAppearance a = Scene.AvatarService.GetAppearance(account.PrincipalID);
|
||||
if (a != null)
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", name);
|
||||
|
||||
foreach (AvatarAttachment att in a.GetAttachments())
|
||||
{
|
||||
InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID);
|
||||
item = Scene.InventoryService.GetItem(item);
|
||||
if (item != null)
|
||||
a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID);
|
||||
else
|
||||
m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory {1}", att.ItemID, name);
|
||||
}
|
||||
|
||||
m_ExportedAppearances.Add(a);
|
||||
m_Attachs.AddRange(a.GetAttachments());
|
||||
}
|
||||
|
||||
return m_ExportedAppearances;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region ISharedRegionModule
|
||||
|
||||
public override string Name
|
||||
@@ -72,8 +126,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
{
|
||||
IConfig transferConfig = source.Configs["EntityTransfer"];
|
||||
if (transferConfig != null)
|
||||
{
|
||||
m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0);
|
||||
|
||||
m_RestrictAppearanceAbroad = transferConfig.GetBoolean("RestrictAppearanceAbroad", false);
|
||||
if (m_RestrictAppearanceAbroad)
|
||||
{
|
||||
m_AccountName = transferConfig.GetString("AccountForAppearance", string.Empty);
|
||||
if (m_AccountName == string.Empty)
|
||||
m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is on, but no account has been given for avatar appearance!");
|
||||
}
|
||||
}
|
||||
|
||||
InitialiseCommon(source);
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
|
||||
}
|
||||
@@ -195,6 +259,124 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||
return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout);
|
||||
}
|
||||
|
||||
protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
|
||||
{
|
||||
reason = "Please wear your grid's allowed appearance before teleporting to another grid";
|
||||
if (!m_RestrictAppearanceAbroad)
|
||||
return true;
|
||||
|
||||
// The rest is only needed for controlling appearance
|
||||
|
||||
int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
||||
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
||||
{
|
||||
// this user is going to another grid
|
||||
if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID))
|
||||
{
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance");
|
||||
|
||||
// Check wearables
|
||||
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
|
||||
{
|
||||
for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++)
|
||||
{
|
||||
if (sp.Appearance.Wearables[i] == null)
|
||||
continue;
|
||||
|
||||
bool found = false;
|
||||
foreach (AvatarAppearance a in ExportedAppearance)
|
||||
if (a.Wearables[i] != null)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
|
||||
return false;
|
||||
}
|
||||
|
||||
found = false;
|
||||
foreach (AvatarAppearance a in ExportedAppearance)
|
||||
if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check attachments
|
||||
foreach (AvatarAttachment att in sp.Appearance.GetAttachments())
|
||||
{
|
||||
bool found = false;
|
||||
foreach (AvatarAttachment att2 in m_Attachs)
|
||||
{
|
||||
if (att2.AssetID == att.AssetID)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Attachment not allowed to go outside {0}", att.AttachPoint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reason = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//protected override bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agentData, ScenePresence sp)
|
||||
//{
|
||||
// int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
|
||||
// if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
|
||||
// {
|
||||
// // this user is going to another grid
|
||||
// if (m_RestrictAppearanceAbroad && Scene.UserManagementModule.IsLocalGridUser(agentData.AgentID))
|
||||
// {
|
||||
// // We need to strip the agent off its appearance
|
||||
// m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Sending generic appearance");
|
||||
|
||||
// // Delete existing npc attachments
|
||||
// Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false);
|
||||
|
||||
// // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments
|
||||
// AvatarAppearance newAppearance = new AvatarAppearance(ExportedAppearance, true);
|
||||
// sp.Appearance = newAppearance;
|
||||
|
||||
// // Rez needed npc attachments
|
||||
// Scene.AttachmentsModule.RezAttachments(sp);
|
||||
|
||||
|
||||
// IAvatarFactoryModule module = Scene.RequestModuleInterface<IAvatarFactoryModule>();
|
||||
// //module.SendAppearance(sp.UUID);
|
||||
// module.RequestRebake(sp, false);
|
||||
|
||||
// Scene.AttachmentsModule.CopyAttachments(sp, agentData);
|
||||
// agentData.Appearance = sp.Appearance;
|
||||
// }
|
||||
// }
|
||||
|
||||
// foreach (AvatarAttachment a in agentData.Appearance.GetAttachments())
|
||||
// m_log.DebugFormat("[XXX]: {0}-{1}", a.ItemID, a.AssetID);
|
||||
|
||||
|
||||
// return base.UpdateAgent(reg, finalDestination, agentData, sp);
|
||||
//}
|
||||
|
||||
public override void TeleportHome(UUID id, IClientAPI client)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
|
||||
@@ -71,19 +71,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
|
||||
#region Internal functions
|
||||
|
||||
public AssetBase FetchAsset(string url, UUID assetID)
|
||||
public AssetMetadata FetchMetadata(string url, UUID assetID)
|
||||
{
|
||||
if (!url.EndsWith("/") && !url.EndsWith("="))
|
||||
url = url + "/";
|
||||
|
||||
AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString());
|
||||
AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString());
|
||||
|
||||
if (asset != null)
|
||||
{
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url);
|
||||
return asset;
|
||||
}
|
||||
return null;
|
||||
if (meta != null)
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url);
|
||||
else
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url);
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
public bool PostAsset(string url, AssetBase asset)
|
||||
@@ -93,6 +93,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
if (!url.EndsWith("/") && !url.EndsWith("="))
|
||||
url = url + "/";
|
||||
|
||||
bool success = true;
|
||||
// See long comment in AssetCache.AddAsset
|
||||
if (!asset.Temporary || asset.Local)
|
||||
{
|
||||
@@ -103,14 +104,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
// not having a global naming infrastructure
|
||||
AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID);
|
||||
Copy(asset, asset1);
|
||||
try
|
||||
{
|
||||
asset1.ID = url + asset.ID;
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_log.Warn("[HG ASSET MAPPER]: Oops.");
|
||||
}
|
||||
asset1.ID = url + asset.ID;
|
||||
|
||||
AdjustIdentifiers(asset1.Metadata);
|
||||
if (asset1.Metadata.Type == (sbyte)AssetType.Object)
|
||||
@@ -118,11 +112,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
else
|
||||
asset1.Data = asset.Data;
|
||||
|
||||
m_scene.AssetService.Store(asset1);
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
|
||||
string id = m_scene.AssetService.Store(asset1);
|
||||
if (id == string.Empty)
|
||||
{
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID);
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
else
|
||||
m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache.");
|
||||
|
||||
@@ -222,28 +222,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
|
||||
public void Get(UUID assetID, UUID ownerID, string userAssetURL)
|
||||
{
|
||||
// Get the item from the remote asset server onto the local AssetCache
|
||||
// and place an entry in m_assetMap
|
||||
// Get the item from the remote asset server onto the local AssetService
|
||||
|
||||
m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL);
|
||||
AssetBase asset = FetchAsset(userAssetURL, assetID);
|
||||
AssetMetadata meta = FetchMetadata(userAssetURL, assetID);
|
||||
if (meta == null)
|
||||
return;
|
||||
|
||||
if (asset != null)
|
||||
{
|
||||
// OK, now fetch the inside.
|
||||
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
|
||||
HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL);
|
||||
uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
|
||||
if (ids.ContainsKey(assetID))
|
||||
ids.Remove(assetID);
|
||||
foreach (UUID uuid in ids.Keys)
|
||||
FetchAsset(userAssetURL, uuid);
|
||||
// The act of gathering UUIDs downloads the assets from the remote server
|
||||
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
|
||||
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
|
||||
uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids);
|
||||
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL);
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", assetID, userAssetURL);
|
||||
|
||||
}
|
||||
else
|
||||
m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL);
|
||||
}
|
||||
|
||||
|
||||
@@ -257,19 +248,23 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
if (asset != null)
|
||||
{
|
||||
Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
|
||||
HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty);
|
||||
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
|
||||
uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
|
||||
bool success = false;
|
||||
foreach (UUID uuid in ids.Keys)
|
||||
{
|
||||
asset = m_scene.AssetService.Get(uuid.ToString());
|
||||
if (asset == null)
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid);
|
||||
else
|
||||
PostAsset(userAssetURL, asset);
|
||||
success = PostAsset(userAssetURL, asset);
|
||||
}
|
||||
|
||||
// maybe all pieces got there...
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
|
||||
// maybe all pieces got there...
|
||||
if (!success)
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL);
|
||||
else
|
||||
m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
|
||||
|
||||
}
|
||||
else
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -26,32 +26,36 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||
namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
{
|
||||
public class HGUuidGatherer : UuidGatherer
|
||||
public class DynamicTexture : IDynamicTexture
|
||||
{
|
||||
protected string m_assetServerURL;
|
||||
protected HGAssetMapper m_assetMapper;
|
||||
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 HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache)
|
||||
public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
|
||||
{
|
||||
m_assetMapper = assMap;
|
||||
m_assetServerURL = assetServerURL;
|
||||
InputCommands = inputCommands;
|
||||
InputParams = inputParams;
|
||||
Data = data;
|
||||
Size = size;
|
||||
IsReuseable = isReuseable;
|
||||
}
|
||||
|
||||
protected override AssetBase GetAsset(UUID uuid)
|
||||
public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
|
||||
{
|
||||
if (string.Empty == m_assetServerURL)
|
||||
return m_assetCache.Get(uuid.ToString());
|
||||
else
|
||||
return m_assetMapper.FetchAsset(m_assetServerURL, uuid);
|
||||
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
|
||||
|
||||
@@ -211,6 +211,23 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
|
||||
RegisterScriptInvocation(target, mi);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterScriptInvocations(IRegionModuleBase target)
|
||||
{
|
||||
foreach(MethodInfo method in target.GetType().GetMethods(
|
||||
BindingFlags.Public | BindingFlags.Instance |
|
||||
BindingFlags.Static))
|
||||
{
|
||||
if(method.GetCustomAttributes(
|
||||
typeof(ScriptInvocationAttribute), true).Any())
|
||||
{
|
||||
if(method.IsStatic)
|
||||
RegisterScriptInvocation(target.GetType(), method);
|
||||
else
|
||||
RegisterScriptInvocation(target, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Delegate[] GetScriptInvocationList()
|
||||
{
|
||||
@@ -313,6 +330,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterConstants(IRegionModuleBase target)
|
||||
{
|
||||
foreach (FieldInfo field in target.GetType().GetFields(
|
||||
BindingFlags.Public | BindingFlags.Static |
|
||||
BindingFlags.Instance))
|
||||
{
|
||||
if (field.GetCustomAttributes(
|
||||
typeof(ScriptConstantAttribute), true).Any())
|
||||
{
|
||||
RegisterConstant(field.Name, field.GetValue(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to check for a registered constant
|
||||
/// </summary>
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
|
||||
|
||||
private bool m_Enabled = false;
|
||||
|
||||
private AssetPermissions m_AssetPerms;
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
@@ -128,6 +130,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
|
||||
if (m_LocalAssetServiceURI != string.Empty)
|
||||
m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/');
|
||||
|
||||
IConfig hgConfig = source.Configs["HGAssetService"];
|
||||
m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null
|
||||
|
||||
m_Enabled = true;
|
||||
m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled");
|
||||
}
|
||||
@@ -206,14 +211,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
|
||||
asset = m_HGService.Get(id);
|
||||
if (asset != null)
|
||||
{
|
||||
// Now store it locally
|
||||
// For now, let me just do it for textures and scripts
|
||||
if (((AssetType)asset.Type == AssetType.Texture) ||
|
||||
((AssetType)asset.Type == AssetType.LSLBytecode) ||
|
||||
((AssetType)asset.Type == AssetType.LSLText))
|
||||
{
|
||||
// Now store it locally, if allowed
|
||||
if (m_AssetPerms.AllowedImport(asset.Type))
|
||||
m_GridService.Store(asset);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -328,7 +330,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
|
||||
|
||||
string id = string.Empty;
|
||||
if (IsHG(asset.ID))
|
||||
id = m_HGService.Store(asset);
|
||||
{
|
||||
if (m_AssetPerms.AllowedExport(asset.Type))
|
||||
id = m_HGService.Store(asset);
|
||||
else
|
||||
return String.Empty;
|
||||
}
|
||||
else
|
||||
id = m_GridService.Store(asset);
|
||||
|
||||
|
||||
@@ -204,8 +204,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
|
||||
public byte[] GetData(string id)
|
||||
{
|
||||
// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id);
|
||||
|
||||
AssetBase asset = m_Cache.Get(id);
|
||||
|
||||
AssetBase asset = null;
|
||||
|
||||
if (m_Cache != null)
|
||||
asset = m_Cache.Get(id);
|
||||
|
||||
if (asset != null)
|
||||
return asset.Data;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.Threading;
|
||||
using log4net.Config;
|
||||
using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset;
|
||||
using OpenSim.Tests.Common;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AssetConnectorsTests : OpenSimTestCase
|
||||
{
|
||||
[Test]
|
||||
public void TestAddAsset()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
|
||||
config.AddConfig("AssetService");
|
||||
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
|
||||
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
|
||||
|
||||
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
|
||||
lasc.Initialise(config);
|
||||
|
||||
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
|
||||
lasc.Store(a1);
|
||||
|
||||
AssetBase retreivedA1 = lasc.Get(a1.ID);
|
||||
Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID));
|
||||
Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID));
|
||||
Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length));
|
||||
|
||||
AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID);
|
||||
Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID));
|
||||
|
||||
byte[] retrievedA1Data = lasc.GetData(a1.ID);
|
||||
Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length));
|
||||
|
||||
// TODO: Add cache and check that this does receive a copy of the asset
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddTemporaryAsset()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
|
||||
config.AddConfig("AssetService");
|
||||
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
|
||||
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
|
||||
|
||||
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
|
||||
lasc.Initialise(config);
|
||||
|
||||
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
|
||||
a1.Temporary = true;
|
||||
|
||||
lasc.Store(a1);
|
||||
|
||||
Assert.That(lasc.Get(a1.ID), Is.Null);
|
||||
Assert.That(lasc.GetData(a1.ID), Is.Null);
|
||||
Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
|
||||
|
||||
// TODO: Add cache and check that this does receive a copy of the asset
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddLocalAsset()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
|
||||
config.AddConfig("AssetService");
|
||||
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
|
||||
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
|
||||
|
||||
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
|
||||
lasc.Initialise(config);
|
||||
|
||||
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
|
||||
a1.Local = true;
|
||||
|
||||
lasc.Store(a1);
|
||||
|
||||
Assert.That(lasc.Get(a1.ID), Is.Null);
|
||||
Assert.That(lasc.GetData(a1.ID), Is.Null);
|
||||
Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
|
||||
|
||||
// TODO: Add cache and check that this does receive a copy of the asset
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,11 +43,15 @@ 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()
|
||||
|
||||
[SetUp]
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.AddConfig("GridService");
|
||||
@@ -71,8 +75,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
|
||||
SetUp();
|
||||
|
||||
// Create 4 regions
|
||||
GridRegion r1 = new GridRegion();
|
||||
r1.RegionName = "Test Region 1";
|
||||
|
||||
@@ -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,41 @@ 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()
|
||||
public override void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
// FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later
|
||||
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 +137,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 +179,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 +204,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 +287,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 +324,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 +379,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 +405,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 +432,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 +479,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 +538,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 +577,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 +687,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 +723,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);
|
||||
|
||||
@@ -74,6 +74,14 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="methods"></param>
|
||||
void RegisterScriptInvocation(Type target, string[] methods);
|
||||
|
||||
/// <summary>
|
||||
/// Automatically register script invocations by checking for methods
|
||||
/// with <see cref="ScriptInvocationAttribute"/>. Should only check
|
||||
/// public methods.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
void RegisterScriptInvocations(IRegionModuleBase target);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of all registered script calls
|
||||
/// </summary>
|
||||
@@ -96,11 +104,43 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="key"></param>
|
||||
void DispatchReply(UUID scriptId, int code, string text, string key);
|
||||
|
||||
/// For constants
|
||||
/// <summary>
|
||||
/// Operation to for a region module to register a constant to be used
|
||||
/// by the script engine
|
||||
/// </summary>
|
||||
/// <param name="cname">
|
||||
/// The name of the constant. LSL convention is for constant names to
|
||||
/// be uppercase.
|
||||
/// </param>
|
||||
/// <param name="value">
|
||||
/// The value of the constant. Should be of a type that can be
|
||||
/// converted to one of <see cref="OpenSim.Region.ScriptEngine.Shared.LSL_Types"/>
|
||||
/// </param>
|
||||
void RegisterConstant(string cname, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Automatically register all constants on a region module by
|
||||
/// checking for fields with <see cref="ScriptConstantAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
void RegisterConstants(IRegionModuleBase target);
|
||||
|
||||
/// <summary>
|
||||
/// Operation to check for a registered constant
|
||||
/// </summary>
|
||||
/// <param name="cname">Name of constant</param>
|
||||
/// <returns>Value of constant or null if none found.</returns>
|
||||
object LookupModConstant(string cname);
|
||||
|
||||
// For use ONLY by the script API
|
||||
void RaiseEvent(UUID script, string id, string module, string command, string key);
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class ScriptInvocationAttribute : Attribute
|
||||
{ }
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class ScriptConstantAttribute : Attribute
|
||||
{ }
|
||||
}
|
||||
|
||||
@@ -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,22 +132,74 @@ 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);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after <see cref="OpenSim.IApplicationPlugin.PostInitialise"/>
|
||||
/// has been called for all <see cref="OpenSim.IApplicationPlugin"/>
|
||||
/// loaded via <see cref="OpenSim.OpenSimBase.LoadPlugins"/>.
|
||||
/// Handlers for this event are typically used to parse the arguments
|
||||
/// from <see cref="OnPluginConsoleDelegate"/> in order to process or
|
||||
/// filter the arguments and pass them onto <see cref="OpenSim.Region.CoreModules.Framework.InterfaceCommander.Commander.ProcessConsoleCommand"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerOnPluginConsole"/> in
|
||||
/// <see cref="Scene.SendCommandToPlugins"/> via
|
||||
/// <see cref="SceneManager.SendCommandToPluginModules"/> via
|
||||
/// <see cref="OpenSim.OpenSimBase.HandleCommanderCommand"/> via
|
||||
/// <see cref="OpenSim.OpenSimBase.AddPluginCommands"/> via
|
||||
/// <see cref="OpenSim.OpenSimBase.StartupSpecific"/>
|
||||
/// </remarks>
|
||||
public event OnPluginConsoleDelegate OnPluginConsole;
|
||||
|
||||
/// <summary>
|
||||
@@ -117,8 +214,28 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered before the grunt work for adding a root agent to a
|
||||
/// scene has been performed (resuming attachment scripts, physics,
|
||||
/// animations etc.)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered before <see cref="OnMakeRootAgent"/>
|
||||
/// by <see cref="TriggerSetRootAgentScene"/>
|
||||
/// in <see cref="ScenePresence.MakeRootAgent"/>
|
||||
/// via <see cref="Scene.AgentCrossing"/>
|
||||
/// and <see cref="ScenePresence.CompleteMovement"/>
|
||||
/// </remarks>
|
||||
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>
|
||||
@@ -133,13 +250,45 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <summary>
|
||||
/// Fired when an object is touched/grabbed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The originalID is the local ID of the part that was actually touched. The localID itself is always that of
|
||||
/// the root part.
|
||||
/// Triggerd in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/>
|
||||
/// via <see cref="TriggerObjectGrab"/>
|
||||
/// in <see cref="Scene.ProcessObjectGrab"/>
|
||||
/// </remarks>
|
||||
public event ObjectGrabDelegate OnObjectGrab;
|
||||
public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object is being touched/grabbed continuously.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabUpdate"/>
|
||||
/// via <see cref="TriggerObjectGrabbing"/>
|
||||
/// in <see cref="Scene.ProcessObjectGrabUpdate"/>
|
||||
/// </remarks>
|
||||
public event ObjectGrabDelegate OnObjectGrabbing;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object stops being touched/grabbed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnDeGrabObject"/>
|
||||
/// via <see cref="TriggerObjectDeGrab"/>
|
||||
/// in <see cref="Scene.ProcessObjectDeGrab"/>
|
||||
/// </remarks>
|
||||
public event ObjectDeGrabDelegate OnObjectDeGrab;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a script resets.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerScriptReset"/>
|
||||
/// in <see cref="Scene.ProcessScriptReset"/>
|
||||
/// via <see cref="OpenSim.Framework.IClientAPI.OnScriptReset"/>
|
||||
/// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleScriptReset"/>
|
||||
/// </remarks>
|
||||
public event ScriptResetDelegate OnScriptReset;
|
||||
|
||||
public event OnPermissionErrorDelegate OnPermissionError;
|
||||
@@ -149,17 +298,50 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Occurs after OnNewScript.
|
||||
/// Triggered by <see cref="TriggerRezScript"/>
|
||||
/// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>
|
||||
/// </remarks>
|
||||
public event NewRezScript OnRezScript;
|
||||
public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource);
|
||||
|
||||
public delegate void RemoveScript(uint localID, UUID itemID);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a script is removed from an object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerRemoveScript"/>
|
||||
/// in <see cref="Scene.RemoveTaskInventory"/>,
|
||||
/// <see cref="Scene.CreateAgentInventoryItemFromTask"/>,
|
||||
/// <see cref="SceneObjectPartInventory.RemoveScriptInstance"/>,
|
||||
/// <see cref="SceneObjectPartInventory.RemoveInventoryItem"/>
|
||||
/// </remarks>
|
||||
public event RemoveScript OnRemoveScript;
|
||||
|
||||
public delegate void StartScript(uint localID, UUID itemID);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a script starts.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerStartScript"/>
|
||||
/// in <see cref="Scene.SetScriptRunning"/>
|
||||
/// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>,
|
||||
/// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/>
|
||||
/// </remarks>
|
||||
public event StartScript OnStartScript;
|
||||
|
||||
public delegate void StopScript(uint localID, UUID itemID);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a script stops.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerStopScript"/>,
|
||||
/// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>,
|
||||
/// <see cref="SceneObjectPartInventory.StopScriptInstance"/>,
|
||||
/// <see cref="Scene.SetScriptRunning"/>
|
||||
/// </remarks>
|
||||
public event StopScript OnStopScript;
|
||||
|
||||
public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta);
|
||||
@@ -210,6 +392,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Occurs before OnRezScript
|
||||
/// Triggered by <see cref="TriggerNewScript"/>
|
||||
/// in <see cref="Scene.RezScriptFromAgentInventory"/>,
|
||||
/// <see cref="Scene.RezNewScript"/>
|
||||
/// </remarks>
|
||||
public event NewScript OnNewScript;
|
||||
|
||||
@@ -244,6 +429,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset.
|
||||
/// Triggered by <see cref="TriggerUpdateScript"/>
|
||||
/// in <see cref="Scene.CapsUpdateTaskInventoryScriptAsset"/>
|
||||
/// via <see cref="Scene.CapsUpdateTaskInventoryScriptAsset"/>
|
||||
/// via <see cref="OpenSim.Region.ClientStack.Linden.BunchOfCaps.TaskScriptUpdated"/>
|
||||
/// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.OnUpLoad"/>
|
||||
/// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.uploaderCaps"/>
|
||||
/// </remarks>
|
||||
public event UpdateScript OnUpdateScript;
|
||||
|
||||
@@ -269,48 +460,203 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when some scene object properties change.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ScriptChangedEvent is fired when a scene object property that a script might be interested
|
||||
/// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event.
|
||||
/// This is not an indication that the script has changed (see OnUpdateScript for that).
|
||||
/// This event is sent to a script to tell it that some property changed on
|
||||
/// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed .
|
||||
/// </summary>
|
||||
/// Triggered by <see cref="TriggerOnScriptChangedEvent"/>
|
||||
/// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.TeleportAgentWithinRegion"/>,
|
||||
/// <see cref="SceneObjectPart.TriggerScriptChangedEvent"/>
|
||||
/// </remarks>
|
||||
public event ScriptChangedEvent OnScriptChangedEvent;
|
||||
public delegate void ScriptChangedEvent(uint localID, uint change);
|
||||
|
||||
public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a script receives control input from an agent.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerControlEvent"/>
|
||||
/// in <see cref="ScenePresence.SendControlsToScripts"/>
|
||||
/// via <see cref="ScenePresence.HandleAgentUpdate"/>
|
||||
/// via <see cref="OpenSim.Framework.IClientAPI.OnAgentUpdate"/>
|
||||
/// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleAgentUpdate"/>
|
||||
/// </remarks>
|
||||
public event ScriptControlEvent OnScriptControlEvent;
|
||||
|
||||
public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object has arrived within a tolerance distance
|
||||
/// of a motion target.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerAtTargetEvent"/>
|
||||
/// in <see cref="SceneObjectGroup.checkAtTargets"/>
|
||||
/// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
|
||||
/// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
|
||||
/// </remarks>
|
||||
public event ScriptAtTargetEvent OnScriptAtTargetEvent;
|
||||
|
||||
public delegate void ScriptNotAtTargetEvent(uint localID);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object has a motion target but has not arrived
|
||||
/// within a tolerance distance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerNotAtTargetEvent"/>
|
||||
/// in <see cref="SceneObjectGroup.checkAtTargets"/>
|
||||
/// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
|
||||
/// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
|
||||
/// </remarks>
|
||||
public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent;
|
||||
|
||||
public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object has arrived within a tolerance rotation
|
||||
/// of a rotation target.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerAtRotTargetEvent"/>
|
||||
/// in <see cref="SceneObjectGroup.checkAtTargets"/>
|
||||
/// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
|
||||
/// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
|
||||
/// </remarks>
|
||||
public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent;
|
||||
|
||||
public delegate void ScriptNotAtRotTargetEvent(uint localID);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object has a rotation target but has not arrived
|
||||
/// within a tolerance rotation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerNotAtRotTargetEvent"/>
|
||||
/// in <see cref="SceneObjectGroup.checkAtTargets"/>
|
||||
/// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
|
||||
/// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
|
||||
/// </remarks>
|
||||
public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent;
|
||||
|
||||
public delegate void ScriptColliding(uint localID, ColliderArgs colliders);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a physical collision has started between a prim
|
||||
/// and something other than the region terrain.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerScriptCollidingStart"/>
|
||||
/// in <see cref="SceneObjectPart.SendCollisionEvent"/>
|
||||
/// via <see cref="SceneObjectPart.PhysicsCollision"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
|
||||
/// </remarks>
|
||||
public event ScriptColliding OnScriptColliderStart;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when something that previously collided with a prim has
|
||||
/// not stopped colliding with it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <seealso cref="OnScriptColliderStart"/>
|
||||
/// Triggered by <see cref="TriggerScriptColliding"/>
|
||||
/// in <see cref="SceneObjectPart.SendCollisionEvent"/>
|
||||
/// via <see cref="SceneObjectPart.PhysicsCollision"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
|
||||
/// </remarks>
|
||||
public event ScriptColliding OnScriptColliding;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when something that previously collided with a prim has
|
||||
/// stopped colliding with it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerScriptCollidingEnd"/>
|
||||
/// in <see cref="SceneObjectPart.SendCollisionEvent"/>
|
||||
/// via <see cref="SceneObjectPart.PhysicsCollision"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
|
||||
/// </remarks>
|
||||
public event ScriptColliding OnScriptCollidingEnd;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a physical collision has started between an object
|
||||
/// and the region terrain.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerScriptLandCollidingStart"/>
|
||||
/// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
|
||||
/// via <see cref="SceneObjectPart.PhysicsCollision"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
|
||||
/// </remarks>
|
||||
public event ScriptColliding OnScriptLandColliderStart;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object that previously collided with the region
|
||||
/// terrain has not yet stopped colliding with it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerScriptLandColliding"/>
|
||||
/// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
|
||||
/// via <see cref="SceneObjectPart.PhysicsCollision"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
|
||||
/// </remarks>
|
||||
public event ScriptColliding OnScriptLandColliding;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object that previously collided with the region
|
||||
/// terrain has stopped colliding with it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerScriptLandCollidingEnd"/>
|
||||
/// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
|
||||
/// via <see cref="SceneObjectPart.PhysicsCollision"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
|
||||
/// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
|
||||
/// </remarks>
|
||||
public event ScriptColliding OnScriptLandColliderEnd;
|
||||
|
||||
public delegate void OnMakeChildAgentDelegate(ScenePresence presence);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an agent has been made a child agent of a scene.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerOnMakeChildAgent"/>
|
||||
/// in <see cref="ScenePresence.MakeChildAgent"/>
|
||||
/// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CrossAgentToNewRegionAsync"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.InterGrid.KillAUser.ShutdownNoLogout"/>
|
||||
/// </remarks>
|
||||
public event OnMakeChildAgentDelegate OnMakeChildAgent;
|
||||
|
||||
public delegate void OnSaveNewWindlightProfileDelegate();
|
||||
public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after the grunt work for adding a root agent to a
|
||||
/// scene has been performed (resuming attachment scripts, physics,
|
||||
/// animations etc.)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This event is on the critical path for transferring an avatar from one region to another. Try and do
|
||||
/// as little work on this event as possible, or do work asynchronously.
|
||||
/// </summary>
|
||||
/// Triggered after <see cref="OnSetRootAgentScene"/>
|
||||
/// by <see cref="TriggerOnMakeRootAgent"/>
|
||||
/// in <see cref="ScenePresence.MakeRootAgent"/>
|
||||
/// via <see cref="Scene.AgentCrossing"/>
|
||||
/// and <see cref="ScenePresence.CompleteMovement"/>
|
||||
/// </remarks>
|
||||
public event Action<ScenePresence> OnMakeRootAgent;
|
||||
|
||||
public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
|
||||
@@ -336,9 +682,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public event AvatarKillData OnAvatarKilled;
|
||||
public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar);
|
||||
|
||||
// public delegate void ScriptTimerEvent(uint localID, double timerinterval);
|
||||
|
||||
// public event ScriptTimerEvent OnScriptTimerEvent;
|
||||
/*
|
||||
public delegate void ScriptTimerEvent(uint localID, double timerinterval);
|
||||
/// <summary>
|
||||
/// Used to be triggered when the LSL timer event fires.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerTimerEvent"/>
|
||||
/// via <see cref="SceneObjectPart.handleTimerAccounting"/>
|
||||
/// </remarks>
|
||||
public event ScriptTimerEvent OnScriptTimerEvent;
|
||||
*/
|
||||
|
||||
public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour);
|
||||
public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
|
||||
@@ -348,12 +702,27 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <summary>
|
||||
/// Triggered when an object is added to the scene.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerObjectAddedToScene"/>
|
||||
/// in <see cref="Scene.AddNewSceneObject"/>,
|
||||
/// <see cref="Scene.DuplicateObject"/>,
|
||||
/// <see cref="Scene.doObjectDuplicateOnRay"/>
|
||||
/// </remarks>
|
||||
public event Action<SceneObjectGroup> OnObjectAddedToScene;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for <see cref="OnObjectBeingRemovedFromScene"/>
|
||||
/// </summary>
|
||||
/// <param name="obj">The object being removed from the scene</param>
|
||||
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object is removed from the scene.
|
||||
/// </summary>
|
||||
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerObjectBeingRemovedFromScene"/>
|
||||
/// in <see cref="Scene.DeleteSceneObject"/>
|
||||
/// </remarks>
|
||||
public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
|
||||
|
||||
public delegate void NoticeNoLandDataFromStorage();
|
||||
@@ -369,6 +738,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 +811,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 +864,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);
|
||||
|
||||
@@ -522,9 +908,28 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public event PrimsLoaded OnPrimsLoaded;
|
||||
|
||||
public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a teleport starts
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerTeleportStart"/>
|
||||
/// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CreateAgent"/>
|
||||
/// and <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.HGEntityTransferModule.CreateAgent"/>
|
||||
/// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
|
||||
/// </remarks>
|
||||
public event TeleportStart OnTeleportStart;
|
||||
|
||||
public delegate void TeleportFail(IClientAPI client, bool gridLogout);
|
||||
|
||||
/// <summary>
|
||||
/// Trigered when a teleport fails.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerTeleportFail"/>
|
||||
/// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.Fail"/>
|
||||
/// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
|
||||
/// </remarks>
|
||||
public event TeleportFail OnTeleportFail;
|
||||
|
||||
public class MoneyTransferArgs : EventArgs
|
||||
@@ -532,7 +937,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public UUID sender;
|
||||
public UUID receiver;
|
||||
|
||||
// Always false. The SL protocol sucks.
|
||||
/// <summary>
|
||||
/// Always false. The SL protocol sucks.
|
||||
/// </summary>
|
||||
public bool authenticated = false;
|
||||
|
||||
public int amount;
|
||||
@@ -589,8 +996,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)
|
||||
@@ -2006,7 +2434,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
// this lets us keep track of nasty script events like timer, etc.
|
||||
/// <summary>
|
||||
/// this lets us keep track of nasty script events like timer, etc.
|
||||
/// </summary>
|
||||
/// <param name="objLocalID"></param>
|
||||
/// <param name="Interval"></param>
|
||||
public void TriggerTimerEvent(uint objLocalID, double Interval)
|
||||
{
|
||||
throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak");
|
||||
@@ -2068,7 +2500,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 +2509,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
try
|
||||
{
|
||||
d(requestId, message);
|
||||
d(requestId, loadedScenes, message);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <summary>
|
||||
/// Minimum value of the size of a non-physical prim in each axis
|
||||
/// </summary>
|
||||
public float m_minNonphys = 0.01f;
|
||||
public float m_minNonphys = 0.001f;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum value of the size of a non-physical prim in each axis
|
||||
@@ -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;
|
||||
@@ -739,13 +744,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
|
||||
CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims);
|
||||
|
||||
m_minNonphys = startupConfig.GetFloat("NonphysicalPrimMin", m_minNonphys);
|
||||
m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
|
||||
if (RegionInfo.NonphysPrimMin > 0)
|
||||
{
|
||||
m_minNonphys = RegionInfo.NonphysPrimMin;
|
||||
}
|
||||
|
||||
m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
|
||||
m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
|
||||
if (RegionInfo.NonphysPrimMax > 0)
|
||||
{
|
||||
m_maxNonphys = RegionInfo.NonphysPrimMax;
|
||||
@@ -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);
|
||||
@@ -850,6 +861,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
|
||||
// FIXME: Ultimately this should be in a module.
|
||||
SendPeriodicAppearanceUpdates = true;
|
||||
|
||||
IConfig appearanceConfig = m_config.Configs["Appearance"];
|
||||
if (appearanceConfig != null)
|
||||
{
|
||||
@@ -4334,6 +4347,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 +4604,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 +4647,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>
|
||||
@@ -5482,6 +5529,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public string GetExtraSetting(string name)
|
||||
{
|
||||
if (m_extraSettings == null)
|
||||
return String.Empty;
|
||||
|
||||
string val;
|
||||
|
||||
if (!m_extraSettings.TryGetValue(name, out val))
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -52,26 +52,23 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public class UuidGatherer
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Asset cache used for gathering assets
|
||||
/// </summary>
|
||||
protected IAssetService m_assetCache;
|
||||
|
||||
/// <summary>
|
||||
/// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate
|
||||
/// asset was found by the asset service.
|
||||
/// </summary>
|
||||
private AssetBase m_requestedObjectAsset;
|
||||
|
||||
/// <summary>
|
||||
/// Signal whether we are currently waiting for the asset service to deliver an asset.
|
||||
/// </summary>
|
||||
private bool m_waitingForObjectAsset;
|
||||
protected IAssetService m_assetService;
|
||||
|
||||
// /// <summary>
|
||||
// /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate
|
||||
// /// asset was found by the asset service.
|
||||
// /// </summary>
|
||||
// private AssetBase m_requestedObjectAsset;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Signal whether we are currently waiting for the asset service to deliver an asset.
|
||||
// /// </summary>
|
||||
// private bool m_waitingForObjectAsset;
|
||||
|
||||
public UuidGatherer(IAssetService assetCache)
|
||||
{
|
||||
m_assetCache = assetCache;
|
||||
m_assetService = assetCache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -195,18 +192,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The callback made when we request the asset for an object from the asset service.
|
||||
/// </summary>
|
||||
private void AssetReceived(string id, Object sender, AssetBase asset)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
m_requestedObjectAsset = asset;
|
||||
m_waitingForObjectAsset = false;
|
||||
Monitor.Pulse(this);
|
||||
}
|
||||
}
|
||||
// /// <summary>
|
||||
// /// The callback made when we request the asset for an object from the asset service.
|
||||
// /// </summary>
|
||||
// private void AssetReceived(string id, Object sender, AssetBase asset)
|
||||
// {
|
||||
// lock (this)
|
||||
// {
|
||||
// m_requestedObjectAsset = asset;
|
||||
// m_waitingForObjectAsset = false;
|
||||
// Monitor.Pulse(this);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Get an asset synchronously, potentially using an asynchronous callback. If the
|
||||
@@ -216,25 +213,29 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <returns></returns>
|
||||
protected virtual AssetBase GetAsset(UUID uuid)
|
||||
{
|
||||
m_waitingForObjectAsset = true;
|
||||
m_assetCache.Get(uuid.ToString(), this, AssetReceived);
|
||||
return m_assetService.Get(uuid.ToString());
|
||||
|
||||
// The asset cache callback can either
|
||||
//
|
||||
// 1. Complete on the same thread (if the asset is already in the cache) or
|
||||
// 2. Come in via a different thread (if we need to go fetch it).
|
||||
//
|
||||
// The code below handles both these alternatives.
|
||||
lock (this)
|
||||
{
|
||||
if (m_waitingForObjectAsset)
|
||||
{
|
||||
Monitor.Wait(this);
|
||||
m_waitingForObjectAsset = false;
|
||||
}
|
||||
}
|
||||
|
||||
return m_requestedObjectAsset;
|
||||
// XXX: Switching to do this synchronously where the call was async before but we always waited for it
|
||||
// to complete anyway!
|
||||
// m_waitingForObjectAsset = true;
|
||||
// m_assetCache.Get(uuid.ToString(), this, AssetReceived);
|
||||
//
|
||||
// // The asset cache callback can either
|
||||
// //
|
||||
// // 1. Complete on the same thread (if the asset is already in the cache) or
|
||||
// // 2. Come in via a different thread (if we need to go fetch it).
|
||||
// //
|
||||
// // The code below handles both these alternatives.
|
||||
// lock (this)
|
||||
// {
|
||||
// if (m_waitingForObjectAsset)
|
||||
// {
|
||||
// Monitor.Wait(this);
|
||||
// m_waitingForObjectAsset = false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return m_requestedObjectAsset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -365,4 +366,40 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class HGUuidGatherer : UuidGatherer
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected string m_assetServerURL;
|
||||
|
||||
public HGUuidGatherer(IAssetService assetService, string assetServerURL)
|
||||
: base(assetService)
|
||||
{
|
||||
m_assetServerURL = assetServerURL;
|
||||
}
|
||||
|
||||
protected override AssetBase GetAsset(UUID uuid)
|
||||
{
|
||||
if (string.Empty == m_assetServerURL)
|
||||
return base.GetAsset(uuid);
|
||||
else
|
||||
return FetchAsset(m_assetServerURL, uuid);
|
||||
}
|
||||
|
||||
public AssetBase FetchAsset(string url, UUID assetID)
|
||||
{
|
||||
if (!url.EndsWith("/") && !url.EndsWith("="))
|
||||
url = url + "/";
|
||||
|
||||
AssetBase asset = m_assetService.Get(url + assetID.ToString());
|
||||
|
||||
if (asset != null)
|
||||
{
|
||||
m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server. ", asset.ID, url);
|
||||
return asset;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,37 +130,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
||||
SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val));
|
||||
}
|
||||
|
||||
private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint)
|
||||
private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint)
|
||||
{
|
||||
SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host);
|
||||
|
||||
if (hostPart == null)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (hostPart.ParentGroup.IsAttachment)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>();
|
||||
if (attachmentsModule == null)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script);
|
||||
if (item == null)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH
|
||||
return;
|
||||
return 0;
|
||||
|
||||
ScenePresence target;
|
||||
if (!m_scene.TryGetScenePresence(item.PermsGranter, out target))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (target.UUID != hostPart.ParentGroup.OwnerID)
|
||||
{
|
||||
uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions();
|
||||
|
||||
if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
hostPart.ParentGroup.SetOwnerId(target.UUID);
|
||||
hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId);
|
||||
@@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
||||
hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
|
||||
}
|
||||
|
||||
attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true);
|
||||
return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,12 +231,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
|
||||
if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null)
|
||||
throw new Exception("Invalid connector configuration");
|
||||
|
||||
// Generate an initial nickname if randomizing is enabled
|
||||
// Generate an initial nickname
|
||||
|
||||
if (m_randomizeNick)
|
||||
{
|
||||
m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
|
||||
}
|
||||
else
|
||||
m_nick = m_baseNick;
|
||||
|
||||
m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn);
|
||||
|
||||
|
||||
@@ -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,7 @@ 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));
|
||||
// avatars get all collisions no matter what (makes walking on ground and such work)
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -440,7 +440,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 +465,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -478,11 +478,10 @@ public class BSCharacter : BSPhysObject
|
||||
// Stop collision events
|
||||
public override void UnSubscribeEvents() {
|
||||
_subscribedEventsMs = 0;
|
||||
// Avatars get all their collision events
|
||||
// Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
|
||||
// {
|
||||
// BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
// });
|
||||
Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
|
||||
{
|
||||
BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
}
|
||||
// Return 'true' if someone has subscribed to events
|
||||
public override bool SubscribedEvents() {
|
||||
@@ -530,20 +529,20 @@ public class BSCharacter : BSPhysObject
|
||||
// The collision, if it should be reported to the character, is placed in a collection
|
||||
// that will later be sent to the simulator when SendCollisions() is called.
|
||||
CollisionEventUpdate collisionCollection = null;
|
||||
public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
||||
public override bool Collide(uint collidingWith, BSPhysObject collidee, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
||||
bool ret = false;
|
||||
|
||||
// The following makes IsColliding() and IsCollidingGround() work
|
||||
_collidingStep = Scene.SimulationStep;
|
||||
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
||||
if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
|
||||
{
|
||||
_collidingGroundStep = Scene.SimulationStep;
|
||||
}
|
||||
// DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
|
||||
|
||||
// throttle collisions to the rate specified in the subscription
|
||||
if (_subscribedEventsMs != 0) {
|
||||
if (SubscribedEvents()) {
|
||||
int nowTime = Scene.SimulationNowTime;
|
||||
if (nowTime >= _nextCollisionOkTime) {
|
||||
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
||||
@@ -551,8 +550,10 @@ public class BSCharacter : BSPhysObject
|
||||
if (collisionCollection == null)
|
||||
collisionCollection = new CollisionEventUpdate();
|
||||
collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override void SendCollisions()
|
||||
|
||||
@@ -74,6 +74,17 @@ public abstract class BSConstraint : IDisposable
|
||||
return ret;
|
||||
}
|
||||
|
||||
public virtual bool SetSolverIterations(float cnt)
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_enabled)
|
||||
{
|
||||
BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.Ptr, cnt);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public virtual bool CalculateTransforms()
|
||||
{
|
||||
bool ret = false;
|
||||
@@ -96,8 +107,9 @@ public abstract class BSConstraint : IDisposable
|
||||
ret = CalculateTransforms();
|
||||
if (ret)
|
||||
{
|
||||
// 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 the link is enabled, be sure to set the constraint itself to enabled.
|
||||
BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// Linear properties
|
||||
private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
|
||||
private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
|
||||
private Vector3 m_dir = Vector3.Zero; // velocity applied to body
|
||||
private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body
|
||||
private Vector3 m_linearFrictionTimescale = Vector3.Zero;
|
||||
private float m_linearMotorDecayTimescale = 0;
|
||||
private float m_linearMotorTimescale = 0;
|
||||
@@ -131,7 +131,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
m_type = Vehicle.TYPE_NONE;
|
||||
}
|
||||
|
||||
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep)
|
||||
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
|
||||
{
|
||||
VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
|
||||
switch (pParam)
|
||||
@@ -230,7 +230,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
}
|
||||
}//end ProcessFloatVehicleParam
|
||||
|
||||
internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep)
|
||||
internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
|
||||
{
|
||||
VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
|
||||
switch (pParam)
|
||||
@@ -299,7 +299,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
}
|
||||
}//end ProcessVehicleFlags
|
||||
|
||||
internal void ProcessTypeChange(Vehicle pType, float stepSize)
|
||||
internal void ProcessTypeChange(Vehicle pType)
|
||||
{
|
||||
VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
|
||||
// Set Defaults For Type
|
||||
@@ -478,29 +478,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
MoveAngular(pTimestep);
|
||||
LimitRotation(pTimestep);
|
||||
|
||||
// remember the position so next step we can limit absolute movement effects
|
||||
m_lastPositionVector = m_prim.Position;
|
||||
|
||||
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
|
||||
m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
|
||||
}// end Step
|
||||
|
||||
private void MoveLinear(float pTimestep)
|
||||
{
|
||||
// requested m_linearMotorDirection is significant
|
||||
// if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
|
||||
if (m_linearMotorDirection.LengthSquared() > 0.0001f)
|
||||
// m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates
|
||||
// m_lastLinearVelocityVector is the speed we are moving in that direction
|
||||
if (m_linearMotorDirection.LengthSquared() > 0.001f)
|
||||
{
|
||||
Vector3 origDir = m_linearMotorDirection;
|
||||
Vector3 origVel = m_lastLinearVelocityVector;
|
||||
|
||||
// add drive to body
|
||||
// Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
|
||||
Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale);
|
||||
// lastLinearVelocityVector is the current body velocity vector?
|
||||
// Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale / pTimestep);
|
||||
Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep);
|
||||
// lastLinearVelocityVector is the current body velocity vector
|
||||
// RA: Not sure what the *10 is for. A correction for pTimestep?
|
||||
// m_lastLinearVelocityVector += (addAmount*10);
|
||||
m_lastLinearVelocityVector += addAmount;
|
||||
|
||||
// This will work temporarily, but we really need to compare speed on an axis
|
||||
// KF: Limit body velocity to applied velocity?
|
||||
// Limit the velocity vector to less than the last set linear motor direction
|
||||
if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
|
||||
m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
|
||||
@@ -509,53 +510,108 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
|
||||
m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
|
||||
|
||||
// decay applied velocity
|
||||
Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
|
||||
m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
|
||||
|
||||
/*
|
||||
Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
|
||||
m_lastLinearVelocityVector += addAmount;
|
||||
|
||||
float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
|
||||
m_linearMotorDirection *= decayfraction;
|
||||
|
||||
// decay applied velocity
|
||||
Vector3 decayfraction = Vector3.One/(m_linearMotorDecayTimescale / pTimestep);
|
||||
// (RA: do not know where the 0.5f comes from)
|
||||
m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
|
||||
*/
|
||||
float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep));
|
||||
m_linearMotorDirection *= keepfraction;
|
||||
|
||||
VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
|
||||
m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
|
||||
VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}",
|
||||
m_prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if what remains of applied is small, zero it.
|
||||
// if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
|
||||
// m_lastLinearVelocityVector = Vector3.Zero;
|
||||
// if what remains of direction is very small, zero it.
|
||||
m_linearMotorDirection = Vector3.Zero;
|
||||
m_lastLinearVelocityVector = Vector3.Zero;
|
||||
VDetailLog("{0},MoveLinear,zeroed", m_prim.LocalID);
|
||||
}
|
||||
|
||||
// convert requested object velocity to object relative vector
|
||||
Quaternion rotq = m_prim.Orientation;
|
||||
m_dir = m_lastLinearVelocityVector * rotq;
|
||||
m_newVelocity = m_lastLinearVelocityVector * rotq;
|
||||
|
||||
// Add the various forces into m_dir which will be our new direction vector (velocity)
|
||||
|
||||
// add Gravity and Buoyancy
|
||||
// KF: So far I have found no good method to combine a script-requested
|
||||
// .Z velocity and gravity. Therefore only 0g will used script-requested
|
||||
// .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
|
||||
Vector3 grav = Vector3.Zero;
|
||||
// There is some gravity, make a gravity force vector that is applied after object velocity.
|
||||
// m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
|
||||
grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy);
|
||||
Vector3 grav = m_prim.Scene.DefaultGravity * (m_prim.Mass * (1f - m_VehicleBuoyancy));
|
||||
|
||||
/*
|
||||
* RA: Not sure why one would do this
|
||||
// Preserve the current Z velocity
|
||||
Vector3 vel_now = m_prim.Velocity;
|
||||
m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
|
||||
*/
|
||||
|
||||
Vector3 pos = m_prim.Position;
|
||||
Vector3 posChange = pos;
|
||||
// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
|
||||
double Zchange = Math.Abs(posChange.Z);
|
||||
|
||||
// If below the terrain, move us above the ground a little.
|
||||
float terrainHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
||||
// Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
|
||||
// Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
|
||||
// Vector3 rotatedSize = m_prim.Size * m_prim.Orientation;
|
||||
// if (rotatedSize.Z < terrainHeight)
|
||||
if (pos.Z < terrainHeight)
|
||||
{
|
||||
pos.Z = terrainHeight + 2;
|
||||
m_prim.Position = pos;
|
||||
VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", m_prim.LocalID, terrainHeight, pos);
|
||||
}
|
||||
|
||||
// Check if hovering
|
||||
if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
|
||||
{
|
||||
// We should hover, get the target height
|
||||
if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_prim.Scene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight;
|
||||
}
|
||||
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = terrainHeight + m_VhoverHeight;
|
||||
}
|
||||
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_VhoverHeight;
|
||||
}
|
||||
|
||||
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
|
||||
{
|
||||
// If body is aready heigher, use its height as target height
|
||||
if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
|
||||
}
|
||||
if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
|
||||
{
|
||||
if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
|
||||
{
|
||||
m_prim.Position = pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float herr0 = pos.Z - m_VhoverTargetHeight;
|
||||
// Replace Vertical speed with correction figure if significant
|
||||
if (Math.Abs(herr0) > 0.01f)
|
||||
{
|
||||
m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
|
||||
//KF: m_VhoverEfficiency is not yet implemented
|
||||
}
|
||||
else
|
||||
{
|
||||
m_newVelocity.Z = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight);
|
||||
}
|
||||
|
||||
Vector3 posChange = pos - m_lastPositionVector;
|
||||
if (m_BlockingEndPoint != Vector3.Zero)
|
||||
{
|
||||
bool changed = false;
|
||||
@@ -592,125 +648,43 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
}
|
||||
}
|
||||
|
||||
// If below the terrain, move us above the ground a little.
|
||||
if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos))
|
||||
{
|
||||
pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2;
|
||||
m_prim.Position = pos;
|
||||
VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
|
||||
}
|
||||
|
||||
// Check if hovering
|
||||
if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
|
||||
{
|
||||
// We should hover, get the target height
|
||||
if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight;
|
||||
}
|
||||
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
|
||||
}
|
||||
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_VhoverHeight;
|
||||
}
|
||||
|
||||
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
|
||||
{
|
||||
// If body is aready heigher, use its height as target height
|
||||
if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
|
||||
}
|
||||
if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
|
||||
{
|
||||
if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
|
||||
{
|
||||
m_prim.Position = pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float herr0 = pos.Z - m_VhoverTargetHeight;
|
||||
// Replace Vertical speed with correction figure if significant
|
||||
if (Math.Abs(herr0) > 0.01f)
|
||||
{
|
||||
m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
|
||||
//KF: m_VhoverEfficiency is not yet implemented
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dir.Z = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
|
||||
|
||||
// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
|
||||
// m_VhoverTimescale = 0f; // time to acheive height
|
||||
// pTimestep is time since last frame,in secs
|
||||
}
|
||||
|
||||
float Zchange = Math.Abs(posChange.Z);
|
||||
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
|
||||
{
|
||||
//Start Experimental Values
|
||||
if (Zchange > .3)
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 3);
|
||||
}
|
||||
if (Zchange > .15)
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 2);
|
||||
}
|
||||
if (Zchange > .75)
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 1.5);
|
||||
}
|
||||
if (Zchange > .05)
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 1.25);
|
||||
}
|
||||
if (Zchange > .025)
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 1.125);
|
||||
}
|
||||
float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
||||
float postemp = (pos.Z - terraintemp);
|
||||
float postemp = (pos.Z - terrainHeight);
|
||||
if (postemp > 2.5f)
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 1.037125);
|
||||
}
|
||||
VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
|
||||
//End Experimental Values
|
||||
}
|
||||
if ((m_flags & (VehicleFlag.NO_X)) != 0)
|
||||
{
|
||||
m_dir.X = 0;
|
||||
}
|
||||
m_newVelocity.X = 0;
|
||||
if ((m_flags & (VehicleFlag.NO_Y)) != 0)
|
||||
{
|
||||
m_dir.Y = 0;
|
||||
}
|
||||
m_newVelocity.Y = 0;
|
||||
if ((m_flags & (VehicleFlag.NO_Z)) != 0)
|
||||
{
|
||||
m_dir.Z = 0;
|
||||
}
|
||||
|
||||
m_lastPositionVector = m_prim.Position;
|
||||
m_newVelocity.Z = 0;
|
||||
|
||||
// Apply velocity
|
||||
m_prim.Velocity = m_dir;
|
||||
m_prim.Velocity = m_newVelocity;
|
||||
// apply gravity force
|
||||
// Why is this set here? The physics engine already does gravity.
|
||||
// m_prim.AddForce(grav, false);
|
||||
// m_prim.Force = grav;
|
||||
|
||||
// Apply friction
|
||||
Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
|
||||
m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
|
||||
Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
|
||||
m_lastLinearVelocityVector *= keepFraction;
|
||||
|
||||
VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
|
||||
m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
|
||||
VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}",
|
||||
m_prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction);
|
||||
|
||||
} // end MoveLinear()
|
||||
|
||||
@@ -735,17 +709,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// There are m_angularMotorApply steps.
|
||||
Vector3 origAngularVelocity = m_angularMotorVelocity;
|
||||
// ramp up to new value
|
||||
// current velocity += error / (time to get there / step interval)
|
||||
// requested speed - last motor speed
|
||||
// current velocity += error / ( time to get there / step interval)
|
||||
// requested speed - last motor speed
|
||||
m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
|
||||
m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
|
||||
m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
|
||||
|
||||
VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
|
||||
m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
|
||||
VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}",
|
||||
m_prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
|
||||
|
||||
m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
|
||||
// velocity may still be acheived.
|
||||
// This is done so that if script request rate is less than phys frame rate the expected
|
||||
// velocity may still be acheived.
|
||||
m_angularMotorApply--;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -760,7 +735,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
Vector3 vertattr = Vector3.Zero;
|
||||
if (m_verticalAttractionTimescale < 300)
|
||||
{
|
||||
float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
|
||||
float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep);
|
||||
// get present body rotation
|
||||
Quaternion rotq = m_prim.Orientation;
|
||||
// make a vector pointing up
|
||||
@@ -863,16 +838,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
m_rot.Y = 0;
|
||||
changed = true;
|
||||
}
|
||||
if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
|
||||
{
|
||||
m_rot.X = 0;
|
||||
m_rot.Y = 0;
|
||||
changed = true;
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
m_prim.Orientation = m_rot;
|
||||
VDetailLog("{0},LimitRotation,done,orig={1},new={2}", m_prim.LocalID, rotq, m_rot);
|
||||
}
|
||||
|
||||
VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
|
||||
}
|
||||
|
||||
// Invoke the detailed logger and output something if it's enabled.
|
||||
|
||||
@@ -202,11 +202,33 @@ public class BSLinkset
|
||||
return com;
|
||||
}
|
||||
|
||||
// The object is going dynamic (physical). Do any setup necessary
|
||||
// for a dynamic linkset.
|
||||
// Only the state of the passed object can be modified. The rest of the linkset
|
||||
// has not yet been fully constructed.
|
||||
// Return 'true' if any properties updated on the passed object.
|
||||
// Called at taint-time!
|
||||
public bool MakeDynamic(BSPhysObject child)
|
||||
{
|
||||
bool ret = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// The object is going static (non-physical). Do any setup necessary
|
||||
// for a static linkset.
|
||||
// Return 'true' if any properties updated on the passed object.
|
||||
// Called at taint-time!
|
||||
public bool MakeStatic(BSPhysObject child)
|
||||
{
|
||||
// What is done for each object in BSPrim is what we want.
|
||||
return false;
|
||||
}
|
||||
|
||||
// When physical properties are changed the linkset needs to recalculate
|
||||
// its internal properties.
|
||||
public void Refresh(BSPhysObject requestor)
|
||||
{
|
||||
// If there are no children, there aren't any constraints to recompute
|
||||
// If there are no children, there can't be any constraints to recompute
|
||||
if (!HasAnyChildren)
|
||||
return;
|
||||
|
||||
@@ -225,15 +247,16 @@ public class BSLinkset
|
||||
// from a linkset to make sure the constraints know about the new mass and
|
||||
// geometry.
|
||||
// Must only be called at taint time!!
|
||||
private bool RecomputeLinksetConstraintVariables()
|
||||
private void RecomputeLinksetConstraintVariables()
|
||||
{
|
||||
float linksetMass = LinksetMass;
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
bool somethingMissing = false;
|
||||
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);
|
||||
@@ -241,16 +264,36 @@ public class BSLinkset
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-fatal error that can happen when children are being added to the linkset but
|
||||
// Non-fatal error that happens when children are being added to the linkset but
|
||||
// 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);
|
||||
somethingMissing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the whole linkset is not here, doesn't make sense to recompute linkset wide values
|
||||
if (!somethingMissing)
|
||||
{
|
||||
// If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
|
||||
OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
|
||||
BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
|
||||
foreach (BSPhysObject child in m_children)
|
||||
{
|
||||
BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
|
||||
}
|
||||
/*
|
||||
// The root prim takes on the weight of the whole linkset
|
||||
OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(LinksetRoot.BSShape.Ptr, linksetMass);
|
||||
BulletSimAPI.SetMassProps2(LinksetRoot.BSBody.Ptr, linksetMass, inertia);
|
||||
OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
|
||||
BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.Ptr, centerOfMass, OMV.Quaternion.Identity);
|
||||
BulletSimAPI.UpdateInertiaTensor2(LinksetRoot.BSBody.Ptr);
|
||||
*/
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// I am the root of a linkset and a new child is being added
|
||||
@@ -296,9 +339,9 @@ public class BSLinkset
|
||||
DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
|
||||
|
||||
PhysicallyUnlinkAChildFromRoot(rootx, childx);
|
||||
RecomputeLinksetConstraintVariables();
|
||||
});
|
||||
|
||||
RecomputeLinksetConstraintVariables();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -327,7 +370,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
|
||||
@@ -377,6 +420,10 @@ public class BSLinkset
|
||||
PhysicsScene.Params.linkConstraintTransMotorMaxVel,
|
||||
PhysicsScene.Params.linkConstraintTransMotorMaxForce);
|
||||
constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
|
||||
if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
|
||||
{
|
||||
constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
|
||||
}
|
||||
|
||||
RecomputeLinksetConstraintVariables();
|
||||
}
|
||||
@@ -388,10 +435,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 +447,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.
|
||||
|
||||
@@ -41,14 +41,18 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
{
|
||||
public abstract BSLinkset Linkset { get; set; }
|
||||
|
||||
public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type,
|
||||
public abstract bool Collide(uint collidingWith, BSPhysObject collidee,
|
||||
OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
|
||||
public abstract void SendCollisions();
|
||||
|
||||
// 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;
|
||||
@@ -133,16 +136,18 @@ public sealed class BSPrim : BSPhysObject
|
||||
Linkset = new BSLinkset(Scene, this); // a linkset of one
|
||||
_vehicle = new BSDynamics(Scene, this); // add vehicleness
|
||||
_mass = CalculateMass();
|
||||
// do the actual object creation at taint time
|
||||
DetailLog("{0},BSPrim.constructor,call", LocalID);
|
||||
// do the actual object creation at taint time
|
||||
_scene.TaintedObject("BSPrim.create", delegate()
|
||||
{
|
||||
RecreateGeomAndObject();
|
||||
CreateGeomAndObject(true);
|
||||
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -181,9 +186,10 @@ public sealed class BSPrim : BSPhysObject
|
||||
_scene.TaintedObject("BSPrim.setSize", delegate()
|
||||
{
|
||||
_mass = CalculateMass(); // changing size changes the mass
|
||||
BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
|
||||
DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
|
||||
RecreateGeomAndObject();
|
||||
// Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct
|
||||
// scale and margins are set.
|
||||
CreateGeomAndObject(true);
|
||||
DetailLog("{0}: BSPrim.setSize: size={1}, scale={2}, mass={3}, physical={4}", LocalID, _size, _scale, _mass, IsPhysical);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -193,7 +199,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
_scene.TaintedObject("BSPrim.setShape", delegate()
|
||||
{
|
||||
_mass = CalculateMass(); // changing the shape changes the mass
|
||||
RecreateGeomAndObject();
|
||||
CreateGeomAndObject(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -258,10 +264,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)
|
||||
@@ -274,7 +280,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
get {
|
||||
if (!Linkset.IsRoot(this))
|
||||
// child prims move around based on their parent. Need to get the latest location
|
||||
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
_position = BulletSimAPI.GetPosition2(BSBody.Ptr);
|
||||
|
||||
// don't do the GetObjectPosition for root elements because this function is called a zillion times
|
||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
@@ -286,7 +292,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
_scene.TaintedObject("BSPrim.setPosition", delegate()
|
||||
{
|
||||
DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -297,7 +303,8 @@ public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
get
|
||||
{
|
||||
return Linkset.LinksetMass;
|
||||
// return Linkset.LinksetMass;
|
||||
return _mass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,8 +330,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
_scene.TaintedObject("BSPrim.setForce", delegate()
|
||||
{
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -340,7 +346,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
// Done at taint time so we're sure the physics engine is not using the variables
|
||||
// Vehicle code changes the parameters for this vehicle type.
|
||||
_vehicle.ProcessTypeChange(type, Scene.LastSimulatedTimestep);
|
||||
_vehicle.ProcessTypeChange(type);
|
||||
// Tell the scene about the vehicle so it will get processing each frame.
|
||||
_scene.VehicleInSceneTypeChanged(this, type);
|
||||
});
|
||||
@@ -350,14 +356,14 @@ public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
_scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
|
||||
{
|
||||
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
|
||||
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
|
||||
});
|
||||
}
|
||||
public override void VehicleVectorParam(int param, OMV.Vector3 value)
|
||||
{
|
||||
_scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
|
||||
{
|
||||
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
|
||||
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
|
||||
});
|
||||
}
|
||||
public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
|
||||
@@ -401,7 +407,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
_scene.TaintedObject("BSPrim.setVelocity", delegate()
|
||||
{
|
||||
DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
|
||||
BulletSimAPI.SetLinearVelocity2(BSBody.Ptr, _velocity);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -425,7 +431,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
if (!Linkset.IsRoot(this))
|
||||
{
|
||||
// Children move around because tied to parent. Get a fresh value.
|
||||
_orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
|
||||
_orientation = BulletSimAPI.GetOrientation2(BSBody.Ptr);
|
||||
}
|
||||
return _orientation;
|
||||
}
|
||||
@@ -436,14 +442,13 @@ public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
|
||||
});
|
||||
}
|
||||
}
|
||||
public override int PhysicsActorType {
|
||||
get { return _physicsActorType; }
|
||||
set { _physicsActorType = value;
|
||||
}
|
||||
set { _physicsActorType = value; }
|
||||
}
|
||||
public override bool IsPhysical {
|
||||
get { return _isPhysical; }
|
||||
@@ -470,21 +475,131 @@ 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
|
||||
VerifyCorrectPhysicalShape();
|
||||
UpdatePhysicalParameters();
|
||||
}
|
||||
|
||||
private void UpdatePhysicalParameters()
|
||||
{
|
||||
/*
|
||||
// Bullet wants static objects to have a mass of zero
|
||||
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 (does gravity and collisions move this object)
|
||||
MakeDynamic(IsStatic);
|
||||
|
||||
// Make solid or not (do things bounce off or pass through this object)
|
||||
MakeSolid(IsSolid);
|
||||
|
||||
// Arrange for collisions events if the simulator wants them
|
||||
EnableCollisions(SubscribedEvents());
|
||||
|
||||
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.UpdatePhysicalParameters,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(bool makeStatic)
|
||||
{
|
||||
if (makeStatic)
|
||||
{
|
||||
// Become a Bullet 'static' object type
|
||||
m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||
// Stop all movement
|
||||
BulletSimAPI.ClearAllForces2(BSBody.Ptr);
|
||||
// Center of mass is at the center of the object
|
||||
BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.Ptr, _position, _orientation);
|
||||
// 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);
|
||||
// There can be special things needed for implementing linksets
|
||||
Linkset.MakeStatic(this);
|
||||
// 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
|
||||
m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||
|
||||
// Set various physical properties so internal things will get computed correctly as they are set
|
||||
BulletSimAPI.SetFriction2(BSBody.Ptr, Scene.Params.defaultFriction);
|
||||
BulletSimAPI.SetRestitution2(BSBody.Ptr, Scene.Params.defaultRestitution);
|
||||
// per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
|
||||
BulletSimAPI.SetInterpolationLinearVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetInterpolationAngularVelocity2(BSBody.Ptr, OMV.Vector3.Zero);
|
||||
BulletSimAPI.SetInterpolationVelocity2(BSBody.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
|
||||
// A dynamic object has mass
|
||||
IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.Ptr);
|
||||
OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Linkset.LinksetMass);
|
||||
BulletSimAPI.SetMassProps2(BSBody.Ptr, _mass, inertia);
|
||||
// Inertia is based on our new mass
|
||||
BulletSimAPI.UpdateInertiaTensor2(BSBody.Ptr);
|
||||
|
||||
// Various values for simulation limits
|
||||
BulletSimAPI.SetDamping2(BSBody.Ptr, Scene.Params.linearDamping, Scene.Params.angularDamping);
|
||||
BulletSimAPI.SetDeactivationTime2(BSBody.Ptr, Scene.Params.deactivationTime);
|
||||
BulletSimAPI.SetSleepingThresholds2(BSBody.Ptr, Scene.Params.linearSleepingThreshold, Scene.Params.angularSleepingThreshold);
|
||||
BulletSimAPI.SetContactProcessingThreshold2(BSBody.Ptr, Scene.Params.contactProcessingThreshold);
|
||||
|
||||
// There can be special things needed for implementing linksets
|
||||
Linkset.MakeDynamic(this);
|
||||
|
||||
// Force activation of the object so Bullet will act on it.
|
||||
BulletSimAPI.Activate2(BSBody.Ptr, true);
|
||||
}
|
||||
}
|
||||
|
||||
// "Making solid" means that other object will not pass through this object.
|
||||
private void MakeSolid(bool makeSolid)
|
||||
{
|
||||
if (makeSolid)
|
||||
{
|
||||
// Easy in Bullet -- just remove the object flag that controls collision response
|
||||
m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn on or off the flag controlling whether collision events are returned to the simulator.
|
||||
private void EnableCollisions(bool wantsCollisionEvents)
|
||||
{
|
||||
if (wantsCollisionEvents)
|
||||
{
|
||||
m_currentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
}
|
||||
}
|
||||
|
||||
// prims don't fly
|
||||
@@ -544,7 +659,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
_scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
|
||||
{
|
||||
DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
|
||||
BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
|
||||
BulletSimAPI.SetAngularVelocity2(BSBody.Ptr, _rotationalVelocity);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -561,7 +676,10 @@ public sealed class BSPrim : BSPhysObject
|
||||
_scene.TaintedObject("BSPrim.setBuoyancy", delegate()
|
||||
{
|
||||
DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
|
||||
// Buoyancy is faked by changing the gravity applied to the object
|
||||
float grav = Scene.Params.gravity * (1f - _buoyancy);
|
||||
BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav));
|
||||
// BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -609,7 +727,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()
|
||||
@@ -623,8 +741,9 @@ public sealed class BSPrim : BSPhysObject
|
||||
}
|
||||
m_accumulatedForces.Clear();
|
||||
}
|
||||
DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
|
||||
BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
|
||||
DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
|
||||
// For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
|
||||
BulletSimAPI.ApplyCentralForce2(BSBody.Ptr, fSum);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -644,7 +763,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 +771,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() {
|
||||
@@ -959,36 +1078,44 @@ public sealed class BSPrim : BSPhysObject
|
||||
}// end CalculateMass
|
||||
#endregion Mass Calculation
|
||||
|
||||
// Create the geometry information in Bullet for later use
|
||||
// The objects needs a hull if it's physical otherwise a mesh is enough
|
||||
// No locking here because this is done when we know physics is not simulating
|
||||
// if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
|
||||
// Returns 'true' if the geometry was rebuilt
|
||||
// Create the geometry information in Bullet for later use.
|
||||
// The objects needs a hull if it's physical otherwise a mesh is enough.
|
||||
// No locking here because this is done when we know physics is not simulating.
|
||||
// if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
|
||||
// Returns 'true' if the geometry was rebuilt.
|
||||
// Called at taint-time!
|
||||
private bool CreateGeom(bool forceRebuild)
|
||||
{
|
||||
// the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
|
||||
bool ret = false;
|
||||
if (!_scene.NeedsMeshing(_pbs))
|
||||
bool haveShape = false;
|
||||
|
||||
// If the prim attributes are simple, this could be a simple Bullet native shape
|
||||
if ((_pbs.SculptEntry && !Scene.ShouldMeshSculptedPrim)
|
||||
|| (_pbs.ProfileBegin == 0 && _pbs.ProfileEnd == 0
|
||||
&& _pbs.ProfileHollow == 0
|
||||
&& _pbs.PathTwist == 0 && _pbs.PathTwistBegin == 0
|
||||
&& _pbs.PathBegin == 0 && _pbs.PathEnd == 0
|
||||
&& _pbs.PathTaperX == 0 && _pbs.PathTaperY == 0
|
||||
&& _pbs.PathScaleX == 100 && _pbs.PathScaleY == 100
|
||||
&& _pbs.PathShearX == 0 && _pbs.PathShearY == 0) )
|
||||
{
|
||||
if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||
{
|
||||
// if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
|
||||
// {
|
||||
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
|
||||
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
|
||||
{
|
||||
DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
|
||||
_shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
|
||||
// Bullet native objects are scaled by the Bullet engine so pass the size in
|
||||
_scale = _size;
|
||||
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
|
||||
ret = true;
|
||||
}
|
||||
// }
|
||||
haveShape = true;
|
||||
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
|
||||
{
|
||||
DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
|
||||
_shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
|
||||
// Bullet native objects are scaled by the Bullet engine so pass the size in
|
||||
_scale = _size;
|
||||
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
|
||||
haveShape = true;
|
||||
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
|
||||
{
|
||||
DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
|
||||
@@ -999,16 +1126,16 @@ public sealed class BSPrim : BSPhysObject
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
// If a simple shape isn't happening, create a mesh and possibly a hull
|
||||
if (!haveShape)
|
||||
{
|
||||
if (IsPhysical)
|
||||
{
|
||||
if (forceRebuild || _hullKey == 0)
|
||||
{
|
||||
// physical objects require a hull for interaction.
|
||||
// This will create the mesh if it doesn't already exist
|
||||
CreateGeomHull();
|
||||
ret = true;
|
||||
// This also creates the mesh if it doesn't already exist
|
||||
ret = CreateGeomHull();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1016,8 +1143,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
if (forceRebuild || _meshKey == 0)
|
||||
{
|
||||
// Static (non-physical) objects only need a mesh for bumping into
|
||||
CreateGeomMesh();
|
||||
ret = true;
|
||||
ret = CreateGeomMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1025,7 +1151,9 @@ public sealed class BSPrim : BSPhysObject
|
||||
}
|
||||
|
||||
// No locking here because this is done when we know physics is not simulating
|
||||
private void CreateGeomMesh()
|
||||
// Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
|
||||
// Called at taint-time!
|
||||
private bool CreateGeomMesh()
|
||||
{
|
||||
// level of detail based on size and type of the object
|
||||
float lod = _scene.MeshLOD;
|
||||
@@ -1039,7 +1167,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
// m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
|
||||
|
||||
// if this new shape is the same as last time, don't recreate the mesh
|
||||
if (_meshKey == newMeshKey) return;
|
||||
if (_meshKey == newMeshKey) return false;
|
||||
|
||||
DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
|
||||
// Since we're recreating new, get rid of any previously generated shape
|
||||
@@ -1076,19 +1204,19 @@ public sealed class BSPrim : BSPhysObject
|
||||
_shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
|
||||
// meshes are already scaled by the meshmerizer
|
||||
_scale = new OMV.Vector3(1f, 1f, 1f);
|
||||
DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// No locking here because this is done when we know physics is not simulating
|
||||
private void CreateGeomHull()
|
||||
// Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
|
||||
private bool CreateGeomHull()
|
||||
{
|
||||
float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
|
||||
ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
|
||||
// m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
|
||||
|
||||
// if the hull hasn't changed, don't rebuild it
|
||||
if (newHullKey == _hullKey) return;
|
||||
if (newHullKey == _hullKey) return false;
|
||||
|
||||
DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
|
||||
|
||||
@@ -1191,7 +1319,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
// meshes are already scaled by the meshmerizer
|
||||
_scale = new OMV.Vector3(1f, 1f, 1f);
|
||||
DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Callback from convex hull creater with a newly created hull.
|
||||
@@ -1204,20 +1332,12 @@ public sealed class BSPrim : BSPhysObject
|
||||
|
||||
private void VerifyCorrectPhysicalShape()
|
||||
{
|
||||
if (IsStatic)
|
||||
{
|
||||
// if static, we don't need a hull so, if there is one, rebuild without it
|
||||
if (_hullKey != 0)
|
||||
{
|
||||
RecreateGeomAndObject();
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!IsStatic)
|
||||
{
|
||||
// if not static, it will need a hull to efficiently collide with things
|
||||
if (_hullKey == 0)
|
||||
{
|
||||
RecreateGeomAndObject();
|
||||
CreateGeomAndObject(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1236,8 +1356,9 @@ public sealed class BSPrim : BSPhysObject
|
||||
// m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
|
||||
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));
|
||||
// the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
|
||||
BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1261,15 +1382,20 @@ public sealed class BSPrim : BSPhysObject
|
||||
shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
|
||||
}
|
||||
|
||||
|
||||
// Rebuild the geometry and object.
|
||||
// This is called when the shape changes so we need to recreate the mesh/hull.
|
||||
// No locking here because this is done when the physics engine is not simulating
|
||||
private void RecreateGeomAndObject()
|
||||
private void CreateGeomAndObject(bool forceRebuild)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID);
|
||||
if (CreateGeom(true))
|
||||
// m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild);
|
||||
// Create the geometry that will make up the object
|
||||
if (CreateGeom(forceRebuild))
|
||||
{
|
||||
// Create the object and place it into the world
|
||||
CreateObject();
|
||||
// Make sure the properties are set on the new object
|
||||
UpdatePhysicalParameters();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1350,12 +1476,14 @@ public sealed class BSPrim : BSPhysObject
|
||||
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
||||
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
|
||||
|
||||
// BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr);
|
||||
|
||||
base.RequestPhysicsterseUpdate();
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
// For debugging, we also report the movement of children
|
||||
// For debugging, we can also report the movement of children
|
||||
DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
||||
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
|
||||
entprop.Acceleration, entprop.RotationalVelocity);
|
||||
@@ -1366,15 +1494,15 @@ public sealed class BSPrim : BSPhysObject
|
||||
// I've collided with something
|
||||
// Called at taint time from within the Step() function
|
||||
CollisionEventUpdate collisionCollection;
|
||||
public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
||||
public override bool Collide(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
||||
bool ret = false;
|
||||
|
||||
// The following lines make IsColliding() and IsCollidingGround() work
|
||||
_collidingStep = _scene.SimulationStep;
|
||||
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
||||
_collidingStep = Scene.SimulationStep;
|
||||
if (collidingWith <= Scene.TerrainManager.HighestTerrainID)
|
||||
{
|
||||
_collidingGroundStep = _scene.SimulationStep;
|
||||
_collidingGroundStep = Scene.SimulationStep;
|
||||
}
|
||||
|
||||
// DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
|
||||
@@ -1382,21 +1510,23 @@ public sealed class BSPrim : BSPhysObject
|
||||
// prims in the same linkset cannot collide with each other
|
||||
if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
|
||||
{
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// if someone has subscribed for collision events....
|
||||
if (SubscribedEvents()) {
|
||||
// throttle the collisions to the number of milliseconds specified in the subscription
|
||||
int nowTime = _scene.SimulationNowTime;
|
||||
int nowTime = Scene.SimulationNowTime;
|
||||
if (nowTime >= _nextCollisionOkTime) {
|
||||
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
||||
|
||||
if (collisionCollection == null)
|
||||
collisionCollection = new CollisionEventUpdate();
|
||||
collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// The scene is telling us it's time to pass our collected collisions into the simulator
|
||||
|
||||
@@ -56,7 +56,6 @@ using OpenMetaverse;
|
||||
// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
|
||||
// Implement LockAngularMotion
|
||||
// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
|
||||
// Does NeedsMeshing() really need to exclude all the different shapes?
|
||||
// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
|
||||
// Add PID movement operations. What does ScenePresence.MoveToTarget do?
|
||||
// Check terrain size. 128 or 127?
|
||||
@@ -79,7 +78,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
|
||||
// Following is a kludge and can be removed when avatar animation updating is
|
||||
// moved to a better place.
|
||||
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
|
||||
private HashSet<BSPhysObject> m_avatarsWithCollisions = new HashSet<BSPhysObject>();
|
||||
|
||||
// List of all the objects that have vehicle properties and should be called
|
||||
// to update each physics step.
|
||||
@@ -111,11 +110,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
private long m_simulationStep = 0;
|
||||
public long SimulationStep { get { return m_simulationStep; } }
|
||||
|
||||
// The length of the last timestep we were asked to simulate.
|
||||
// This is used by the vehicle code. Since the vehicle code is called
|
||||
// once per simulation step, its constants need to be scaled by this.
|
||||
public float LastSimulatedTimestep { get; private set; }
|
||||
|
||||
// A value of the time now so all the collision and update routines do not have to get their own
|
||||
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
||||
public int SimulationNowTime { get; private set; }
|
||||
@@ -132,8 +126,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
private EntityProperties[] m_updateArray;
|
||||
private GCHandle m_updateArrayPinnedHandle;
|
||||
|
||||
private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
|
||||
private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
|
||||
public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
|
||||
public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
|
||||
|
||||
public float PID_D { get; private set; } // derivative
|
||||
public float PID_P { get; private set; } // proportional
|
||||
@@ -153,6 +147,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
{
|
||||
get { return new Vector3(0f, 0f, Params.gravity); }
|
||||
}
|
||||
// Just the Z value of the gravity
|
||||
public float DefaultGravityZ
|
||||
{
|
||||
get { return Params.gravity; }
|
||||
}
|
||||
|
||||
public float MaximumObjectMass { get; private set; }
|
||||
|
||||
@@ -171,8 +170,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
callback = c;
|
||||
}
|
||||
}
|
||||
private Object _taintLock = new Object(); // lock for using the next object
|
||||
private List<TaintCallbackEntry> _taintedObjects;
|
||||
private Object _taintLock = new Object();
|
||||
|
||||
// A pointer to an instance if this structure is passed to the C++ code
|
||||
// Used to pass basic configuration values to the unmanaged code.
|
||||
@@ -465,12 +464,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
int collidersCount = 0;
|
||||
IntPtr collidersPtr;
|
||||
|
||||
LastSimulatedTimestep = timeStep;
|
||||
|
||||
// prevent simulation until we've been initialized
|
||||
if (!m_initialized) return 10.0f;
|
||||
|
||||
int simulateStartTime = Util.EnvironmentTickCount();
|
||||
if (!m_initialized) return 5.0f;
|
||||
|
||||
// update the prim states while we know the physics engine is not busy
|
||||
int numTaints = _taintedObjects.Count;
|
||||
@@ -478,6 +473,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
// Some of the prims operate with special vehicle properties
|
||||
ProcessVehicles(timeStep);
|
||||
numTaints += _taintedObjects.Count;
|
||||
ProcessTaints(); // the vehicles might have added taints
|
||||
|
||||
// step the physical world one interval
|
||||
@@ -506,6 +502,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// Get a value for 'now' so all the collision and update routines don't have to get their own
|
||||
SimulationNowTime = Util.EnvironmentTickCount();
|
||||
|
||||
// This is a kludge to get avatar movement updates.
|
||||
// ODE sends collisions for avatars even if there are have been no collisions. This updates
|
||||
// avatar animations and stuff.
|
||||
// If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
|
||||
m_objectsWithCollisions = new HashSet<BSPhysObject>(m_avatarsWithCollisions);
|
||||
|
||||
// If there were collisions, process them by sending the event to the prim.
|
||||
// Collisions must be processed before updates.
|
||||
if (collidersCount > 0)
|
||||
@@ -527,13 +529,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
bsp.SendCollisions();
|
||||
m_objectsWithCollisions.Clear();
|
||||
|
||||
// This is a kludge to get avatar movement updated.
|
||||
// ODE sends collisions even if there are none and this is used to update
|
||||
// avatar animations and stuff.
|
||||
foreach (BSPhysObject bpo in m_avatarsWithCollisions)
|
||||
bpo.SendCollisions();
|
||||
// m_avatarsWithCollisions.Clear();
|
||||
|
||||
// If any of the objects had updated properties, tell the object it has been changed by the physics engine
|
||||
if (updatedEntityCount > 0)
|
||||
{
|
||||
@@ -544,7 +539,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
if (PhysObjects.TryGetValue(entprop.ID, out pobj))
|
||||
{
|
||||
pobj.UpdateProperties(entprop);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -558,18 +552,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
}
|
||||
}
|
||||
|
||||
// this is a waste since the outside routine also calcuates the physics simulation
|
||||
// period. TODO: There should be a way of computing physics frames from simulator computation.
|
||||
// long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
|
||||
// return (timeStep * (float)simulateTotalTime);
|
||||
|
||||
// TODO: FIX THIS: fps calculation possibly wrong.
|
||||
// This calculation says 1/timeStep is the ideal frame rate. Any time added to
|
||||
// that by the physics simulation gives a slower frame rate.
|
||||
long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
|
||||
if (totalSimulationTime >= timeStep)
|
||||
return 0;
|
||||
return 1f / (timeStep + totalSimulationTime);
|
||||
// The physics engine returns the number of milliseconds it simulated this call.
|
||||
// These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
|
||||
// Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS.
|
||||
return numSubSteps * m_fixedTimeStep;
|
||||
}
|
||||
|
||||
// Something has collided
|
||||
@@ -580,28 +566,25 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
return; // don't send collisions to the terrain
|
||||
}
|
||||
|
||||
BSPhysObject collider = PhysObjects[localID];
|
||||
// TODO: as of this code, terrain was not in the physical object list.
|
||||
// When BSTerrain is created and it will be in the list, we can remove
|
||||
// the possibility that it's not there and just fetch the collidee.
|
||||
BSPhysObject collidee = null;
|
||||
BSPhysObject collider;
|
||||
if (!PhysObjects.TryGetValue(localID, out collider))
|
||||
{
|
||||
// If the object that is colliding cannot be found, just ignore the collision.
|
||||
return;
|
||||
}
|
||||
|
||||
ActorTypes type = ActorTypes.Prim;
|
||||
if (collidingWith <= TerrainManager.HighestTerrainID)
|
||||
{
|
||||
type = ActorTypes.Ground;
|
||||
}
|
||||
else
|
||||
{
|
||||
collidee = PhysObjects[collidingWith];
|
||||
if (collidee is BSCharacter)
|
||||
type = ActorTypes.Agent;
|
||||
}
|
||||
// The terrain is not in the physical object list so 'collidee'
|
||||
// can be null when Collide() is called.
|
||||
BSPhysObject collidee = null;
|
||||
PhysObjects.TryGetValue(collidingWith, out collidee);
|
||||
|
||||
// DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
|
||||
|
||||
collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration);
|
||||
m_objectsWithCollisions.Add(collider);
|
||||
if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
|
||||
{
|
||||
// If a collision was posted, remember to send it to the simulator
|
||||
m_objectsWithCollisions.Add(collider);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -619,9 +602,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
public override void SetWaterLevel(float baseheight)
|
||||
{
|
||||
m_waterLevel = baseheight;
|
||||
// TODO: pass to physics engine so things will float?
|
||||
}
|
||||
public float GetWaterLevel()
|
||||
// Someday....
|
||||
public float GetWaterLevelAtXYZ(Vector3 loc)
|
||||
{
|
||||
return m_waterLevel;
|
||||
}
|
||||
@@ -659,121 +642,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
public override bool IsThreaded { get { return false; } }
|
||||
|
||||
/// <summary>
|
||||
/// Routine to figure out if we need to mesh this prim with our mesher
|
||||
/// </summary>
|
||||
/// <param name="pbs"></param>
|
||||
/// <returns>true if the prim needs meshing</returns>
|
||||
public bool NeedsMeshing(PrimitiveBaseShape pbs)
|
||||
{
|
||||
// most of this is redundant now as the mesher will return null if it cant mesh a prim
|
||||
// but we still need to check for sculptie meshing being enabled so this is the most
|
||||
// convenient place to do it for now...
|
||||
|
||||
// int iPropertiesNotSupportedDefault = 0;
|
||||
|
||||
if (pbs.SculptEntry && !_meshSculptedPrim)
|
||||
{
|
||||
// Render sculpties as boxes
|
||||
return false;
|
||||
}
|
||||
|
||||
// if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet
|
||||
// can use an internal representation for the prim
|
||||
if (!_forceSimplePrimMeshing)
|
||||
{
|
||||
if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
|
||||
|| (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
|
||||
&& pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
|
||||
{
|
||||
|
||||
if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
|
||||
&& pbs.ProfileHollow == 0
|
||||
&& pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
|
||||
&& pbs.PathBegin == 0 && pbs.PathEnd == 0
|
||||
&& pbs.PathTaperX == 0 && pbs.PathTaperY == 0
|
||||
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
|
||||
&& pbs.PathShearX == 0 && pbs.PathShearY == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: verify that the mesher will now do all these shapes
|
||||
if (pbs.ProfileHollow != 0)
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
|
||||
iPropertiesNotSupportedDefault++;
|
||||
|
||||
// test for torus
|
||||
if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
|
||||
{
|
||||
if (pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||
{
|
||||
iPropertiesNotSupportedDefault++;
|
||||
}
|
||||
}
|
||||
else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
|
||||
{
|
||||
if (pbs.PathCurve == (byte)Extrusion.Straight)
|
||||
{
|
||||
iPropertiesNotSupportedDefault++;
|
||||
}
|
||||
// ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
|
||||
else if (pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||
{
|
||||
iPropertiesNotSupportedDefault++;
|
||||
}
|
||||
}
|
||||
else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
|
||||
{
|
||||
if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
|
||||
{
|
||||
iPropertiesNotSupportedDefault++;
|
||||
}
|
||||
}
|
||||
else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
|
||||
{
|
||||
if (pbs.PathCurve == (byte)Extrusion.Straight)
|
||||
{
|
||||
iPropertiesNotSupportedDefault++;
|
||||
}
|
||||
else if (pbs.PathCurve == (byte)Extrusion.Curve1)
|
||||
{
|
||||
iPropertiesNotSupportedDefault++;
|
||||
}
|
||||
}
|
||||
if (iPropertiesNotSupportedDefault == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calls to the PhysicsActors can't directly call into the physics engine
|
||||
// because it might be busy. We delay changes to a known time.
|
||||
// We rely on C#'s closure to save and restore the context for the delegate.
|
||||
@@ -782,7 +650,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
if (!m_initialized) return;
|
||||
|
||||
lock (_taintLock)
|
||||
{
|
||||
_taintedObjects.Add(new TaintCallbackEntry(ident, callback));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -919,14 +790,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
{
|
||||
new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||
(s) => { return s.NumericBool(s._meshSculptedPrim); },
|
||||
(s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ),
|
||||
(s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||
(s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
|
||||
(s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
|
||||
new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||
(s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
|
||||
(s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
|
||||
(s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||
(s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
|
||||
(s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
|
||||
|
||||
new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
|
||||
8f,
|
||||
@@ -1162,8 +1033,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
|
||||
(s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
|
||||
new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0",
|
||||
0.0f,
|
||||
new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
|
||||
0.1f,
|
||||
(s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].linkConstraintCFM; },
|
||||
(s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
|
||||
@@ -1172,6 +1043,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].linkConstraintERP; },
|
||||
(s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
|
||||
new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
|
||||
40,
|
||||
(s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].linkConstraintSolverIterations; },
|
||||
(s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
|
||||
|
||||
new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
|
||||
0f,
|
||||
|
||||
@@ -154,27 +154,31 @@ public class BSTerrainManager
|
||||
|
||||
// The simulator wants to set a new heightmap for the terrain.
|
||||
public void SetTerrain(float[] heightMap) {
|
||||
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
|
||||
float[] localHeightMap = heightMap;
|
||||
m_physicsScene.TaintedObject("TerrainManager.SetTerrain", delegate()
|
||||
{
|
||||
// If a child of a mega-region, we shouldn't have any terrain allocated for us
|
||||
ReleaseGroundPlaneAndTerrain();
|
||||
// If doing the mega-prim stuff and we are the child of the zero region,
|
||||
// the terrain is added to our parent
|
||||
if (m_parentScene is BSScene)
|
||||
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
|
||||
{
|
||||
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
|
||||
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||
((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
|
||||
heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||
// If a child of a mega-region, we shouldn't have any terrain allocated for us
|
||||
ReleaseGroundPlaneAndTerrain();
|
||||
// If doing the mega-prim stuff and we are the child of the zero region,
|
||||
// the terrain is added to our parent
|
||||
if (m_parentScene is BSScene)
|
||||
{
|
||||
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
|
||||
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||
((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
|
||||
localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If not doing the mega-prim thing, just change the terrain
|
||||
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
||||
else
|
||||
{
|
||||
// If not doing the mega-prim thing, just change the terrain
|
||||
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
||||
|
||||
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||
}
|
||||
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
|
||||
@@ -319,6 +323,8 @@ public class BSTerrainManager
|
||||
|
||||
// Make sure the new shape is processed.
|
||||
BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
|
||||
|
||||
m_terrainModified = true;
|
||||
};
|
||||
|
||||
// There is the option to do the changes now (we're already in 'taint time'), or
|
||||
@@ -357,6 +363,8 @@ public class BSTerrainManager
|
||||
m_heightMaps.Add(terrainRegionBase, mapInfo);
|
||||
// Build the terrain
|
||||
UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
|
||||
|
||||
m_terrainModified = true;
|
||||
};
|
||||
|
||||
// If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
|
||||
@@ -383,7 +391,7 @@ public class BSTerrainManager
|
||||
private float lastHeightTX = 999999f;
|
||||
private float lastHeightTY = 999999f;
|
||||
private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
|
||||
public float GetTerrainHeightAtXY(float tX, float tY)
|
||||
private float GetTerrainHeightAtXY(float tX, float tY)
|
||||
{
|
||||
// You'd be surprized at the number of times this routine is called
|
||||
// with the same parameters as last time.
|
||||
@@ -403,19 +411,27 @@ public class BSTerrainManager
|
||||
{
|
||||
float regionX = tX - offsetX;
|
||||
float regionY = tY - offsetY;
|
||||
if (regionX > mapInfo.sizeX) regionX = 0;
|
||||
if (regionY > mapInfo.sizeY) 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);
|
||||
try
|
||||
{
|
||||
ret = mapInfo.heightMap[mapIndex];
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Sometimes they give us wonky values of X and Y. Give a warning and return something.
|
||||
m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}",
|
||||
LogHeader, terrainBaseXY, regionX, regionY);
|
||||
ret = HEIGHT_GETHEIGHT_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
|
||||
{
|
||||
m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
|
||||
LogHeader, m_physicsScene.RegionName, tX, tY);
|
||||
}
|
||||
m_terrainModified = false;
|
||||
lastHeight = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -213,12 +213,26 @@ public struct ConfigurationParameters
|
||||
public float linkConstraintTransMotorMaxForce;
|
||||
public float linkConstraintERP;
|
||||
public float linkConstraintCFM;
|
||||
public float linkConstraintSolverIterations;
|
||||
|
||||
public const float numericTrue = 1f;
|
||||
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 +247,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
|
||||
@@ -315,23 +396,6 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool CreateObject(uint worldID, ShapeData shapeData);
|
||||
|
||||
/* Remove old functionality
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void AddConstraint(uint worldID, uint id1, uint id2,
|
||||
Vector3 frame1, Quaternion frame1rot,
|
||||
Vector3 frame2, Quaternion frame2rot,
|
||||
Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool RemoveConstraintByID(uint worldID, uint id1);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
|
||||
*/
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
|
||||
|
||||
@@ -347,6 +411,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 +468,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 +479,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 +505,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,
|
||||
@@ -454,6 +522,21 @@ public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape);
|
||||
public static extern IntPtr BuildNativeShape2(IntPtr world,
|
||||
float shapeType, float collisionMargin, Vector3 scale);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool IsNativeShape2(IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateCompoundShape2(IntPtr sim);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
|
||||
|
||||
[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 bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
|
||||
|
||||
@@ -464,8 +547,16 @@ public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vecto
|
||||
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 IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||
@@ -484,6 +575,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 +628,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,88 +737,293 @@ 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 Vector3 CalculateLocalInertia2(IntPtr shape, float mass);
|
||||
|
||||
[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 DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
|
||||
|
||||
[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.
|
||||
|
||||
@@ -5465,27 +5465,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
/// Returns the index of the first occurrence of test
|
||||
/// in src.
|
||||
/// </summary>
|
||||
|
||||
/// <param name="src">Source list</param>
|
||||
/// <param name="test">List to search for</param>
|
||||
/// <returns>
|
||||
/// The index number of the point in src where test was found if it was found.
|
||||
/// Otherwise returns -1
|
||||
/// </returns>
|
||||
public LSL_Integer llListFindList(LSL_List src, LSL_List test)
|
||||
{
|
||||
|
||||
int index = -1;
|
||||
int length = src.Length - test.Length + 1;
|
||||
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
// If either list is empty, do not match
|
||||
|
||||
if (src.Length != 0 && test.Length != 0)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (src.Data[i].Equals(test.Data[0]))
|
||||
// Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
|
||||
// rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
|
||||
// and so the comparison fails even if the LSL_Integer conceptually has the same value.
|
||||
// Therefore, here we test Equals on both the source and destination objects.
|
||||
// However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
|
||||
if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
|
||||
{
|
||||
int j;
|
||||
for (j = 1; j < test.Length; j++)
|
||||
if (!src.Data[i+j].Equals(test.Data[j]))
|
||||
if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j])))
|
||||
break;
|
||||
|
||||
if (j == test.Length)
|
||||
{
|
||||
index = i;
|
||||
@@ -5496,19 +5505,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
}
|
||||
|
||||
return index;
|
||||
|
||||
}
|
||||
|
||||
public LSL_String llGetObjectName()
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
return m_host.Name!=null?m_host.Name:String.Empty;
|
||||
return m_host.Name !=null ? m_host.Name : String.Empty;
|
||||
}
|
||||
|
||||
public void llSetObjectName(string name)
|
||||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
m_host.Name = name!=null?name:String.Empty;
|
||||
m_host.Name = name != null ? name : String.Empty;
|
||||
}
|
||||
|
||||
public LSL_String llGetDate()
|
||||
@@ -9770,20 +9778,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 +10406,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;
|
||||
|
||||
134
OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
Normal file
134
OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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 NUnit.Framework;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Tests.Common;
|
||||
using OpenSim.Region.ScriptEngine.Shared;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using Nini.Config;
|
||||
using OpenSim.Region.ScriptEngine.Shared.Api;
|
||||
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Tests.Common.Mock;
|
||||
|
||||
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
|
||||
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
|
||||
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
|
||||
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
|
||||
|
||||
namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class LSL_ApiListTests
|
||||
{
|
||||
private LSL_Api m_lslApi;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
IConfigSource initConfigSource = new IniConfigSource();
|
||||
IConfig config = initConfigSource.AddConfig("XEngine");
|
||||
config.Set("Enabled", "true");
|
||||
|
||||
Scene scene = new SceneHelpers().SetupScene();
|
||||
SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart;
|
||||
|
||||
XEngine.XEngine engine = new XEngine.XEngine();
|
||||
engine.Initialise(initConfigSource);
|
||||
engine.AddRegion(scene);
|
||||
|
||||
m_lslApi = new LSL_Api();
|
||||
m_lslApi.Initialize(engine, part, null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestllListFindList()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
|
||||
LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3));
|
||||
|
||||
{
|
||||
// Test for a single item that should be found
|
||||
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
|
||||
Assert.That(result, Is.EqualTo(-1));
|
||||
}
|
||||
|
||||
{
|
||||
// Test for a single item that should be found
|
||||
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2)));
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
{
|
||||
// Test for a constant that should be found
|
||||
int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT));
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
{
|
||||
// Test for a list that should be found
|
||||
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3)));
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
{
|
||||
// Test for a single item not in the list
|
||||
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
|
||||
Assert.That(result, Is.EqualTo(-1));
|
||||
}
|
||||
|
||||
{
|
||||
// Test for something that should not be cast
|
||||
int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4")));
|
||||
Assert.That(result, Is.EqualTo(-1));
|
||||
}
|
||||
|
||||
{
|
||||
// Test for a list not in the list
|
||||
int result
|
||||
= m_lslApi.llListFindList(
|
||||
src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4)));
|
||||
Assert.That(result, Is.EqualTo(-1));
|
||||
}
|
||||
|
||||
{
|
||||
LSL_List srcWithConstants
|
||||
= new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET);
|
||||
|
||||
// Test for constants that appears in the source list that should be found
|
||||
int result
|
||||
= m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2)));
|
||||
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"];
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace OpenSim.Services.AssetService
|
||||
|
||||
m_Database = LoadPlugin<IAssetDataPlugin>(dllName);
|
||||
if (m_Database == null)
|
||||
throw new Exception("Could not find a storage interface in the given module");
|
||||
throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName));
|
||||
|
||||
m_Database.Initialise(connString);
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace OpenSim.Services.AssetService
|
||||
m_AssetLoader = LoadPlugin<IAssetLoader>(loaderName);
|
||||
|
||||
if (m_AssetLoader == null)
|
||||
throw new Exception("Asset loader could not be loaded");
|
||||
throw new Exception(string.Format("Asset loader could not be loaded from {0}", loaderName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -58,6 +58,8 @@ namespace OpenSim.Services.HypergridService
|
||||
|
||||
private UserAccountCache m_Cache;
|
||||
|
||||
private AssetPermissions m_AssetPerms;
|
||||
|
||||
public HGAssetService(IConfigSource config, string configName) : base(config, configName)
|
||||
{
|
||||
m_log.Debug("[HGAsset Service]: Starting");
|
||||
@@ -80,6 +82,10 @@ namespace OpenSim.Services.HypergridService
|
||||
m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL);
|
||||
|
||||
m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
|
||||
|
||||
// Permissions
|
||||
m_AssetPerms = new AssetPermissions(assetConfig);
|
||||
|
||||
}
|
||||
|
||||
#region IAssetService overrides
|
||||
@@ -90,6 +96,9 @@ namespace OpenSim.Services.HypergridService
|
||||
if (asset == null)
|
||||
return null;
|
||||
|
||||
if (!m_AssetPerms.AllowedExport(asset.Type))
|
||||
return null;
|
||||
|
||||
if (asset.Metadata.Type == (sbyte)AssetType.Object)
|
||||
asset.Data = AdjustIdentifiers(asset.Data); ;
|
||||
|
||||
@@ -112,16 +121,27 @@ namespace OpenSim.Services.HypergridService
|
||||
|
||||
public override byte[] GetData(string id)
|
||||
{
|
||||
byte[] data = base.GetData(id);
|
||||
AssetBase asset = Get(id);
|
||||
|
||||
if (data == null)
|
||||
if (asset == null)
|
||||
return null;
|
||||
|
||||
return AdjustIdentifiers(data);
|
||||
if (!m_AssetPerms.AllowedExport(asset.Type))
|
||||
return null;
|
||||
|
||||
return asset.Data;
|
||||
}
|
||||
|
||||
//public virtual bool Get(string id, Object sender, AssetRetrieved handler)
|
||||
|
||||
public override string Store(AssetBase asset)
|
||||
{
|
||||
if (!m_AssetPerms.AllowedImport(asset.Type))
|
||||
return string.Empty;
|
||||
|
||||
return base.Store(asset);
|
||||
}
|
||||
|
||||
public override bool Delete(string id)
|
||||
{
|
||||
// NOGO
|
||||
|
||||
@@ -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,52 @@ 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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +1,5 @@
|
||||
<configuration>
|
||||
<dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib" />
|
||||
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64" />
|
||||
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64" />
|
||||
<dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686" />
|
||||
<dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686" />
|
||||
<dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet-2.1.5.0-dotnet-1.dylib" />
|
||||
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-x86_64" />
|
||||
<dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet" />
|
||||
</configuration>
|
||||
|
||||
Binary file not shown.
@@ -87,13 +87,13 @@
|
||||
;; from the selected region_info_source.
|
||||
; allow_regionless = false
|
||||
|
||||
;# {NonPhysicalPrimMin} {} {Minimum size of nonphysical prims?} {} 0.01
|
||||
;; Minimum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMin!).
|
||||
; NonphysicalPrimMin = 0.01
|
||||
;# {NonPhysicalPrimMin} {} {Minimum size of nonphysical prims?} {} 0.001
|
||||
;; Minimum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonPhysicalPrimMin!).
|
||||
; NonPhysicalPrimMin = 0.001
|
||||
|
||||
;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256
|
||||
;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!).
|
||||
; NonphysicalPrimMax = 256
|
||||
;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonPhysicalPrimMax!).
|
||||
; NonPhysicalPrimMax = 256
|
||||
|
||||
;# {PhysicalPrimMin} {} {Minimum size of physical prims?} {} 10
|
||||
;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file.
|
||||
@@ -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.
|
||||
|
||||
@@ -85,8 +85,8 @@
|
||||
;; from the selected region_info_source.
|
||||
allow_regionless = false
|
||||
|
||||
; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!).
|
||||
NonphysicalPrimMax = 256
|
||||
; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonPhysicalPrimMax!).
|
||||
NonPhysicalPrimMax = 256
|
||||
|
||||
; Maximum size of physical prims. Affects resizing of existing prims. This can be overriden in the region config file.
|
||||
PhysicalPrimMax = 10
|
||||
@@ -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.
|
||||
@@ -669,8 +673,7 @@
|
||||
; If true, avatar appearance information is resent to other avatars in the simulator every 60 seconds.
|
||||
; This may help with some situations where avatars are persistently grey, though it will not help
|
||||
; in other situations (e.g. appearance baking failures where the avatar only appears as a cloud to others).
|
||||
; This setting is experimental.
|
||||
ResendAppearanceUpdates = false
|
||||
ResendAppearanceUpdates = true
|
||||
|
||||
|
||||
[Attachments]
|
||||
@@ -703,6 +706,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"
|
||||
@@ -431,6 +437,18 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
|
||||
UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
|
||||
HomeURI = "http://127.0.0.1:8002"
|
||||
|
||||
;; The asset types that this grid can export to / import from other grids.
|
||||
;; Comma separated.
|
||||
;; Valid values are all the asset types in OpenMetaverse.AssetType, namely:
|
||||
;; Unknown, Texture, Sound, CallingCard, Landmark, Clothing, Object, Notecard, LSLText,
|
||||
;; LSLBytecode, TextureTGA, Bodypart, SoundWAV, ImageTGA, ImageJPEG, Animation, Gesture, Mesh
|
||||
;;
|
||||
;; Leave blank or commented if you don't want to apply any restrictions.
|
||||
;; A more strict, but still reasonable, policy may be to disallow the exchange
|
||||
;; of scripts, like so:
|
||||
; DisallowExport ="LSLText"
|
||||
; DisallowImport ="LSLBytecode"
|
||||
|
||||
[HGFriendsService]
|
||||
LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGFriendsService"
|
||||
UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -137,6 +137,26 @@
|
||||
;; uncomment the next line. You may want to do this on sims that have licensed content.
|
||||
; OutboundPermission = False
|
||||
|
||||
[HGAssetService]
|
||||
;
|
||||
; === HG ONLY ===
|
||||
; Change this to your server
|
||||
; accessible from other grids
|
||||
;
|
||||
HomeURI = "http://mygridserver.com:8002"
|
||||
|
||||
;; The asset types that this grid can export to / import from other grids.
|
||||
;; Comma separated.
|
||||
;; Valid values are all the asset types in OpenMetaverse.AssetType, namely:
|
||||
;; Unknown, Texture, Sound, CallingCard, Landmark, Clothing, Object, Notecard, LSLText,
|
||||
;; LSLBytecode, TextureTGA, Bodypart, SoundWAV, ImageTGA, ImageJPEG, Animation, Gesture, Mesh
|
||||
;;
|
||||
;; Leave blank or commented if you don't want to apply any restrictions.
|
||||
;; A more strict, but still reasonable, policy may be to disallow the exchange
|
||||
;; of scripts, like so:
|
||||
; DisallowExport ="LSLText"
|
||||
; DisallowImport ="LSLBytecode"
|
||||
|
||||
[HGFriendsModule]
|
||||
; User level required to be able to send friendship invitations to foreign users
|
||||
;LevelHGFriends = 0;
|
||||
|
||||
@@ -53,6 +53,19 @@
|
||||
[HGAssetService]
|
||||
HomeURI = "http://127.0.0.1:9000"
|
||||
|
||||
;; The asset types that this grid can export to / import from other grids.
|
||||
;; Comma separated.
|
||||
;; Valid values are all the asset types in OpenMetaverse.AssetType, namely:
|
||||
;; Unknown, Texture, Sound, CallingCard, Landmark, Clothing, Object, Notecard, LSLText,
|
||||
;; LSLBytecode, TextureTGA, Bodypart, SoundWAV, ImageTGA, ImageJPEG, Animation, Gesture, Mesh
|
||||
;;
|
||||
;; Leave blank or commented if you don't want to apply any restrictions.
|
||||
;; A more strict, but still reasonable, policy may be to disallow the exchange
|
||||
;; of scripts, like so:
|
||||
; DisallowExport ="LSLText"
|
||||
; DisallowImport ="LSLBytecode"
|
||||
|
||||
|
||||
[HGInventoryAccessModule]
|
||||
HomeURI = "http://127.0.0.1:9000"
|
||||
Gatekeeper = "http://127.0.0.1:9000"
|
||||
|
||||
@@ -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"
|
||||
@@ -151,6 +153,7 @@
|
||||
; For the InventoryServiceInConnector
|
||||
LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInventoryService"
|
||||
UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
|
||||
AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
|
||||
|
||||
;; The interface that local users get when they are in other grids
|
||||
;; This restricts/filters the asset operations from the outside
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user