Merge branch 'master' of ssh://3dhosting.de/var/git/careminster
commit
f142e1f394
|
@ -141,6 +141,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||||
availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod);
|
availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod);
|
||||||
|
|
||||||
// Agent management
|
// Agent management
|
||||||
|
availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod);
|
||||||
availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod);
|
availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod);
|
||||||
|
|
||||||
// User management
|
// User management
|
||||||
|
@ -1901,6 +1902,71 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
||||||
m_log.Info("[RADMIN]: Access List List Request complete");
|
m_log.Info("[RADMIN]: Access List List Request complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void XmlRpcGetAgentsMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
|
||||||
|
{
|
||||||
|
Hashtable responseData = (Hashtable)response.Value;
|
||||||
|
Hashtable requestData = (Hashtable)request.Params[0];
|
||||||
|
|
||||||
|
bool includeChildren = false;
|
||||||
|
|
||||||
|
if (requestData.Contains("include_children"))
|
||||||
|
bool.TryParse((string)requestData["include_children"], out includeChildren);
|
||||||
|
|
||||||
|
Scene scene;
|
||||||
|
GetSceneFromRegionParams(requestData, responseData, out scene);
|
||||||
|
|
||||||
|
ArrayList xmlRpcRegions = new ArrayList();
|
||||||
|
responseData["regions"] = xmlRpcRegions;
|
||||||
|
|
||||||
|
Hashtable xmlRpcRegion = new Hashtable();
|
||||||
|
xmlRpcRegions.Add(xmlRpcRegion);
|
||||||
|
|
||||||
|
xmlRpcRegion["name"] = scene.Name;
|
||||||
|
xmlRpcRegion["id"] = scene.RegionInfo.RegionID.ToString();
|
||||||
|
|
||||||
|
List<ScenePresence> agents = scene.GetScenePresences();
|
||||||
|
ArrayList xmlrpcAgents = new ArrayList();
|
||||||
|
|
||||||
|
foreach (ScenePresence agent in agents)
|
||||||
|
{
|
||||||
|
if (agent.IsChildAgent && !includeChildren)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Hashtable xmlRpcAgent = new Hashtable();
|
||||||
|
xmlRpcAgent.Add("name", agent.Name);
|
||||||
|
xmlRpcAgent.Add("id", agent.UUID.ToString());
|
||||||
|
xmlRpcAgent.Add("type", agent.PresenceType.ToString());
|
||||||
|
xmlRpcAgent.Add("current_parcel_id", agent.currentParcelUUID.ToString());
|
||||||
|
|
||||||
|
Vector3 pos = agent.AbsolutePosition;
|
||||||
|
xmlRpcAgent.Add("pos_x", pos.X.ToString());
|
||||||
|
xmlRpcAgent.Add("pos_y", pos.Y.ToString());
|
||||||
|
xmlRpcAgent.Add("pos_z", pos.Z.ToString());
|
||||||
|
|
||||||
|
Vector3 lookAt = agent.Lookat;
|
||||||
|
xmlRpcAgent.Add("lookat_x", lookAt.X.ToString());
|
||||||
|
xmlRpcAgent.Add("lookat_y", lookAt.Y.ToString());
|
||||||
|
xmlRpcAgent.Add("lookat_z", lookAt.Z.ToString());
|
||||||
|
|
||||||
|
Vector3 vel = agent.Velocity;
|
||||||
|
xmlRpcAgent.Add("vel_x", vel.X.ToString());
|
||||||
|
xmlRpcAgent.Add("vel_y", vel.Y.ToString());
|
||||||
|
xmlRpcAgent.Add("vel_z", vel.Z.ToString());
|
||||||
|
|
||||||
|
xmlRpcAgent.Add("is_flying", agent.Flying.ToString());
|
||||||
|
xmlRpcAgent.Add("is_sat_on_ground", agent.SitGround.ToString());
|
||||||
|
xmlRpcAgent.Add("is_sat_on_object", agent.IsSatOnObject.ToString());
|
||||||
|
|
||||||
|
xmlrpcAgents.Add(xmlRpcAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[REMOTE ADMIN]: XmlRpcGetAgents found {0} agents in {1}", xmlrpcAgents.Count, scene.Name);
|
||||||
|
|
||||||
|
xmlRpcRegion["agents"] = xmlrpcAgents;
|
||||||
|
responseData["success"] = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void XmlRpcTeleportAgentMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
|
private void XmlRpcTeleportAgentMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
|
||||||
{
|
{
|
||||||
Hashtable responseData = (Hashtable)response.Value;
|
Hashtable responseData = (Hashtable)response.Value;
|
||||||
|
|
|
@ -97,6 +97,14 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
+ " >= 1 - turns on outgoing event logging\n"
|
+ " >= 1 - turns on outgoing event logging\n"
|
||||||
+ " >= 2 - turns on poll notification",
|
+ " >= 2 - turns on poll notification",
|
||||||
HandleDebugEq);
|
HandleDebugEq);
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
|
"Debug",
|
||||||
|
false,
|
||||||
|
"show eq",
|
||||||
|
"show eq",
|
||||||
|
"Show contents of event queues for logged in avatars. Used for debugging.",
|
||||||
|
HandleShowEq);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
|
@ -138,7 +146,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
|
if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
|
||||||
{
|
{
|
||||||
MainConsole.Instance.OutputFormat("Usage: debug eq [0|1]");
|
MainConsole.Instance.OutputFormat("Usage: debug eq [0|1|2]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -148,6 +156,21 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void HandleShowEq(string module, string[] args)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("For scene {0}", m_scene.Name);
|
||||||
|
|
||||||
|
lock (queues)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<UUID, Queue<OSD>> kvp in queues)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat(
|
||||||
|
"For agent {0} there are {1} messages queued for send.",
|
||||||
|
kvp.Key, kvp.Value.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Always returns a valid queue
|
/// Always returns a valid queue
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -70,6 +70,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
|
|
||||||
private string m_MapImageServerURL = string.Empty;
|
private string m_MapImageServerURL = string.Empty;
|
||||||
private string m_SearchURL = string.Empty;
|
private string m_SearchURL = string.Empty;
|
||||||
|
private bool m_ExportSupported = false;
|
||||||
|
|
||||||
#region ISharedRegionModule Members
|
#region ISharedRegionModule Members
|
||||||
|
|
||||||
|
@ -87,6 +88,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
}
|
}
|
||||||
|
|
||||||
m_SearchURL = config.GetString("SearchServerURI", string.Empty);
|
m_SearchURL = config.GetString("SearchServerURI", string.Empty);
|
||||||
|
|
||||||
|
m_ExportSupported = config.GetBoolean("ExportSupported", m_ExportSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddDefaultFeatures();
|
AddDefaultFeatures();
|
||||||
|
@ -152,6 +155,9 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
if (m_SearchURL != string.Empty)
|
if (m_SearchURL != string.Empty)
|
||||||
gridServicesMap["search"] = m_SearchURL;
|
gridServicesMap["search"] = m_SearchURL;
|
||||||
m_features["GridServices"] = gridServicesMap;
|
m_features["GridServices"] = gridServicesMap;
|
||||||
|
|
||||||
|
if (m_ExportSupported)
|
||||||
|
m_features["ExportSupported"] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
#region INonSharedRegionModule
|
#region INonSharedRegionModule
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public int DebugLevel { get; set; }
|
||||||
|
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private IInventoryAccessModule m_invAccessModule;
|
private IInventoryAccessModule m_invAccessModule;
|
||||||
|
|
||||||
|
@ -76,11 +78,67 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
|
m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
|
||||||
|
|
||||||
if (Enabled)
|
if (Enabled)
|
||||||
|
{
|
||||||
m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
|
m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
|
||||||
|
m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
|
||||||
|
m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
|
||||||
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand(
|
||||||
|
"Debug",
|
||||||
|
false,
|
||||||
|
"debug attachments",
|
||||||
|
"debug attachments [0|1]",
|
||||||
|
"Turn on attachments debugging\n"
|
||||||
|
+ " <= 0 - turns off debugging\n"
|
||||||
|
+ " >= 1 - turns on attachment message logging\n",
|
||||||
|
HandleDebugAttachments);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
|
// TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleDebugAttachments(string module, string[] args)
|
||||||
|
{
|
||||||
|
int debugLevel;
|
||||||
|
|
||||||
|
if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugLevel = debugLevel;
|
||||||
|
MainConsole.Instance.OutputFormat(
|
||||||
|
"Set event queue debug level to {0} in {1}", DebugLevel, m_scene.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Listen for client triggered running state changes so that we can persist the script's object if necessary.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='localID'></param>
|
||||||
|
/// <param name='itemID'></param>
|
||||||
|
private void HandleScriptStateChange(uint localID, bool started)
|
||||||
|
{
|
||||||
|
SceneObjectGroup sog = m_scene.GetGroupByPrim(localID);
|
||||||
|
if (sog != null && sog.IsAttachment)
|
||||||
|
{
|
||||||
|
if (!started)
|
||||||
|
{
|
||||||
|
// FIXME: This is a convoluted way for working out whether the script state has changed to stop
|
||||||
|
// because it has been manually stopped or because the stop was called in UpdateDetachedObject() below
|
||||||
|
// This needs to be handled in a less tangled way.
|
||||||
|
ScenePresence sp = m_scene.GetScenePresence(sog.AttachedAvatar);
|
||||||
|
if (sp.ControllingClient.IsActive)
|
||||||
|
sog.HasGroupChanged = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sog.HasGroupChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
{
|
{
|
||||||
m_scene.UnregisterModuleInterface<IAttachmentsModule>(this);
|
m_scene.UnregisterModuleInterface<IAttachmentsModule>(this);
|
||||||
|
@ -153,10 +211,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// RezAttachments. This should only be called upon login on the first region.
|
|
||||||
/// Attachment rezzings on crossings and TPs are done in a different way.
|
|
||||||
/// </summary>
|
|
||||||
public void RezAttachments(IScenePresence sp)
|
public void RezAttachments(IScenePresence sp)
|
||||||
{
|
{
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
|
@ -165,10 +219,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (null == sp.Appearance)
|
if (null == sp.Appearance)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID);
|
m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0}", sp.Name);
|
if (sp.GetAttachments().Count > 0)
|
||||||
|
{
|
||||||
|
if (DebugLevel > 0)
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ATTACHMENTS MODULE]: Not doing simulator-side attachment rez for {0} in {1} as their viewer has already rezzed attachments",
|
||||||
|
m_scene.Name, sp.Name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DebugLevel > 0)
|
||||||
|
m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
|
||||||
|
|
||||||
XmlDocument doc = new XmlDocument();
|
XmlDocument doc = new XmlDocument();
|
||||||
string stateData = String.Empty;
|
string stateData = String.Empty;
|
||||||
|
@ -235,10 +301,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
// If we're an NPC then skip all the item checks and manipulations since we don't have an
|
// If we're an NPC then skip all the item checks and manipulations since we don't have an
|
||||||
// inventory right now.
|
// inventory right now.
|
||||||
if (sp.PresenceType == PresenceType.Npc)
|
RezSingleAttachmentFromInventoryInternal(
|
||||||
RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null, true);
|
sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, null);
|
||||||
else
|
|
||||||
RezSingleAttachmentFromInventory(sp, attach.ItemID, p | (uint)0x80, d);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -254,7 +318,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
|
if (DebugLevel > 0)
|
||||||
|
m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
|
||||||
|
|
||||||
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||||
|
|
||||||
|
@ -287,9 +352,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
|
m_log.DebugFormat(
|
||||||
// m_scene.RegionInfo.RegionName, sp.Name, silent);
|
"[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
|
||||||
|
m_scene.RegionInfo.RegionName, sp.Name, silent);
|
||||||
|
|
||||||
foreach (SceneObjectGroup sop in sp.GetAttachments())
|
foreach (SceneObjectGroup sop in sp.GetAttachments())
|
||||||
{
|
{
|
||||||
|
@ -299,12 +365,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
sp.ClearAttachments();
|
sp.ClearAttachments();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append)
|
public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool append)
|
||||||
{
|
{
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, false, append);
|
return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -315,9 +381,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
/// <param name='group'>The object to attach.</param>
|
/// <param name='group'>The object to attach.</param>
|
||||||
/// <param name='attachmentPt'></param>
|
/// <param name='attachmentPt'></param>
|
||||||
/// <param name='silent'></param>
|
/// <param name='silent'></param>
|
||||||
/// <param name='temp'></param>
|
/// <param name='addToInventory'>If true then add object to user inventory.</param>
|
||||||
/// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
|
/// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
|
||||||
private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool resumeScripts, bool append)
|
private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool resumeScripts, bool append)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
|
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
|
||||||
|
@ -334,9 +400,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
if (group.GetSittingAvatarsCount() != 0)
|
if (group.GetSittingAvatarsCount() != 0)
|
||||||
{
|
{
|
||||||
// m_log.WarnFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
|
m_log.WarnFormat(
|
||||||
// group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
|
"[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since {4} avatars are still sitting on it",
|
||||||
|
group.Name, group.LocalId, sp.Name, attachmentPt, group.GetSittingAvatarsCount());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -372,6 +439,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
|
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
|
||||||
|
|
||||||
|
if (attachments.Contains(group))
|
||||||
|
{
|
||||||
|
if (DebugLevel > 0)
|
||||||
|
m_log.WarnFormat(
|
||||||
|
"[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
|
||||||
|
group.Name, group.LocalId, sp.Name, attachmentPt);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
|
// If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
|
||||||
while (attachments.Count >= 5)
|
while (attachments.Count >= 5)
|
||||||
{
|
{
|
||||||
|
@ -395,8 +472,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
group.AttachmentPoint = attachmentPt;
|
group.AttachmentPoint = attachmentPt;
|
||||||
group.AbsolutePosition = attachPos;
|
group.AbsolutePosition = attachPos;
|
||||||
|
|
||||||
if (sp.PresenceType != PresenceType.Npc)
|
if (addToInventory && sp.PresenceType != PresenceType.Npc)
|
||||||
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append);
|
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
|
||||||
|
|
||||||
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
|
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
|
||||||
|
|
||||||
|
@ -415,17 +492,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp, bool append)
|
private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool append)
|
||||||
{
|
{
|
||||||
// Add the new attachment to inventory if we don't already have it.
|
// Add the new attachment to inventory if we don't already have it.
|
||||||
if (!temp)
|
UUID newAttachmentItemID = group.FromItemID;
|
||||||
{
|
if (newAttachmentItemID == UUID.Zero)
|
||||||
UUID newAttachmentItemID = group.FromItemID;
|
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
|
||||||
if (newAttachmentItemID == UUID.Zero)
|
|
||||||
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
|
|
||||||
|
|
||||||
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
|
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
|
public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
|
||||||
|
@ -438,40 +512,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}",
|
m_log.DebugFormat(
|
||||||
// (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
|
"[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}",
|
||||||
|
(AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
|
||||||
|
|
||||||
bool append = (AttachmentPt & 0x80) != 0;
|
// We check the attachments in the avatar appearance here rather than the objects attached to the
|
||||||
AttachmentPt &= 0x7f;
|
// ScenePresence itself so that we can ignore calls by viewer 2/3 to attach objects on startup. We are
|
||||||
|
// already doing this in ScenePresence.MakeRootAgent(). Simulator-side attaching needs to be done
|
||||||
// Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
|
// because pre-outfit folder viewers (most version 1 viewers) require it.
|
||||||
// This often happens during login - not sure the exact reason.
|
|
||||||
// For now, we will ignore the request. Unfortunately, this means that we need to dig through all the
|
|
||||||
// ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login
|
|
||||||
// before anything has actually been attached.
|
|
||||||
bool alreadyOn = false;
|
bool alreadyOn = false;
|
||||||
List<SceneObjectGroup> existingAttachments = sp.GetAttachments();
|
List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments();
|
||||||
foreach (SceneObjectGroup so in existingAttachments)
|
foreach (AvatarAttachment existingAttachment in existingAttachments)
|
||||||
{
|
{
|
||||||
if (so.FromItemID == itemID)
|
if (existingAttachment.ItemID == itemID)
|
||||||
{
|
{
|
||||||
alreadyOn = true;
|
alreadyOn = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (sp.Appearance.GetAttachmentForItem(itemID) != null)
|
|
||||||
if (alreadyOn)
|
if (alreadyOn)
|
||||||
{
|
{
|
||||||
// m_log.WarnFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
|
m_log.DebugFormat(
|
||||||
// sp.Name, itemID, AttachmentPt);
|
"[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
|
||||||
|
sp.Name, itemID, AttachmentPt);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc, append);
|
bool append = (AttachmentPt & 0x80) != 0;
|
||||||
|
AttachmentPt &= 0x7f;
|
||||||
|
|
||||||
|
return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
|
public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
|
||||||
|
@ -479,7 +553,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
|
if (DebugLevel > 0)
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ATTACHMENTS MODULE]: Rezzing {0} attachments from inventory for {1} in {2}",
|
||||||
|
rezlist.Count, sp.Name, m_scene.Name);
|
||||||
|
|
||||||
foreach (KeyValuePair<UUID, uint> rez in rezlist)
|
foreach (KeyValuePair<UUID, uint> rez in rezlist)
|
||||||
{
|
{
|
||||||
|
@ -497,9 +574,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
|
m_log.DebugFormat(
|
||||||
// sp.UUID, soLocalId);
|
"[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
|
||||||
|
sp.UUID, soLocalId);
|
||||||
|
|
||||||
SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
|
SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
|
||||||
|
|
||||||
|
@ -515,9 +593,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (inventoryID == UUID.Zero)
|
if (inventoryID == UUID.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
|
m_log.DebugFormat(
|
||||||
// so.Name, so.LocalId, inventoryID);
|
"[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
|
||||||
|
so.Name, so.LocalId, inventoryID);
|
||||||
|
|
||||||
lock (sp.AttachmentsSyncLock)
|
lock (sp.AttachmentsSyncLock)
|
||||||
{
|
{
|
||||||
|
@ -572,9 +651,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
|
m_log.DebugFormat(
|
||||||
// so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name);
|
"[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
|
||||||
|
so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name);
|
||||||
|
|
||||||
// Scripts MUST be snapshotted before the object is
|
// Scripts MUST be snapshotted before the object is
|
||||||
// removed from the scene because doing otherwise will
|
// removed from the scene because doing otherwise will
|
||||||
|
@ -700,12 +780,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
grp.HasGroupChanged = false; // Prevent it being saved over and over
|
grp.HasGroupChanged = false; // Prevent it being saved over and over
|
||||||
}
|
}
|
||||||
// else
|
else if (DebugLevel > 0)
|
||||||
// {
|
{
|
||||||
// m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
// "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
|
"[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
|
||||||
// grp.UUID, grp.AttachmentPoint);
|
grp.UUID, grp.AttachmentPoint);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -723,9 +803,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
private void AttachToAgent(
|
private void AttachToAgent(
|
||||||
IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
|
IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
|
m_log.DebugFormat(
|
||||||
// so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
|
"[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
|
||||||
|
so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
|
||||||
|
|
||||||
so.DetachFromBackup();
|
so.DetachFromBackup();
|
||||||
|
|
||||||
|
@ -750,9 +831,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
{
|
{
|
||||||
if (so.HasPrivateAttachmentPoint)
|
if (so.HasPrivateAttachmentPoint)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
|
m_log.DebugFormat(
|
||||||
// so.Name, sp.Name, so.AttachmentPoint);
|
"[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
|
||||||
|
so.Name, sp.Name, so.AttachmentPoint);
|
||||||
|
|
||||||
// As this scene object can now only be seen by the attaching avatar, tell everybody else in the
|
// As this scene object can now only be seen by the attaching avatar, tell everybody else in the
|
||||||
// scene that it's no longer in their awareness.
|
// scene that it's no longer in their awareness.
|
||||||
|
@ -786,9 +868,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (m_invAccessModule == null)
|
if (m_invAccessModule == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
|
m_log.DebugFormat(
|
||||||
// grp.Name, grp.LocalId, remoteClient.Name);
|
"[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
|
||||||
|
grp.Name, grp.LocalId, sp.Name);
|
||||||
|
|
||||||
InventoryItemBase newItem
|
InventoryItemBase newItem
|
||||||
= m_invAccessModule.CopyToInventory(
|
= m_invAccessModule.CopyToInventory(
|
||||||
|
@ -872,7 +955,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
|
protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
|
||||||
IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc, bool append)
|
IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
|
||||||
{
|
{
|
||||||
if (m_invAccessModule == null)
|
if (m_invAccessModule == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -897,6 +980,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DebugLevel > 0)
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}",
|
||||||
|
objatt.Name, sp.Name, attachmentPt, m_scene.Name);
|
||||||
|
|
||||||
// HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
|
// HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
|
||||||
objatt.HasGroupChanged = false;
|
objatt.HasGroupChanged = false;
|
||||||
bool tainted = false;
|
bool tainted = false;
|
||||||
|
@ -917,7 +1005,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
objatt.ResetOwnerChangeFlag();
|
objatt.ResetOwnerChangeFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachObjectInternal(sp, objatt, attachmentPt, false, true, false, true, append);
|
AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -971,9 +1059,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID);
|
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID);
|
||||||
if (changed && m_scene.AvatarFactory != null)
|
if (changed && m_scene.AvatarFactory != null)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
|
m_log.DebugFormat(
|
||||||
// sp.Name, att.Name, AttachmentPt);
|
"[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
|
||||||
|
sp.Name, att.Name, AttachmentPt);
|
||||||
|
|
||||||
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
|
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
|
||||||
}
|
}
|
||||||
|
@ -988,9 +1077,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
|
m_log.DebugFormat(
|
||||||
// (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
|
"[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
|
||||||
|
(AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
|
||||||
|
|
||||||
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
|
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
|
||||||
|
|
||||||
|
@ -1021,9 +1111,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
|
private void Client_OnObjectAttach(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
|
m_log.DebugFormat(
|
||||||
// objectLocalID, remoteClient.Name, AttachmentPt, silent);
|
"[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
|
||||||
|
objectLocalID, remoteClient.Name, AttachmentPt, silent);
|
||||||
|
|
||||||
if (!Enabled)
|
if (!Enabled)
|
||||||
return;
|
return;
|
||||||
|
@ -1056,11 +1147,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
AttachmentPt &= 0x7f;
|
AttachmentPt &= 0x7f;
|
||||||
|
|
||||||
// Calls attach with a Zero position
|
// Calls attach with a Zero position
|
||||||
if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false, append))
|
if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, false, append))
|
||||||
{
|
{
|
||||||
// m_log.Debug(
|
if (DebugLevel > 0)
|
||||||
// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
|
m_log.Debug(
|
||||||
// + ", AttachmentPoint: " + AttachmentPt);
|
"[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
|
||||||
|
+ ", AttachmentPoint: " + AttachmentPt);
|
||||||
|
|
||||||
// Save avatar attachment information
|
// Save avatar attachment information
|
||||||
m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId);
|
m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId);
|
||||||
|
|
|
@ -130,7 +130,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
config.AddConfig("Modules");
|
config.AddConfig("Modules");
|
||||||
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
|
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
|
||||||
|
|
||||||
modules.Add(new AttachmentsModule());
|
AttachmentsModule attMod = new AttachmentsModule();
|
||||||
|
attMod.DebugLevel = 1;
|
||||||
|
modules.Add(attMod);
|
||||||
modules.Add(new BasicInventoryAccessModule());
|
modules.Add(new BasicInventoryAccessModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
|
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
|
||||||
|
|
||||||
m_numberOfAttachEventsFired = 0;
|
m_numberOfAttachEventsFired = 0;
|
||||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false);
|
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
|
||||||
|
|
||||||
// Check status on scene presence
|
// Check status on scene presence
|
||||||
Assert.That(sp.HasAttachments(), Is.True);
|
Assert.That(sp.HasAttachments(), Is.True);
|
||||||
|
@ -244,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
|
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
|
||||||
|
|
||||||
m_numberOfAttachEventsFired = 0;
|
m_numberOfAttachEventsFired = 0;
|
||||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, false, false, false);
|
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false, false);
|
||||||
|
|
||||||
// Check status on scene presence
|
// Check status on scene presence
|
||||||
Assert.That(sp.HasAttachments(), Is.True);
|
Assert.That(sp.HasAttachments(), Is.True);
|
||||||
|
@ -277,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
|
|
||||||
// Test wearing a different attachment from the ground.
|
// Test wearing a different attachment from the ground.
|
||||||
{
|
{
|
||||||
scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false, false, false);
|
scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
|
||||||
|
|
||||||
// Check status on scene presence
|
// Check status on scene presence
|
||||||
Assert.That(sp.HasAttachments(), Is.True);
|
Assert.That(sp.HasAttachments(), Is.True);
|
||||||
|
@ -310,7 +312,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
|
|
||||||
// Test rewearing an already worn attachment from ground. Nothing should happen.
|
// Test rewearing an already worn attachment from ground. Nothing should happen.
|
||||||
{
|
{
|
||||||
scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, false, false, false);
|
scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
|
||||||
|
|
||||||
// Check status on scene presence
|
// Check status on scene presence
|
||||||
Assert.That(sp.HasAttachments(), Is.True);
|
Assert.That(sp.HasAttachments(), Is.True);
|
||||||
|
@ -368,7 +370,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
sp2.AbsolutePosition = new Vector3(0, 0, 0);
|
sp2.AbsolutePosition = new Vector3(0, 0, 0);
|
||||||
sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
|
sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
|
||||||
|
|
||||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false);
|
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
|
||||||
|
|
||||||
Assert.That(sp.HasAttachments(), Is.False);
|
Assert.That(sp.HasAttachments(), Is.False);
|
||||||
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||||
|
@ -728,7 +730,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
public void TestRezAttachmentsOnAvatarEntrance()
|
public void TestRezAttachmentsOnAvatarEntrance()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// log4net.Config.XmlConfigurator.Configure();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
Scene scene = CreateTestScene();
|
Scene scene = CreateTestScene();
|
||||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||||
|
|
|
@ -154,7 +154,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||||
|
|
||||||
void OnIncomingInstantMessage(GridInstantMessage im)
|
void OnIncomingInstantMessage(GridInstantMessage im)
|
||||||
{
|
{
|
||||||
if (im.dialog == (byte)InstantMessageDialog.RequestTeleport)
|
if (im.dialog == (byte)InstantMessageDialog.RequestTeleport
|
||||||
|
|| im.dialog == (byte)InstantMessageDialog.GodLikeRequestTeleport)
|
||||||
{
|
{
|
||||||
UUID sessionID = new UUID(im.imSessionID);
|
UUID sessionID = new UUID(im.imSessionID);
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
||||||
(uint)presence.AbsolutePosition.Y,
|
(uint)presence.AbsolutePosition.Y,
|
||||||
(uint)presence.AbsolutePosition.Z + 2);
|
(uint)presence.AbsolutePosition.Z + 2);
|
||||||
|
|
||||||
m_log.DebugFormat("[LURE]: TP invite with message {0}", message);
|
m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType);
|
||||||
|
|
||||||
GridInstantMessage m;
|
GridInstantMessage m;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ using System.Threading;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Capabilities;
|
using OpenSim.Framework.Capabilities;
|
||||||
using OpenSim.Framework.Client;
|
using OpenSim.Framework.Client;
|
||||||
|
using OpenSim.Framework.Monitoring;
|
||||||
using OpenSim.Region.Framework.Interfaces;
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
@ -77,6 +78,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public bool DisableInterRegionTeleportCancellation { get; set; }
|
public bool DisableInterRegionTeleportCancellation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of times inter-region teleport was attempted.
|
||||||
|
/// </summary>
|
||||||
|
private Stat m_interRegionTeleportAttempts;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of times inter-region teleport was aborted (due to simultaneous client logout).
|
||||||
|
/// </summary>
|
||||||
|
private Stat m_interRegionTeleportAborts;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of times inter-region teleport was successfully cancelled by the client.
|
||||||
|
/// </summary>
|
||||||
|
private Stat m_interRegionTeleportCancels;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of times inter-region teleport failed due to server/client/network problems (e.g. viewer failed to
|
||||||
|
/// connect with destination region).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is not necessarily a problem for this simulator - in open-grid/hg conditions, viewer connectivity to
|
||||||
|
/// destination simulator is unknown.
|
||||||
|
/// </remarks>
|
||||||
|
private Stat m_interRegionTeleportFailures;
|
||||||
|
|
||||||
protected bool m_Enabled = false;
|
protected bool m_Enabled = false;
|
||||||
|
|
||||||
public Scene Scene { get; private set; }
|
public Scene Scene { get; private set; }
|
||||||
|
@ -91,6 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
|
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
|
||||||
|
|
||||||
private IEventQueue m_eqModule;
|
private IEventQueue m_eqModule;
|
||||||
|
private IRegionCombinerModule m_regionCombinerModule;
|
||||||
|
|
||||||
#region ISharedRegionModule
|
#region ISharedRegionModule
|
||||||
|
|
||||||
|
@ -156,6 +183,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
Scene = scene;
|
Scene = scene;
|
||||||
|
|
||||||
|
m_interRegionTeleportAttempts =
|
||||||
|
new Stat(
|
||||||
|
"InterRegionTeleportAttempts",
|
||||||
|
"Number of inter-region teleports attempted.",
|
||||||
|
"This does not count attempts which failed due to pre-conditions (e.g. target simulator refused access).\n"
|
||||||
|
+ "You can get successfully teleports by subtracting aborts, cancels and teleport failures from this figure.",
|
||||||
|
"",
|
||||||
|
"entitytransfer",
|
||||||
|
Scene.Name,
|
||||||
|
StatType.Push,
|
||||||
|
null,
|
||||||
|
StatVerbosity.Debug);
|
||||||
|
|
||||||
|
m_interRegionTeleportAborts =
|
||||||
|
new Stat(
|
||||||
|
"InterRegionTeleportAborts",
|
||||||
|
"Number of inter-region teleports aborted due to client actions.",
|
||||||
|
"The chief action is simultaneous logout whilst teleporting.",
|
||||||
|
"",
|
||||||
|
"entitytransfer",
|
||||||
|
Scene.Name,
|
||||||
|
StatType.Push,
|
||||||
|
null,
|
||||||
|
StatVerbosity.Debug);
|
||||||
|
|
||||||
|
m_interRegionTeleportCancels =
|
||||||
|
new Stat(
|
||||||
|
"InterRegionTeleportCancels",
|
||||||
|
"Number of inter-region teleports cancelled by the client.",
|
||||||
|
null,
|
||||||
|
"",
|
||||||
|
"entitytransfer",
|
||||||
|
Scene.Name,
|
||||||
|
StatType.Push,
|
||||||
|
null,
|
||||||
|
StatVerbosity.Debug);
|
||||||
|
|
||||||
|
m_interRegionTeleportFailures =
|
||||||
|
new Stat(
|
||||||
|
"InterRegionTeleportFailures",
|
||||||
|
"Number of inter-region teleports that failed due to server/client/network issues.",
|
||||||
|
"This number may not be very helpful in open-grid/hg situations as the network connectivity/quality of destinations is uncontrollable.",
|
||||||
|
"",
|
||||||
|
"entitytransfer",
|
||||||
|
Scene.Name,
|
||||||
|
StatType.Push,
|
||||||
|
null,
|
||||||
|
StatVerbosity.Debug);
|
||||||
|
|
||||||
|
StatsManager.RegisterStat(m_interRegionTeleportAttempts);
|
||||||
|
StatsManager.RegisterStat(m_interRegionTeleportAborts);
|
||||||
|
StatsManager.RegisterStat(m_interRegionTeleportCancels);
|
||||||
|
StatsManager.RegisterStat(m_interRegionTeleportFailures);
|
||||||
|
|
||||||
scene.RegisterModuleInterface<IEntityTransferModule>(this);
|
scene.RegisterModuleInterface<IEntityTransferModule>(this);
|
||||||
scene.EventManager.OnNewClient += OnNewClient;
|
scene.EventManager.OnNewClient += OnNewClient;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +254,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
public virtual void Close() {}
|
public virtual void Close() {}
|
||||||
|
|
||||||
public virtual void RemoveRegion(Scene scene) {}
|
public virtual void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (m_Enabled)
|
||||||
|
{
|
||||||
|
StatsManager.DeregisterStat(m_interRegionTeleportAttempts);
|
||||||
|
StatsManager.DeregisterStat(m_interRegionTeleportAborts);
|
||||||
|
StatsManager.DeregisterStat(m_interRegionTeleportCancels);
|
||||||
|
StatsManager.DeregisterStat(m_interRegionTeleportFailures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void RegionLoaded(Scene scene)
|
public virtual void RegionLoaded(Scene scene)
|
||||||
{
|
{
|
||||||
|
@ -181,6 +271,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
|
m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
|
||||||
|
m_regionCombinerModule = Scene.RequestModuleInterface<IRegionCombinerModule>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -291,8 +382,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
Vector3 emergencyPos = new Vector3(128, 128, 128);
|
Vector3 emergencyPos = new Vector3(128, 128, 128);
|
||||||
|
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
|
"[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2} in {3}. Substituting {4}",
|
||||||
position, sp.Name, sp.UUID, emergencyPos);
|
position, sp.Name, sp.UUID, Scene.Name, emergencyPos);
|
||||||
|
|
||||||
position = emergencyPos;
|
position = emergencyPos;
|
||||||
}
|
}
|
||||||
|
@ -548,6 +639,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before this point, teleport 'failure' is due to checkable pre-conditions such as whether the target
|
||||||
|
// simulator can be found and is explicitly prepared to allow access. Therefore, we will not count these
|
||||||
|
// as server attempts.
|
||||||
|
m_interRegionTeleportAttempts.Value++;
|
||||||
|
|
||||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
|
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
|
||||||
|
|
||||||
// Fixing a bug where teleporting while sitting results in the avatar ending up removed from
|
// Fixing a bug where teleporting while sitting results in the avatar ending up removed from
|
||||||
|
@ -600,6 +696,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
bool logout = false;
|
bool logout = false;
|
||||||
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
|
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
|
||||||
{
|
{
|
||||||
|
m_interRegionTeleportFailures.Value++;
|
||||||
|
|
||||||
sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
|
sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
|
@ -611,6 +709,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
|
||||||
{
|
{
|
||||||
|
m_interRegionTeleportCancels.Value++;
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
|
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
@ -619,6 +719,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
}
|
}
|
||||||
else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
{
|
{
|
||||||
|
m_interRegionTeleportAborts.Value++;
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
@ -635,6 +737,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
IClientIPEndpoint ipepClient;
|
IClientIPEndpoint ipepClient;
|
||||||
if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
|
if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
|
||||||
|
finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
|
||||||
|
|
||||||
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
|
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
|
||||||
#region IP Translation for NAT
|
#region IP Translation for NAT
|
||||||
// Uses ipepClient above
|
// Uses ipepClient above
|
||||||
|
@ -688,6 +794,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
// establish th econnection to the destination which makes it return true.
|
// establish th econnection to the destination which makes it return true.
|
||||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
{
|
{
|
||||||
|
m_interRegionTeleportAborts.Value++;
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
@ -703,6 +811,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
{
|
{
|
||||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
{
|
{
|
||||||
|
m_interRegionTeleportAborts.Value++;
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
@ -720,6 +830,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
|
||||||
{
|
{
|
||||||
|
m_interRegionTeleportCancels.Value++;
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
|
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
@ -755,6 +867,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
{
|
{
|
||||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
{
|
{
|
||||||
|
m_interRegionTeleportAborts.Value++;
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
@ -767,6 +881,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion.");
|
Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,15 +923,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
// now we have a child agent in this region.
|
// now we have a child agent in this region.
|
||||||
sp.Reset();
|
sp.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commented pending deletion since this method no longer appears to do anything at all
|
|
||||||
// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
|
|
||||||
// if (sp.Scene.NeedSceneCacheClear(sp.UUID))
|
|
||||||
// {
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
|
|
||||||
// sp.UUID);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -852,6 +958,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
{
|
{
|
||||||
CleanupFailedInterRegionTeleport(sp, finalDestination);
|
CleanupFailedInterRegionTeleport(sp, finalDestination);
|
||||||
|
|
||||||
|
m_interRegionTeleportFailures.Value++;
|
||||||
|
|
||||||
sp.ControllingClient.SendTeleportFailed(
|
sp.ControllingClient.SendTeleportFailed(
|
||||||
string.Format(
|
string.Format(
|
||||||
"Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason));
|
"Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason));
|
||||||
|
@ -907,7 +1015,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
|
protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
|
||||||
{
|
{
|
||||||
return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
|
if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
|
||||||
|
{
|
||||||
|
Vector2 swCorner, neCorner;
|
||||||
|
GetMegaregionViewRange(out swCorner, out neCorner);
|
||||||
|
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Megaregion view of {0} is from {1} to {2} with new agent check for {3},{4}",
|
||||||
|
Scene.Name, swCorner, neCorner, newRegionX, newRegionY);
|
||||||
|
|
||||||
|
return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg)
|
protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg)
|
||||||
|
@ -1011,6 +1133,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
{
|
{
|
||||||
version = String.Empty;
|
version = String.Empty;
|
||||||
newpos = new Vector3(pos.X, pos.Y, pos.Z);
|
newpos = new Vector3(pos.X, pos.Y, pos.Z);
|
||||||
|
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
|
||||||
|
|
||||||
uint neighbourx = scene.RegionInfo.RegionLocX;
|
uint neighbourx = scene.RegionInfo.RegionLocX;
|
||||||
uint neighboury = scene.RegionInfo.RegionLocY;
|
uint neighboury = scene.RegionInfo.RegionLocY;
|
||||||
const float boundaryDistance = 1.7f;
|
const float boundaryDistance = 1.7f;
|
||||||
|
@ -1183,6 +1309,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
{
|
{
|
||||||
Thread.Sleep(10000);
|
Thread.Sleep(10000);
|
||||||
|
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Auto-reteleporting {0} to correct megaregion location {1},{2},{3} from {4}",
|
||||||
|
agent.Name, regionX, regionY, position, initiatingScene.Name);
|
||||||
|
|
||||||
|
agent.Scene.RequestTeleportLocation(
|
||||||
|
agent.ControllingClient,
|
||||||
|
Utils.UIntsToLong(regionX * (uint)Constants.RegionSize, regionY * (uint)Constants.RegionSize),
|
||||||
|
position,
|
||||||
|
agent.Lookat,
|
||||||
|
(uint)Constants.TeleportFlags.ViaLocation);
|
||||||
|
|
||||||
|
/*
|
||||||
IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
|
IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
|
||||||
if (im != null)
|
if (im != null)
|
||||||
{
|
{
|
||||||
|
@ -1217,6 +1355,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar)
|
private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar)
|
||||||
|
@ -1724,6 +1863,37 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
reg.RegionName, sp.Name, sp.UUID, reason);
|
reg.RegionName, sp.Name, sp.UUID, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the range considered in view of this megaregion (assuming this is a megaregion).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Expressed in 256m units</remarks>
|
||||||
|
/// <param name='swCorner'></param>
|
||||||
|
/// <param name='neCorner'></param>
|
||||||
|
private void GetMegaregionViewRange(out Vector2 swCorner, out Vector2 neCorner)
|
||||||
|
{
|
||||||
|
Border[] northBorders = Scene.NorthBorders.ToArray();
|
||||||
|
Border[] eastBorders = Scene.EastBorders.ToArray();
|
||||||
|
|
||||||
|
Vector2 extent = Vector2.Zero;
|
||||||
|
for (int i = 0; i < eastBorders.Length; i++)
|
||||||
|
{
|
||||||
|
extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < northBorders.Length; i++)
|
||||||
|
{
|
||||||
|
extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loss of fraction on purpose
|
||||||
|
extent.X = ((int)extent.X / (int)Constants.RegionSize);
|
||||||
|
extent.Y = ((int)extent.Y / (int)Constants.RegionSize);
|
||||||
|
|
||||||
|
swCorner.X = Scene.RegionInfo.RegionLocX - 1;
|
||||||
|
swCorner.Y = Scene.RegionInfo.RegionLocY - 1;
|
||||||
|
neCorner.X = Scene.RegionInfo.RegionLocX + extent.X;
|
||||||
|
neCorner.Y = Scene.RegionInfo.RegionLocY + extent.Y;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the list of regions that are considered to be neighbours to the given scene.
|
/// Return the list of regions that are considered to be neighbours to the given scene.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1736,15 +1906,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
Scene pScene = avatar.Scene;
|
Scene pScene = avatar.Scene;
|
||||||
RegionInfo m_regionInfo = pScene.RegionInfo;
|
RegionInfo m_regionInfo = pScene.RegionInfo;
|
||||||
|
|
||||||
Border[] northBorders = pScene.NorthBorders.ToArray();
|
|
||||||
Border[] southBorders = pScene.SouthBorders.ToArray();
|
|
||||||
Border[] eastBorders = pScene.EastBorders.ToArray();
|
|
||||||
Border[] westBorders = pScene.WestBorders.ToArray();
|
|
||||||
|
|
||||||
// Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't
|
// Leaving this as a "megaregions" computation vs "non-megaregions" computation; it isn't
|
||||||
// clear what should be done with a "far view" given that megaregions already extended the
|
// clear what should be done with a "far view" given that megaregions already extended the
|
||||||
// view to include everything in the megaregion
|
// view to include everything in the megaregion
|
||||||
if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1)
|
if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
|
||||||
{
|
{
|
||||||
int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance;
|
int dd = avatar.DrawDistance < Constants.RegionSize ? (int)Constants.RegionSize : (int)avatar.DrawDistance;
|
||||||
|
|
||||||
|
@ -1762,27 +1927,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Vector2 extent = Vector2.Zero;
|
Vector2 swCorner, neCorner;
|
||||||
for (int i = 0; i < eastBorders.Length; i++)
|
GetMegaregionViewRange(out swCorner, out neCorner);
|
||||||
{
|
|
||||||
extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < northBorders.Length; i++)
|
|
||||||
{
|
|
||||||
extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loss of fraction on purpose
|
List<GridRegion> neighbours
|
||||||
extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1;
|
= pScene.GridService.GetRegionRange(
|
||||||
extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1;
|
m_regionInfo.ScopeID,
|
||||||
|
(int)swCorner.X * (int)Constants.RegionSize,
|
||||||
|
(int)neCorner.X * (int)Constants.RegionSize,
|
||||||
|
(int)swCorner.Y * (int)Constants.RegionSize,
|
||||||
|
(int)neCorner.Y * (int)Constants.RegionSize);
|
||||||
|
|
||||||
int startX = (int)(pRegionLocX - 1) * (int)Constants.RegionSize;
|
|
||||||
int startY = (int)(pRegionLocY - 1) * (int)Constants.RegionSize;
|
|
||||||
|
|
||||||
int endX = ((int)pRegionLocX + (int)extent.X) * (int)Constants.RegionSize;
|
|
||||||
int endY = ((int)pRegionLocY + (int)extent.Y) * (int)Constants.RegionSize;
|
|
||||||
|
|
||||||
List<GridRegion> neighbours = pScene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
|
|
||||||
neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
|
neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
|
||||||
|
|
||||||
return neighbours;
|
return neighbours;
|
||||||
|
|
|
@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
public override void RemoveRegion(Scene scene)
|
public override void RemoveRegion(Scene scene)
|
||||||
{
|
{
|
||||||
base.AddRegion(scene);
|
base.RemoveRegion(scene);
|
||||||
|
|
||||||
if (m_Enabled)
|
if (m_Enabled)
|
||||||
scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
|
scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
|
||||||
|
|
|
@ -189,6 +189,45 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
|
case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
|
||||||
htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0);
|
htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case (int)HttpRequestConstants.HTTP_VERBOSE_THROTTLE:
|
||||||
|
|
||||||
|
// TODO implement me
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (int)HttpRequestConstants.HTTP_CUSTOM_HEADER:
|
||||||
|
//Parameters are in pairs and custom header takes
|
||||||
|
//arguments in pairs so adjust for header marker.
|
||||||
|
++i;
|
||||||
|
|
||||||
|
//Maximum of 8 headers are allowed based on the
|
||||||
|
//Second Life documentation for llHTTPRequest.
|
||||||
|
for (int count = 1; count <= 8; ++count)
|
||||||
|
{
|
||||||
|
//Not enough parameters remaining for a header?
|
||||||
|
if (parms.Length - i < 2)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Have we reached the end of the list of headers?
|
||||||
|
//End is marked by a string with a single digit.
|
||||||
|
//We already know we have at least one parameter
|
||||||
|
//so it is safe to do this check at top of loop.
|
||||||
|
if (Char.IsDigit(parms[i][0]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (htc.HttpCustomHeaders == null)
|
||||||
|
htc.HttpCustomHeaders = new List<string>();
|
||||||
|
|
||||||
|
htc.HttpCustomHeaders.Add(parms[i]);
|
||||||
|
htc.HttpCustomHeaders.Add(parms[i+1]);
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE:
|
||||||
|
htc.HttpPragmaNoCache = (int.Parse(parms[i + 1]) != 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,6 +392,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
// public const int HTTP_METHOD = 0;
|
// public const int HTTP_METHOD = 0;
|
||||||
// public const int HTTP_MIMETYPE = 1;
|
// public const int HTTP_MIMETYPE = 1;
|
||||||
// public const int HTTP_VERIFY_CERT = 3;
|
// public const int HTTP_VERIFY_CERT = 3;
|
||||||
|
// public const int HTTP_VERBOSE_THROTTLE = 4;
|
||||||
|
// public const int HTTP_CUSTOM_HEADER = 5;
|
||||||
|
// public const int HTTP_PRAGMA_NO_CACHE = 6;
|
||||||
private bool _finished;
|
private bool _finished;
|
||||||
public bool Finished
|
public bool Finished
|
||||||
{
|
{
|
||||||
|
@ -367,6 +409,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
public bool HttpVerifyCert = true;
|
public bool HttpVerifyCert = true;
|
||||||
public IWorkItemResult WorkItem = null;
|
public IWorkItemResult WorkItem = null;
|
||||||
|
|
||||||
|
//public bool HttpVerboseThrottle = true; // not implemented
|
||||||
|
public List<string> HttpCustomHeaders = null;
|
||||||
|
public bool HttpPragmaNoCache = true;
|
||||||
|
private Thread httpThread;
|
||||||
|
|
||||||
// Request info
|
// Request info
|
||||||
private UUID _itemID;
|
private UUID _itemID;
|
||||||
public UUID ItemID
|
public UUID ItemID
|
||||||
|
@ -434,12 +481,26 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
||||||
Request.Method = HttpMethod;
|
Request.Method = HttpMethod;
|
||||||
Request.ContentType = HttpMIMEType;
|
Request.ContentType = HttpMIMEType;
|
||||||
|
|
||||||
if(!HttpVerifyCert)
|
if (!HttpVerifyCert)
|
||||||
{
|
{
|
||||||
// We could hijack Connection Group Name to identify
|
// We could hijack Connection Group Name to identify
|
||||||
// a desired security exception. But at the moment we'll use a dummy header instead.
|
// a desired security exception. But at the moment we'll use a dummy header instead.
|
||||||
Request.Headers.Add("NoVerifyCert", "true");
|
Request.Headers.Add("NoVerifyCert", "true");
|
||||||
}
|
}
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// Request.ConnectionGroupName="Verify";
|
||||||
|
// }
|
||||||
|
if (!HttpPragmaNoCache)
|
||||||
|
{
|
||||||
|
Request.Headers.Add("Pragma", "no-cache");
|
||||||
|
}
|
||||||
|
if (HttpCustomHeaders != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < HttpCustomHeaders.Count; i += 2)
|
||||||
|
Request.Headers.Add(HttpCustomHeaders[i],
|
||||||
|
HttpCustomHeaders[i+1]);
|
||||||
|
}
|
||||||
if (proxyurl != null && proxyurl.Length > 0)
|
if (proxyurl != null && proxyurl.Length > 0)
|
||||||
{
|
{
|
||||||
if (proxyexcepts != null && proxyexcepts.Length > 0)
|
if (proxyexcepts != null && proxyexcepts.Length > 0)
|
||||||
|
|
|
@ -597,6 +597,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
cdl.AddRow("LightFalloff", s.LightFalloff);
|
cdl.AddRow("LightFalloff", s.LightFalloff);
|
||||||
cdl.AddRow("LightIntensity", s.LightIntensity);
|
cdl.AddRow("LightIntensity", s.LightIntensity);
|
||||||
cdl.AddRow("LightRadius", s.LightRadius);
|
cdl.AddRow("LightRadius", s.LightRadius);
|
||||||
|
cdl.AddRow("Location (relative)", sop.RelativePosition);
|
||||||
cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a"));
|
cdl.AddRow("Media", string.Format("{0} entries", s.Media != null ? s.Media.Count.ToString() : "n/a"));
|
||||||
cdl.AddRow("PathBegin", s.PathBegin);
|
cdl.AddRow("PathBegin", s.PathBegin);
|
||||||
cdl.AddRow("PathEnd", s.PathEnd);
|
cdl.AddRow("PathEnd", s.PathEnd);
|
||||||
|
@ -619,6 +620,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
||||||
cdl.AddRow("ProjectionFocus", s.ProjectionFocus);
|
cdl.AddRow("ProjectionFocus", s.ProjectionFocus);
|
||||||
cdl.AddRow("ProjectionFOV", s.ProjectionFOV);
|
cdl.AddRow("ProjectionFOV", s.ProjectionFOV);
|
||||||
cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID);
|
cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID);
|
||||||
|
cdl.AddRow("Rotation (Relative)", sop.RotationOffset);
|
||||||
|
cdl.AddRow("Rotation (World)", sop.GetWorldRotation());
|
||||||
cdl.AddRow("Scale", s.Scale);
|
cdl.AddRow("Scale", s.Scale);
|
||||||
cdl.AddRow(
|
cdl.AddRow(
|
||||||
"SculptData",
|
"SculptData",
|
||||||
|
|
|
@ -54,6 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// RezAttachments. This should only be called upon login on the first region.
|
/// RezAttachments. This should only be called upon login on the first region.
|
||||||
/// Attachment rezzings on crossings and TPs are done in a different way.
|
/// Attachment rezzings on crossings and TPs are done in a different way.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is only actually necessary for viewers which do not have a current outfit folder (these viewers make
|
||||||
|
/// their own attachment calls on login) and agents which have attachments but no viewer (e.g. NPCs).
|
||||||
|
/// </remarks>
|
||||||
/// <param name="sp"></param>
|
/// <param name="sp"></param>
|
||||||
void RezAttachments(IScenePresence sp);
|
void RezAttachments(IScenePresence sp);
|
||||||
|
|
||||||
|
@ -77,14 +81,16 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
void DeleteAttachmentsFromScene(IScenePresence sp, bool silent);
|
void DeleteAttachmentsFromScene(IScenePresence sp, bool silent);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attach an object to an avatar
|
/// Attach an object to an avatar.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sp"></param>
|
/// <param name="sp"></param>
|
||||||
/// <param name="grp"></param>
|
/// <param name="grp"></param>
|
||||||
/// <param name="AttachmentPt"></param>
|
/// <param name="AttachmentPt"></param>
|
||||||
/// <param name="silent"></param>
|
/// <param name="silent"></param>
|
||||||
|
/// <param name="addToInventory">If true then add object to user inventory</param>
|
||||||
|
/// <param name="append">Append to attachment point rather than replace.</param>
|
||||||
/// <returns>true if the object was successfully attached, false otherwise</returns>
|
/// <returns>true if the object was successfully attached, false otherwise</returns>
|
||||||
bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool temp, bool append);
|
bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool addToInventory, bool append);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rez an attachment from user inventory and change inventory status to match.
|
/// Rez an attachment from user inventory and change inventory status to match.
|
||||||
|
|
|
@ -36,6 +36,9 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
HTTP_MIMETYPE = 1,
|
HTTP_MIMETYPE = 1,
|
||||||
HTTP_BODY_MAXLENGTH = 2,
|
HTTP_BODY_MAXLENGTH = 2,
|
||||||
HTTP_VERIFY_CERT = 3,
|
HTTP_VERIFY_CERT = 3,
|
||||||
|
HTTP_VERBOSE_THROTTLE = 4,
|
||||||
|
HTTP_CUSTOM_HEADER = 5,
|
||||||
|
HTTP_PRAGMA_NO_CACHE = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IHttpRequestModule
|
public interface IHttpRequestModule
|
||||||
|
|
|
@ -34,7 +34,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
public class Border
|
public class Border
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Line perpendicular to the Direction Cardinal. Z value is the
|
/// Line perpendicular to the Direction Cardinal. Z value is the
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -81,6 +80,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
TriggerRegionY = triggerRegionY;
|
TriggerRegionY = triggerRegionY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests to see if the given position would cross this border.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public bool TestCross(Vector3 position)
|
public bool TestCross(Vector3 position)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
|
@ -2645,7 +2645,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2863,6 +2862,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
|
RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
|
||||||
|
|
||||||
|
// We must currently not resume scripts at this stage since AttachmentsModule does not have the
|
||||||
|
// information that this is due to a teleport/border cross rather than an ordinary attachment.
|
||||||
|
// We currently do this in Scene.MakeRootAgent() instead.
|
||||||
if (AttachmentsModule != null)
|
if (AttachmentsModule != null)
|
||||||
AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
|
AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
|
||||||
}
|
}
|
||||||
|
@ -2979,35 +2981,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_eventManager.TriggerOnNewPresence(sp);
|
m_eventManager.TriggerOnNewPresence(sp);
|
||||||
|
|
||||||
sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
|
sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
|
||||||
|
|
||||||
// The first agent upon login is a root agent by design.
|
|
||||||
// For this agent we will have to rez the attachments.
|
|
||||||
// All other AddNewClient calls find aCircuit.child to be true.
|
|
||||||
if (aCircuit.child == false)
|
|
||||||
{
|
|
||||||
// We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
|
|
||||||
// start the scripts again (since this is done in RezAttachments()).
|
|
||||||
// XXX: This is convoluted.
|
|
||||||
sp.IsChildAgent = false;
|
|
||||||
sp.IsLoggingIn = true;
|
|
||||||
|
|
||||||
// We leave a 5 second pause before attempting to rez attachments to avoid a clash with
|
|
||||||
// version 3 viewers that maybe doing their own attachment rezzing related to their current
|
|
||||||
// outfit folder on startup. If these operations do clash, then the symptoms are invisible
|
|
||||||
// attachments until one zooms in on the avatar.
|
|
||||||
//
|
|
||||||
// We do not pause if we are launching on the same thread anyway in order to avoid pointlessly
|
|
||||||
// delaying any attachment related regression tests.
|
|
||||||
if (AttachmentsModule != null)
|
|
||||||
Util.FireAndForget(
|
|
||||||
o =>
|
|
||||||
{
|
|
||||||
if (Util.FireAndForgetMethod != FireAndForgetMethod.None)
|
|
||||||
Thread.Sleep(5000);
|
|
||||||
|
|
||||||
AttachmentsModule.RezAttachments(sp);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4344,33 +4317,33 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// Triggered when an agent crosses into this sim. Also happens on initial login.
|
// /// Triggered when an agent crosses into this sim. Also happens on initial login.
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
/// <param name="agentID"></param>
|
// /// <param name="agentID"></param>
|
||||||
/// <param name="position"></param>
|
// /// <param name="position"></param>
|
||||||
/// <param name="isFlying"></param>
|
// /// <param name="isFlying"></param>
|
||||||
public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
|
// public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
|
||||||
{
|
// {
|
||||||
ScenePresence presence = GetScenePresence(agentID);
|
// ScenePresence presence = GetScenePresence(agentID);
|
||||||
if (presence != null)
|
// if (presence != null)
|
||||||
{
|
// {
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
presence.MakeRootAgent(position, isFlying);
|
// presence.MakeRootAgent(position, isFlying);
|
||||||
}
|
// }
|
||||||
catch (Exception e)
|
// catch (Exception e)
|
||||||
{
|
// {
|
||||||
m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace);
|
// m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
m_log.ErrorFormat(
|
// m_log.ErrorFormat(
|
||||||
"[SCENE]: Could not find presence for agent {0} crossing into scene {1}",
|
// "[SCENE]: Could not find presence for agent {0} crossing into scene {1}",
|
||||||
agentID, RegionInfo.RegionName);
|
// agentID, RegionInfo.RegionName);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// We've got an update about an agent that sees into this region,
|
/// We've got an update about an agent that sees into this region,
|
||||||
|
|
|
@ -3743,6 +3743,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="events"></param>
|
/// <param name="events"></param>
|
||||||
public void SetScriptEvents(UUID scriptid, int events)
|
public void SetScriptEvents(UUID scriptid, int events)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[SCENE OBJECT PART]: Set script events for script with id {0} on {1}/{2} to {3} in {4}",
|
||||||
|
// scriptid, Name, ParentGroup.Name, events, ParentGroup.Scene.Name);
|
||||||
|
|
||||||
// scriptEvents oldparts;
|
// scriptEvents oldparts;
|
||||||
lock (m_scriptEvents)
|
lock (m_scriptEvents)
|
||||||
{
|
{
|
||||||
|
|
|
@ -456,9 +456,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
m_pos = PhysicsActor.Position;
|
m_pos = PhysicsActor.Position;
|
||||||
|
|
||||||
//m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENE PRESENCE]: Set position {0} for {1} in {2} via getting AbsolutePosition!",
|
// "[SCENE PRESENCE]: Set position of {0} in {1} to {2} via getting AbsolutePosition!",
|
||||||
// m_pos, Name, Scene.RegionInfo.RegionName);
|
// Name, Scene.Name, m_pos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -485,6 +485,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value);
|
||||||
|
// Util.PrintCallStack();
|
||||||
|
|
||||||
if (PhysicsActor != null)
|
if (PhysicsActor != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -938,8 +941,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
"[SCENE]: Upgrading child to root agent for {0} in {1}",
|
"[SCENE]: Upgrading child to root agent for {0} in {1}",
|
||||||
Name, m_scene.RegionInfo.RegionName);
|
Name, m_scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
bool wasChild = IsChildAgent;
|
|
||||||
|
|
||||||
if (ParentUUID != UUID.Zero)
|
if (ParentUUID != UUID.Zero)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
|
m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
|
||||||
|
@ -972,6 +973,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
IsLoggingIn = false;
|
IsLoggingIn = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
|
||||||
|
|
||||||
|
IsChildAgent = false;
|
||||||
|
|
||||||
IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
|
IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
|
||||||
if (gm != null)
|
if (gm != null)
|
||||||
|
@ -1065,6 +1069,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
else
|
else
|
||||||
AddToPhysicalScene(isFlying);
|
AddToPhysicalScene(isFlying);
|
||||||
|
|
||||||
|
// XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
|
||||||
|
// location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
|
||||||
|
// since it requires a physics actor to be present. If it is left any later, then physics appears to reset
|
||||||
|
// the value to a negative position which does not trigger the border cross.
|
||||||
|
// This may not be the best location for this.
|
||||||
|
CheckForBorderCrossing();
|
||||||
|
|
||||||
if (ForceFly)
|
if (ForceFly)
|
||||||
{
|
{
|
||||||
Flying = true;
|
Flying = true;
|
||||||
|
@ -1085,22 +1096,43 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// and it has already rezzed the attachments and started their scripts.
|
// and it has already rezzed the attachments and started their scripts.
|
||||||
// We do the following only for non-login agents, because their scripts
|
// We do the following only for non-login agents, because their scripts
|
||||||
// haven't started yet.
|
// haven't started yet.
|
||||||
lock (m_attachments)
|
if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
|
||||||
{
|
{
|
||||||
if (wasChild && HasAttachments())
|
// Viewers which have a current outfit folder will actually rez their own attachments. However,
|
||||||
{
|
// viewers without (e.g. v1 viewers) will not, so we still need to make this call.
|
||||||
m_log.DebugFormat(
|
if (Scene.AttachmentsModule != null)
|
||||||
"[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
|
Util.FireAndForget(
|
||||||
|
o =>
|
||||||
// Resume scripts
|
|
||||||
Util.FireAndForget(delegate(object x) {
|
|
||||||
foreach (SceneObjectGroup sog in m_attachments)
|
|
||||||
{
|
{
|
||||||
sog.ScheduleGroupForFullUpdate();
|
// if (PresenceType != PresenceType.Npc && Util.FireAndForgetMethod != FireAndForgetMethod.None)
|
||||||
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
|
// System.Threading.Thread.Sleep(7000);
|
||||||
sog.ResumeScripts();
|
|
||||||
}
|
Scene.AttachmentsModule.RezAttachments(this);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
|
||||||
|
// and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
|
||||||
|
// be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
|
||||||
|
// not transporting the required data.
|
||||||
|
lock (m_attachments)
|
||||||
|
{
|
||||||
|
if (HasAttachments())
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
|
||||||
|
|
||||||
|
// Resume scripts
|
||||||
|
Util.FireAndForget(delegate(object x) {
|
||||||
|
foreach (SceneObjectGroup sog in m_attachments)
|
||||||
|
{
|
||||||
|
sog.ScheduleGroupForFullUpdate();
|
||||||
|
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
|
||||||
|
sog.ResumeScripts();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3121,6 +3153,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (!IsInTransit)
|
if (!IsInTransit)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
|
||||||
|
// pos2, Name, Scene.Name);
|
||||||
|
|
||||||
// Checks if where it's headed exists a region
|
// Checks if where it's headed exists a region
|
||||||
bool needsTransit = false;
|
bool needsTransit = false;
|
||||||
if (m_scene.TestBorderCross(pos2, Cardinals.W))
|
if (m_scene.TestBorderCross(pos2, Cardinals.W))
|
||||||
|
|
|
@ -184,7 +184,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
||||||
hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
|
hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true, true) ? 1 : 0;
|
return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, false, true, true) ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
||||||
+ "If teleport is true then some extra teleport debug information is logged.\n"
|
+ "If teleport is true then some extra teleport debug information is logged.\n"
|
||||||
+ "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
|
+ "If updates is true then any frame which exceeds double the maximum desired frame time is logged.",
|
||||||
HandleDebugSceneSetCommand);
|
HandleDebugSceneSetCommand);
|
||||||
|
|
||||||
|
scene.AddCommand(
|
||||||
|
"Regions",
|
||||||
|
this, "show borders", "show borders", "Show border information for regions", HandleShowBordersCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleShowBordersCommand(string module, string[] args)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.AppendFormat("Borders for {0}:\n", m_scene.Name);
|
||||||
|
|
||||||
|
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||||
|
cdt.AddColumn("Cross Direction", 15);
|
||||||
|
cdt.AddColumn("Line", 34);
|
||||||
|
cdt.AddColumn("Trigger Region", 14);
|
||||||
|
|
||||||
|
foreach (Border b in m_scene.NorthBorders)
|
||||||
|
cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
|
||||||
|
|
||||||
|
foreach (Border b in m_scene.EastBorders)
|
||||||
|
cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
|
||||||
|
|
||||||
|
foreach (Border b in m_scene.SouthBorders)
|
||||||
|
cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
|
||||||
|
|
||||||
|
foreach (Border b in m_scene.WestBorders)
|
||||||
|
cdt.AddRow(b.CrossDirection, b.BorderLine, string.Format("{0}, {1}", b.TriggerRegionX, b.TriggerRegionY));
|
||||||
|
|
||||||
|
cdt.AddToStringBuilder(sb);
|
||||||
|
|
||||||
|
MainConsole.Instance.Output(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleDebugSceneGetCommand(string module, string[] args)
|
private void HandleDebugSceneGetCommand(string module, string[] args)
|
||||||
|
|
|
@ -321,7 +321,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ProcessTypeChange(Vehicle pType)
|
public void ProcessTypeChange(Vehicle pType)
|
||||||
{
|
{
|
||||||
VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType);
|
VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType);
|
||||||
// Set Defaults For Type
|
// Set Defaults For Type
|
||||||
|
@ -1301,14 +1301,52 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
|
// efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
|
||||||
public void ComputeAngularVerticalAttraction()
|
public void ComputeAngularVerticalAttraction()
|
||||||
{
|
{
|
||||||
|
|
||||||
// If vertical attaction timescale is reasonable
|
// If vertical attaction timescale is reasonable
|
||||||
if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
|
if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
|
||||||
{
|
{
|
||||||
|
// Possible solution derived from a discussion at:
|
||||||
|
// http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
|
||||||
|
|
||||||
|
// Create a rotation that is only the vehicle's rotation around Z
|
||||||
|
Vector3 currentEuler = Vector3.Zero;
|
||||||
|
VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
|
||||||
|
Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
|
||||||
|
|
||||||
|
// Create the axis that is perpendicular to the up vector and the rotated up vector.
|
||||||
|
Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
|
||||||
|
// Compute the angle between those to vectors.
|
||||||
|
double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
|
||||||
|
// 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
|
||||||
|
|
||||||
|
// Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
|
||||||
|
// TODO: add 'efficiency'.
|
||||||
|
differenceAngle /= m_verticalAttractionTimescale;
|
||||||
|
|
||||||
|
// Create the quaterian representing the correction angle
|
||||||
|
Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
|
||||||
|
|
||||||
|
// Turn that quaternion into Euler values to make it into velocities to apply.
|
||||||
|
Vector3 vertContributionV = Vector3.Zero;
|
||||||
|
correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
|
||||||
|
vertContributionV *= -1f;
|
||||||
|
|
||||||
|
VehicleRotationalVelocity += vertContributionV;
|
||||||
|
|
||||||
|
VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}",
|
||||||
|
Prim.LocalID,
|
||||||
|
differenceAxis,
|
||||||
|
differenceAngle,
|
||||||
|
correctionRotation,
|
||||||
|
vertContributionV);
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
/*
|
||||||
Vector3 vertContributionV = Vector3.Zero;
|
Vector3 vertContributionV = Vector3.Zero;
|
||||||
Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
|
Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
|
||||||
|
|
||||||
// Take a vector pointing up and convert it from world to vehicle relative coords.
|
// Take a vector pointing up and convert it from world to vehicle relative coords.
|
||||||
Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
|
Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
|
||||||
|
|
||||||
// If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
|
// If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
|
||||||
// is now:
|
// is now:
|
||||||
|
@ -1334,13 +1372,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
|
// 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
|
||||||
// Correction happens over a number of seconds.
|
// Correction happens over a number of seconds.
|
||||||
Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
|
Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
|
||||||
|
|
||||||
|
// The correction happens over the user's time period
|
||||||
vertContributionV /= m_verticalAttractionTimescale;
|
vertContributionV /= m_verticalAttractionTimescale;
|
||||||
|
|
||||||
VehicleRotationalVelocity += vertContributionV;
|
// Rotate the vehicle rotation to the world coordinates.
|
||||||
|
VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
|
||||||
|
|
||||||
VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
|
VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
|
||||||
Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
|
Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
|
||||||
m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
|
m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,11 +180,14 @@ public static class BSMaterials
|
||||||
// Use reflection to set the value in the attribute structure.
|
// Use reflection to set the value in the attribute structure.
|
||||||
private static void SetAttributeValue(int matType, string attribName, float val)
|
private static void SetAttributeValue(int matType, string attribName, float val)
|
||||||
{
|
{
|
||||||
|
// Get the current attribute values for this material
|
||||||
MaterialAttributes thisAttrib = Attributes[matType];
|
MaterialAttributes thisAttrib = Attributes[matType];
|
||||||
|
// Find the field for the passed attribute name (eg, find field named 'friction')
|
||||||
FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
|
FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
|
||||||
if (fieldInfo != null)
|
if (fieldInfo != null)
|
||||||
{
|
{
|
||||||
fieldInfo.SetValue(thisAttrib, val);
|
fieldInfo.SetValue(thisAttrib, val);
|
||||||
|
// Copy new attributes back to array -- since MaterialAttributes is 'struct', passed by value, not reference.
|
||||||
Attributes[matType] = thisAttrib;
|
Attributes[matType] = thisAttrib;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,14 @@ public static class BSParam
|
||||||
public static float VehicleAngularBankingTimescaleFudge { get; private set; }
|
public static float VehicleAngularBankingTimescaleFudge { get; private set; }
|
||||||
public static bool VehicleDebuggingEnabled { get; private set; }
|
public static bool VehicleDebuggingEnabled { get; private set; }
|
||||||
|
|
||||||
|
// Convex Hulls
|
||||||
|
public static int CSHullMaxDepthSplit { get; private set; }
|
||||||
|
public static int CSHullMaxDepthSplitForSimpleShapes { get; private set; }
|
||||||
|
public static float CSHullConcavityThresholdPercent { get; private set; }
|
||||||
|
public static float CSHullVolumeConservationThresholdPercent { get; private set; }
|
||||||
|
public static int CSHullMaxVertices { get; private set; }
|
||||||
|
public static float CSHullMaxSkinWidth { get; private set; }
|
||||||
|
|
||||||
// Linkset implementation parameters
|
// Linkset implementation parameters
|
||||||
public static float LinksetImplementation { get; private set; }
|
public static float LinksetImplementation { get; private set; }
|
||||||
public static bool LinkConstraintUseFrameOffset { get; private set; }
|
public static bool LinkConstraintUseFrameOffset { get; private set; }
|
||||||
|
@ -195,10 +203,10 @@ public static class BSParam
|
||||||
public delegate void PSetOnObject<T>(BSScene scene, BSPhysObject obj);
|
public delegate void PSetOnObject<T>(BSScene scene, BSPhysObject obj);
|
||||||
public sealed class ParameterDefn<T> : ParameterDefnBase
|
public sealed class ParameterDefn<T> : ParameterDefnBase
|
||||||
{
|
{
|
||||||
T defaultValue;
|
private T defaultValue;
|
||||||
PSetValue<T> setter;
|
private PSetValue<T> setter;
|
||||||
PGetValue<T> getter;
|
private PGetValue<T> getter;
|
||||||
PSetOnObject<T> objectSet;
|
private PSetOnObject<T> objectSet;
|
||||||
public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
|
public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
|
||||||
: base(pName, pDesc)
|
: base(pName, pDesc)
|
||||||
{
|
{
|
||||||
|
@ -215,13 +223,23 @@ public static class BSParam
|
||||||
getter = pGetter;
|
getter = pGetter;
|
||||||
objectSet = pObjSetter;
|
objectSet = pObjSetter;
|
||||||
}
|
}
|
||||||
|
/* Wish I could simplify using this definition but CLR doesn't store references so closure around delegates of references won't work
|
||||||
|
public ParameterDefn(string pName, string pDesc, T pDefault, ref T loc)
|
||||||
|
: base(pName, pDesc)
|
||||||
|
{
|
||||||
|
defaultValue = pDefault;
|
||||||
|
setter = (s, v) => { loc = v; };
|
||||||
|
getter = (s) => { return loc; };
|
||||||
|
objectSet = null;
|
||||||
|
}
|
||||||
|
*/
|
||||||
public override void AssignDefault(BSScene s)
|
public override void AssignDefault(BSScene s)
|
||||||
{
|
{
|
||||||
setter(s, defaultValue);
|
setter(s, defaultValue);
|
||||||
}
|
}
|
||||||
public override string GetValue(BSScene s)
|
public override string GetValue(BSScene s)
|
||||||
{
|
{
|
||||||
return String.Format("{0}", getter(s));
|
return getter(s).ToString();
|
||||||
}
|
}
|
||||||
public override void SetValue(BSScene s, string valAsString)
|
public override void SetValue(BSScene s, string valAsString)
|
||||||
{
|
{
|
||||||
|
@ -244,6 +262,7 @@ public static class BSParam
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString });
|
T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString });
|
||||||
|
// Store the parsed value
|
||||||
setter(s, setValue);
|
setter(s, setValue);
|
||||||
// s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue);
|
// s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue);
|
||||||
}
|
}
|
||||||
|
@ -463,7 +482,7 @@ public static class BSParam
|
||||||
(s) => { return TerrainImplementation; },
|
(s) => { return TerrainImplementation; },
|
||||||
(s,v) => { TerrainImplementation = v; } ),
|
(s,v) => { TerrainImplementation = v; } ),
|
||||||
new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
|
new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
|
||||||
3,
|
2,
|
||||||
(s) => { return TerrainMeshMagnification; },
|
(s) => { return TerrainMeshMagnification; },
|
||||||
(s,v) => { TerrainMeshMagnification = v; } ),
|
(s,v) => { TerrainMeshMagnification = v; } ),
|
||||||
new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||||
|
@ -623,6 +642,31 @@ public static class BSParam
|
||||||
(s) => { return GlobalContactBreakingThreshold; },
|
(s) => { return GlobalContactBreakingThreshold; },
|
||||||
(s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
|
(s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
|
||||||
|
|
||||||
|
new ParameterDefn<int>("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy",
|
||||||
|
7,
|
||||||
|
(s) => { return CSHullMaxDepthSplit; },
|
||||||
|
(s,v) => { CSHullMaxDepthSplit = v; } ),
|
||||||
|
new ParameterDefn<int>("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes",
|
||||||
|
2,
|
||||||
|
(s) => { return CSHullMaxDepthSplitForSimpleShapes; },
|
||||||
|
(s,v) => { CSHullMaxDepthSplitForSimpleShapes = v; } ),
|
||||||
|
new ParameterDefn<float>("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)",
|
||||||
|
5f,
|
||||||
|
(s) => { return CSHullConcavityThresholdPercent; },
|
||||||
|
(s,v) => { CSHullConcavityThresholdPercent = v; } ),
|
||||||
|
new ParameterDefn<float>("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)",
|
||||||
|
5f,
|
||||||
|
(s) => { return CSHullVolumeConservationThresholdPercent; },
|
||||||
|
(s,v) => { CSHullVolumeConservationThresholdPercent = v; } ),
|
||||||
|
new ParameterDefn<int>("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.",
|
||||||
|
32,
|
||||||
|
(s) => { return CSHullMaxVertices; },
|
||||||
|
(s,v) => { CSHullMaxVertices = v; } ),
|
||||||
|
new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
|
||||||
|
0,
|
||||||
|
(s) => { return CSHullMaxSkinWidth; },
|
||||||
|
(s,v) => { CSHullMaxSkinWidth = v; } ),
|
||||||
|
|
||||||
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
||||||
(float)BSLinkset.LinksetImplementation.Compound,
|
(float)BSLinkset.LinksetImplementation.Compound,
|
||||||
(s) => { return LinksetImplementation; },
|
(s) => { return LinksetImplementation; },
|
||||||
|
|
|
@ -86,7 +86,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
PhysBody = new BulletBody(localID);
|
PhysBody = new BulletBody(localID);
|
||||||
PhysShape = new BulletShape();
|
PhysShape = new BulletShape();
|
||||||
|
|
||||||
LastAssetBuildFailed = false;
|
PrimAssetState = PrimAssetCondition.Unknown;
|
||||||
|
|
||||||
// Default material type. Also sets Friction, Restitution and Density.
|
// Default material type. Also sets Friction, Restitution and Density.
|
||||||
SetMaterial((int)MaterialAttributes.Material.Wood);
|
SetMaterial((int)MaterialAttributes.Material.Wood);
|
||||||
|
@ -133,9 +133,13 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// Reference to the physical shape (btCollisionShape) of this object
|
// Reference to the physical shape (btCollisionShape) of this object
|
||||||
public BulletShape PhysShape;
|
public BulletShape PhysShape;
|
||||||
|
|
||||||
// 'true' if the mesh's underlying asset failed to build.
|
// The physical representation of the prim might require an asset fetch.
|
||||||
// This will keep us from looping after the first time the build failed.
|
// The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
|
||||||
public bool LastAssetBuildFailed { get; set; }
|
public enum PrimAssetCondition
|
||||||
|
{
|
||||||
|
Unknown, Waiting, Failed, Fetched
|
||||||
|
}
|
||||||
|
public PrimAssetCondition PrimAssetState { get; set; }
|
||||||
|
|
||||||
// The objects base shape information. Null if not a prim type shape.
|
// The objects base shape information. Null if not a prim type shape.
|
||||||
public PrimitiveBaseShape BaseShape { get; protected set; }
|
public PrimitiveBaseShape BaseShape { get; protected set; }
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class BSPrim : BSPhysObject
|
||||||
public override PrimitiveBaseShape Shape {
|
public override PrimitiveBaseShape Shape {
|
||||||
set {
|
set {
|
||||||
BaseShape = value;
|
BaseShape = value;
|
||||||
LastAssetBuildFailed = false;
|
PrimAssetState = PrimAssetCondition.Unknown;
|
||||||
ForceBodyShapeRebuild(false);
|
ForceBodyShapeRebuild(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,17 +447,10 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
// If the prim attributes are simple, this could be a simple Bullet native shape
|
// If the prim attributes are simple, this could be a simple Bullet native shape
|
||||||
if (!haveShape
|
if (!haveShape
|
||||||
|
&& nativeShapePossible
|
||||||
&& pbs != null
|
&& pbs != null
|
||||||
&& !pbs.SculptEntry
|
&& !pbs.SculptEntry
|
||||||
&& nativeShapePossible
|
&& ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) )
|
||||||
&& ((pbs.SculptEntry && !BSParam.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) ) )
|
|
||||||
{
|
{
|
||||||
// Get the scale of any existing shape so we can see if the new shape is same native type and same size.
|
// Get the scale of any existing shape so we can see if the new shape is same native type and same size.
|
||||||
OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
|
OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
|
||||||
|
@ -508,6 +501,18 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return 'true' if this shape description does not include any cutting or twisting.
|
||||||
|
private bool PrimHasNoCuts(PrimitiveBaseShape pbs)
|
||||||
|
{
|
||||||
|
return 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 'true' if the prim's shape was changed.
|
// return 'true' if the prim's shape was changed.
|
||||||
public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
||||||
{
|
{
|
||||||
|
@ -518,7 +523,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
|
if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
|
||||||
{
|
{
|
||||||
// Update prim.BSShape to reference a hull of this shape.
|
// Update prim.BSShape to reference a hull of this shape.
|
||||||
ret = GetReferenceToHull(prim,shapeCallback);
|
ret = GetReferenceToHull(prim, shapeCallback);
|
||||||
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
|
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
|
||||||
prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
|
prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
|
||||||
}
|
}
|
||||||
|
@ -699,6 +704,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
|
|
||||||
// See that hull shape exists in the physical world and update prim.BSShape.
|
// See that hull shape exists in the physical world and update prim.BSShape.
|
||||||
// We could be creating the hull because scale changed or whatever.
|
// We could be creating the hull because scale changed or whatever.
|
||||||
|
// Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
|
||||||
private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
||||||
{
|
{
|
||||||
BulletShape newShape;
|
BulletShape newShape;
|
||||||
|
@ -717,6 +723,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
DereferenceShape(prim.PhysShape, shapeCallback);
|
DereferenceShape(prim.PhysShape, shapeCallback);
|
||||||
|
|
||||||
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
|
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
|
||||||
|
// It might not have been created if we're waiting for an asset.
|
||||||
newShape = VerifyMeshCreated(newShape, prim);
|
newShape = VerifyMeshCreated(newShape, prim);
|
||||||
|
|
||||||
ReferenceShape(newShape);
|
ReferenceShape(newShape);
|
||||||
|
@ -735,13 +742,13 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
HullDesc hullDesc;
|
HullDesc hullDesc;
|
||||||
if (Hulls.TryGetValue(newHullKey, out hullDesc))
|
if (Hulls.TryGetValue(newHullKey, out hullDesc))
|
||||||
{
|
{
|
||||||
// If the hull shape already is created, just use it.
|
// If the hull shape already has been created, just use the one shared instance.
|
||||||
newShape = hullDesc.shape.Clone();
|
newShape = hullDesc.shape.Clone();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Build a new hull in the physical world
|
// Build a new hull in the physical world.
|
||||||
// Pass true for physicalness as this creates some sort of bounding box which we don't need
|
// Pass true for physicalness as this prevents the creation of bounding box which is not needed
|
||||||
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
|
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
|
||||||
if (meshData != null)
|
if (meshData != null)
|
||||||
{
|
{
|
||||||
|
@ -761,15 +768,35 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
|
convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
|
||||||
|
if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
|
||||||
|
{
|
||||||
|
// Simple primitive shapes we know are convex so they are better implemented with
|
||||||
|
// fewer hulls.
|
||||||
|
// Check for simple shape (prim without cuts) and reduce split parameter if so.
|
||||||
|
if (PrimHasNoCuts(pbs))
|
||||||
|
{
|
||||||
|
maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// setup and do convex hull conversion
|
// setup and do convex hull conversion
|
||||||
m_hulls = new List<ConvexResult>();
|
m_hulls = new List<ConvexResult>();
|
||||||
DecompDesc dcomp = new DecompDesc();
|
DecompDesc dcomp = new DecompDesc();
|
||||||
dcomp.mIndices = convIndices;
|
dcomp.mIndices = convIndices;
|
||||||
dcomp.mVertices = convVertices;
|
dcomp.mVertices = convVertices;
|
||||||
|
dcomp.mDepth = maxDepthSplit;
|
||||||
|
dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
|
||||||
|
dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
|
||||||
|
dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
|
||||||
|
dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
|
||||||
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
|
ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
|
||||||
// create the hull into the _hulls variable
|
// create the hull into the _hulls variable
|
||||||
convexBuilder.process(dcomp);
|
convexBuilder.process(dcomp);
|
||||||
|
|
||||||
|
DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
|
||||||
|
BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
|
||||||
|
|
||||||
// Convert the vertices and indices for passing to unmanaged.
|
// Convert the vertices and indices for passing to unmanaged.
|
||||||
// The hull information is passed as a large floating point array.
|
// The hull information is passed as a large floating point array.
|
||||||
// The format is:
|
// The format is:
|
||||||
|
@ -904,58 +931,79 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
if (newShape.HasPhysicalShape)
|
if (newShape.HasPhysicalShape)
|
||||||
return newShape;
|
return newShape;
|
||||||
|
|
||||||
// If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
|
// VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
|
||||||
if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero)
|
// fetched but we end up here again, the meshing of the asset must have failed.
|
||||||
|
// Prevent trying to keep fetching the mesh by declaring failure.
|
||||||
|
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lastFailed={1}", prim.LocalID, prim.LastAssetBuildFailed);
|
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
|
||||||
// This will prevent looping through this code as we keep trying to get the failed shape
|
PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
|
||||||
prim.LastAssetBuildFailed = true;
|
LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
|
||||||
|
|
||||||
BSPhysObject xprim = prim;
|
|
||||||
Util.FireAndForget(delegate
|
|
||||||
{
|
|
||||||
RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
|
|
||||||
if (assetProvider != null)
|
|
||||||
{
|
|
||||||
BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
|
|
||||||
assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
|
|
||||||
{
|
|
||||||
bool assetFound = false; // DEBUG DEBUG
|
|
||||||
string mismatchIDs = String.Empty; // DEBUG DEBUG
|
|
||||||
if (asset != null && yprim.BaseShape.SculptEntry)
|
|
||||||
{
|
|
||||||
if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
|
|
||||||
{
|
|
||||||
yprim.BaseShape.SculptData = asset.Data;
|
|
||||||
// This will cause the prim to see that the filler shape is not the right
|
|
||||||
// one and try again to build the object.
|
|
||||||
// No race condition with the normal shape setting since the rebuild is at taint time.
|
|
||||||
yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
|
|
||||||
assetFound = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
|
|
||||||
yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
|
|
||||||
LogHeader, PhysicsScene.Name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (prim.LastAssetBuildFailed)
|
// If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
|
||||||
|
if (prim.BaseShape.SculptEntry
|
||||||
|
&& prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed
|
||||||
|
&& prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
|
||||||
|
&& prim.BaseShape.SculptTexture != OMV.UUID.Zero
|
||||||
|
)
|
||||||
{
|
{
|
||||||
PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}",
|
DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
|
||||||
LogHeader, prim.LocalID, prim.BaseShape.SculptTexture);
|
// Multiple requestors will know we're waiting for this asset
|
||||||
|
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
|
||||||
|
|
||||||
|
BSPhysObject xprim = prim;
|
||||||
|
Util.FireAndForget(delegate
|
||||||
|
{
|
||||||
|
RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
|
||||||
|
if (assetProvider != null)
|
||||||
|
{
|
||||||
|
BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
|
||||||
|
assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
|
||||||
|
{
|
||||||
|
bool assetFound = false;
|
||||||
|
string mismatchIDs = String.Empty; // DEBUG DEBUG
|
||||||
|
if (asset != null && yprim.BaseShape.SculptEntry)
|
||||||
|
{
|
||||||
|
if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
|
||||||
|
{
|
||||||
|
yprim.BaseShape.SculptData = asset.Data;
|
||||||
|
// This will cause the prim to see that the filler shape is not the right
|
||||||
|
// one and try again to build the object.
|
||||||
|
// No race condition with the normal shape setting since the rebuild is at taint time.
|
||||||
|
yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
|
||||||
|
assetFound = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (assetFound)
|
||||||
|
yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
|
||||||
|
else
|
||||||
|
yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
|
||||||
|
DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
|
||||||
|
yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
|
||||||
|
PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
|
||||||
|
LogHeader, PhysicsScene.Name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
|
||||||
|
{
|
||||||
|
PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
|
||||||
|
LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,7 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
// safe to call Bullet in real time. We hope no one is moving prims around yet.
|
// safe to call Bullet in real time. We hope no one is moving prims around yet.
|
||||||
public void CreateInitialGroundPlaneAndTerrain()
|
public void CreateInitialGroundPlaneAndTerrain()
|
||||||
{
|
{
|
||||||
|
DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName);
|
||||||
// The ground plane is here to catch things that are trying to drop to negative infinity
|
// The ground plane is here to catch things that are trying to drop to negative infinity
|
||||||
BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
|
BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
|
||||||
m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
|
m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
|
||||||
|
@ -145,14 +146,18 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
m_groundPlane.collisionType = CollisionType.Groundplane;
|
m_groundPlane.collisionType = CollisionType.Groundplane;
|
||||||
m_groundPlane.ApplyCollisionMask(PhysicsScene);
|
m_groundPlane.ApplyCollisionMask(PhysicsScene);
|
||||||
|
|
||||||
// Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
|
|
||||||
BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
|
BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
|
||||||
m_terrains.Add(Vector3.Zero, initialTerrain);
|
lock (m_terrains)
|
||||||
|
{
|
||||||
|
// Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
|
||||||
|
m_terrains.Add(Vector3.Zero, initialTerrain);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release all the terrain structures we might have allocated
|
// Release all the terrain structures we might have allocated
|
||||||
public void ReleaseGroundPlaneAndTerrain()
|
public void ReleaseGroundPlaneAndTerrain()
|
||||||
{
|
{
|
||||||
|
DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName);
|
||||||
if (m_groundPlane.HasPhysicalBody)
|
if (m_groundPlane.HasPhysicalBody)
|
||||||
{
|
{
|
||||||
if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane))
|
if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane))
|
||||||
|
@ -193,11 +198,16 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
// the terrain is added to our parent
|
// the terrain is added to our parent
|
||||||
if (MegaRegionParentPhysicsScene is BSScene)
|
if (MegaRegionParentPhysicsScene is BSScene)
|
||||||
{
|
{
|
||||||
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
|
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||||
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
// This looks really odd but this region is passing its terrain to its mega-region root region
|
||||||
((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
|
// and the creation of the terrain must happen on the root region's taint thread and not
|
||||||
BSScene.CHILDTERRAIN_ID, localHeightMap,
|
// my taint thread.
|
||||||
m_worldOffset, m_worldOffset + DefaultRegionSize, true);
|
((BSScene)MegaRegionParentPhysicsScene).PostTaintObject("TerrainManager.SetTerrain.Mega-" + m_worldOffset.ToString(), 0, delegate()
|
||||||
|
{
|
||||||
|
((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
|
||||||
|
BSScene.CHILDTERRAIN_ID, localHeightMap,
|
||||||
|
m_worldOffset, m_worldOffset + DefaultRegionSize, true /* inTaintTime */);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -206,16 +216,16 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
||||||
|
|
||||||
UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap,
|
UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap,
|
||||||
m_worldOffset, m_worldOffset + DefaultRegionSize, true);
|
m_worldOffset, m_worldOffset + DefaultRegionSize, true /* inTaintTime */);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
|
// If called for terrain has has not been previously allocated, a new terrain will be built
|
||||||
// based on the passed information. The 'id' should be either the terrain id or
|
// based on the passed information. The 'id' should be either the terrain id or
|
||||||
// BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
|
// BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
|
||||||
// The latter feature is for creating child terrains for mega-regions.
|
// The latter feature is for creating child terrains for mega-regions.
|
||||||
// If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
|
// If there is an existing terrain body, a new
|
||||||
// terrain shape is created and added to the body.
|
// terrain shape is created and added to the body.
|
||||||
// This call is most often used to update the heightMap and parameters of the terrain.
|
// This call is most often used to update the heightMap and parameters of the terrain.
|
||||||
// (The above does suggest that some simplification/refactoring is in order.)
|
// (The above does suggest that some simplification/refactoring is in order.)
|
||||||
|
@ -223,8 +233,8 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
private void UpdateTerrain(uint id, float[] heightMap,
|
private void UpdateTerrain(uint id, float[] heightMap,
|
||||||
Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
|
Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
|
DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1},minC={2},maxC={3},inTaintTime={4}",
|
||||||
BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
|
BSScene.DetailLogZero, id, minCoords, maxCoords, inTaintTime);
|
||||||
|
|
||||||
// Find high and low points of passed heightmap.
|
// Find high and low points of passed heightmap.
|
||||||
// The min and max passed in is usually the area objects can be in (maximum
|
// The min and max passed in is usually the area objects can be in (maximum
|
||||||
|
@ -253,7 +263,7 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
|
if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
|
||||||
{
|
{
|
||||||
// There is already a terrain in this spot. Free the old and build the new.
|
// There is already a terrain in this spot. Free the old and build the new.
|
||||||
DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
|
DetailLog("{0},BSTErrainManager.UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
|
||||||
BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
|
BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
|
||||||
|
|
||||||
// Remove old terrain from the collection
|
// Remove old terrain from the collection
|
||||||
|
@ -292,7 +302,7 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
|
if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
|
||||||
newTerrainID = ++m_terrainCount;
|
newTerrainID = ++m_terrainCount;
|
||||||
|
|
||||||
DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
|
DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
|
||||||
BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
|
BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
|
||||||
BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
|
BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
|
||||||
m_terrains.Add(terrainRegionBase, newTerrainPhys);
|
m_terrains.Add(terrainRegionBase, newTerrainPhys);
|
||||||
|
@ -343,37 +353,35 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
{
|
{
|
||||||
Vector3 ret = pPos;
|
Vector3 ret = pPos;
|
||||||
|
|
||||||
|
// First, base addresses are never negative so correct for that possible problem.
|
||||||
|
if (ret.X < 0f || ret.Y < 0f)
|
||||||
|
{
|
||||||
|
ret.X = Util.Clamp<float>(ret.X, 0f, 1000000f);
|
||||||
|
ret.Y = Util.Clamp<float>(ret.Y, 0f, 1000000f);
|
||||||
|
DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,zeroingNegXorY,oldPos={1},newPos={2}",
|
||||||
|
BSScene.DetailLogZero, pPos, ret);
|
||||||
|
}
|
||||||
|
|
||||||
// Can't do this function if we don't know about any terrain.
|
// Can't do this function if we don't know about any terrain.
|
||||||
if (m_terrains.Count == 0)
|
if (m_terrains.Count == 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
int loopPrevention = 5;
|
int loopPrevention = 10;
|
||||||
Vector3 terrainBaseXYZ;
|
Vector3 terrainBaseXYZ;
|
||||||
BSTerrainPhys physTerrain;
|
BSTerrainPhys physTerrain;
|
||||||
while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ))
|
while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ))
|
||||||
{
|
{
|
||||||
// The passed position is not within a known terrain area.
|
// The passed position is not within a known terrain area.
|
||||||
|
// NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region.
|
||||||
|
|
||||||
// First, base addresses are never negative so correct for that possible problem.
|
// Must be off the top of a region. Find an adjacent region to move into.
|
||||||
if (ret.X < 0f || ret.Y < 0f)
|
Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
|
||||||
{
|
|
||||||
if (ret.X < 0f)
|
ret.X = Math.Min(ret.X, adjacentTerrainBase.X + (ret.X % DefaultRegionSize.X));
|
||||||
ret.X = 0f;
|
ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + (ret.X % DefaultRegionSize.Y));
|
||||||
if (ret.Y < 0f)
|
DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
|
||||||
ret.Y = 0f;
|
BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
|
||||||
DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,zeroingNegXorY,oldPos={1},newPos={2}",
|
|
||||||
BSScene.DetailLogZero, pPos, ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Must be off the top of a region. Find an adjacent region to move into.
|
|
||||||
Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
|
|
||||||
|
|
||||||
ret.X = Math.Min(ret.X, adjacentTerrainBase.X + DefaultRegionSize.X);
|
|
||||||
ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + DefaultRegionSize.Y);
|
|
||||||
DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
|
|
||||||
BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
|
|
||||||
}
|
|
||||||
if (loopPrevention-- < 0f)
|
if (loopPrevention-- < 0f)
|
||||||
{
|
{
|
||||||
// The 'while' is a little dangerous so this prevents looping forever if the
|
// The 'while' is a little dangerous so this prevents looping forever if the
|
||||||
|
@ -383,6 +391,7 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,11 +488,20 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
private Vector3 FindAdjacentTerrainBase(Vector3 pTerrainBase)
|
private Vector3 FindAdjacentTerrainBase(Vector3 pTerrainBase)
|
||||||
{
|
{
|
||||||
Vector3 ret = pTerrainBase;
|
Vector3 ret = pTerrainBase;
|
||||||
|
|
||||||
|
// Can't do this function if we don't know about any terrain.
|
||||||
|
if (m_terrains.Count == 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// Just some sanity
|
||||||
|
ret.X = Util.Clamp<float>(ret.X, 0f, 1000000f);
|
||||||
|
ret.Y = Util.Clamp<float>(ret.Y, 0f, 1000000f);
|
||||||
ret.Z = 0f;
|
ret.Z = 0f;
|
||||||
|
|
||||||
lock (m_terrains)
|
lock (m_terrains)
|
||||||
{
|
{
|
||||||
// Once down to the <0,0> region, we have to be done.
|
// Once down to the <0,0> region, we have to be done.
|
||||||
while (ret.X > 0f && ret.Y > 0f)
|
while (ret.X > 0f || ret.Y > 0f)
|
||||||
{
|
{
|
||||||
if (ret.X > 0f)
|
if (ret.X > 0f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,20 +98,20 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
if (!meshCreationSuccess)
|
if (!meshCreationSuccess)
|
||||||
{
|
{
|
||||||
// DISASTER!!
|
// DISASTER!!
|
||||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID);
|
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID);
|
||||||
PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
|
PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
|
||||||
// Something is very messed up and a crash is in our future.
|
// Something is very messed up and a crash is in our future.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
|
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
|
||||||
ID, indicesCount, indices.Length, verticesCount, vertices.Length);
|
BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);
|
||||||
|
|
||||||
m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices);
|
m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices);
|
||||||
if (!m_terrainShape.HasPhysicalShape)
|
if (!m_terrainShape.HasPhysicalShape)
|
||||||
{
|
{
|
||||||
// DISASTER!!
|
// DISASTER!!
|
||||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
|
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID);
|
||||||
PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
|
PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
|
||||||
// Something is very messed up and a crash is in our future.
|
// Something is very messed up and a crash is in our future.
|
||||||
return;
|
return;
|
||||||
|
@ -151,7 +151,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
|
|
||||||
if (BSParam.UseSingleSidedMeshes)
|
if (BSParam.UseSingleSidedMeshes)
|
||||||
{
|
{
|
||||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial", id);
|
PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
|
||||||
PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
|
PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -415,18 +415,17 @@ namespace OpenSim.Region.RegionCombinerModule
|
||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// If we're one region over +x y
|
// If we're one region over +x y (i.e. root region is to the west)
|
||||||
//xxx
|
//xxx
|
||||||
//xxy
|
//xxy
|
||||||
//xxx
|
//xxx
|
||||||
|
|
||||||
if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
|
if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
|
||||||
{
|
{
|
||||||
connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
|
connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're one region over x +y
|
// If we're one region over x +y (i.e. root region is to the south)
|
||||||
//xyx
|
//xyx
|
||||||
//xxx
|
//xxx
|
||||||
//xxx
|
//xxx
|
||||||
|
@ -436,7 +435,7 @@ namespace OpenSim.Region.RegionCombinerModule
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're one region over +x +y
|
// If we're one region over +x +y (i.e. root region is to the south-west)
|
||||||
//xxy
|
//xxy
|
||||||
//xxx
|
//xxx
|
||||||
//xxx
|
//xxx
|
||||||
|
@ -646,7 +645,6 @@ namespace OpenSim.Region.RegionCombinerModule
|
||||||
{
|
{
|
||||||
if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
|
if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
|
||||||
{
|
{
|
||||||
|
|
||||||
rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
|
rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
|
||||||
|
|
||||||
lock (rootConn.RegionScene.NorthBorders)
|
lock (rootConn.RegionScene.NorthBorders)
|
||||||
|
|
|
@ -71,6 +71,7 @@ using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
|
||||||
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
|
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Timer = System.Timers.Timer;
|
using Timer = System.Timers.Timer;
|
||||||
|
using System.Linq;
|
||||||
using PermissionMask = OpenSim.Framework.PermissionMask;
|
using PermissionMask = OpenSim.Framework.PermissionMask;
|
||||||
|
|
||||||
namespace OpenSim.Region.ScriptEngine.Shared.Api
|
namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
|
@ -150,6 +151,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{"TURNLEFT", "Turning Left"},
|
{"TURNLEFT", "Turning Left"},
|
||||||
{"TURNRIGHT", "Turning Right"}
|
{"TURNRIGHT", "Turning Right"}
|
||||||
};
|
};
|
||||||
|
//An array of HTTP/1.1 headers that are not allowed to be used
|
||||||
|
//as custom headers by llHTTPRequest.
|
||||||
|
private string[] HttpStandardHeaders =
|
||||||
|
{
|
||||||
|
"Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language",
|
||||||
|
"Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control",
|
||||||
|
"Connection", "Content-Encoding", "Content-Language",
|
||||||
|
"Content-Length", "Content-Location", "Content-MD5",
|
||||||
|
"Content-Range", "Content-Type", "Date", "ETag", "Expect",
|
||||||
|
"Expires", "From", "Host", "If-Match", "If-Modified-Since",
|
||||||
|
"If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified",
|
||||||
|
"Location", "Max-Forwards", "Pragma", "Proxy-Authenticate",
|
||||||
|
"Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
|
||||||
|
"TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent",
|
||||||
|
"Vary", "Via", "Warning", "WWW-Authenticate"
|
||||||
|
};
|
||||||
|
|
||||||
public void Initialize(
|
public void Initialize(
|
||||||
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
|
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
|
||||||
|
@ -1750,7 +1767,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
if (tex.FaceTextures[i] != null)
|
if (tex.FaceTextures[i] != null)
|
||||||
{
|
{
|
||||||
tex.FaceTextures[i].Shiny = sval;
|
tex.FaceTextures[i].Shiny = sval;
|
||||||
tex.FaceTextures[i].Bump = bump;;
|
tex.FaceTextures[i].Bump = bump;
|
||||||
}
|
}
|
||||||
tex.DefaultTexture.Shiny = sval;
|
tex.DefaultTexture.Shiny = sval;
|
||||||
tex.DefaultTexture.Bump = bump;
|
tex.DefaultTexture.Bump = bump;
|
||||||
|
@ -2038,12 +2055,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
|
|
||||||
UUID textureID = new UUID();
|
UUID textureID = new UUID();
|
||||||
|
|
||||||
textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
|
textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
|
||||||
if (textureID == UUID.Zero)
|
if (textureID == UUID.Zero)
|
||||||
{
|
{
|
||||||
if (!UUID.TryParse(texture, out textureID))
|
if (!UUID.TryParse(texture, out textureID))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Primitive.TextureEntry tex = part.Shape.Textures;
|
Primitive.TextureEntry tex = part.Shape.Textures;
|
||||||
|
|
||||||
|
@ -11127,9 +11144,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
IHttpRequestModule httpScriptMod =
|
IHttpRequestModule httpScriptMod =
|
||||||
m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
|
m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
|
||||||
List<string> param = new List<string>();
|
List<string> param = new List<string>();
|
||||||
foreach (object o in parameters.Data)
|
bool ok;
|
||||||
|
Int32 flag;
|
||||||
|
|
||||||
|
for (int i = 0; i < parameters.Data.Length; i += 2)
|
||||||
{
|
{
|
||||||
param.Add(o.ToString());
|
ok = Int32.TryParse(parameters.Data[i].ToString(), out flag);
|
||||||
|
if (!ok || flag < 0 ||
|
||||||
|
flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE)
|
||||||
|
{
|
||||||
|
throw new ScriptException("Parameter " + i.ToString() + " is an invalid flag");
|
||||||
|
}
|
||||||
|
|
||||||
|
param.Add(parameters.Data[i].ToString()); //Add parameter flag
|
||||||
|
|
||||||
|
if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER)
|
||||||
|
{
|
||||||
|
param.Add(parameters.Data[i+1].ToString()); //Add parameter value
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Parameters are in pairs and custom header takes
|
||||||
|
//arguments in pairs so adjust for header marker.
|
||||||
|
++i;
|
||||||
|
|
||||||
|
//Maximum of 8 headers are allowed based on the
|
||||||
|
//Second Life documentation for llHTTPRequest.
|
||||||
|
for (int count = 1; count <= 8; ++count)
|
||||||
|
{
|
||||||
|
//Enough parameters remaining for (another) header?
|
||||||
|
if (parameters.Data.Length - i < 2)
|
||||||
|
{
|
||||||
|
//There must be at least one name/value pair for custom header
|
||||||
|
if (count == 1)
|
||||||
|
throw new ScriptException("Missing name/value for custom header at parameter " + i.ToString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase))
|
||||||
|
throw new ScriptException("Name is invalid as a custom header at parameter " + i.ToString());
|
||||||
|
|
||||||
|
param.Add(parameters.Data[i].ToString());
|
||||||
|
param.Add(parameters.Data[i+1].ToString());
|
||||||
|
|
||||||
|
//Have we reached the end of the list of headers?
|
||||||
|
//End is marked by a string with a single digit.
|
||||||
|
if (i+2 >= parameters.Data.Length ||
|
||||||
|
Char.IsDigit(parameters.Data[i].ToString()[0]))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 position = m_host.AbsolutePosition;
|
Vector3 position = m_host.AbsolutePosition;
|
||||||
|
|
|
@ -356,6 +356,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
public const int HTTP_MIMETYPE = 1;
|
public const int HTTP_MIMETYPE = 1;
|
||||||
public const int HTTP_BODY_MAXLENGTH = 2;
|
public const int HTTP_BODY_MAXLENGTH = 2;
|
||||||
public const int HTTP_VERIFY_CERT = 3;
|
public const int HTTP_VERIFY_CERT = 3;
|
||||||
|
public const int HTTP_VERBOSE_THROTTLE = 4;
|
||||||
|
public const int HTTP_CUSTOM_HEADER = 5;
|
||||||
|
public const int HTTP_PRAGMA_NO_CACHE = 6;
|
||||||
|
|
||||||
public const int PRIM_MATERIAL = 2;
|
public const int PRIM_MATERIAL = 2;
|
||||||
public const int PRIM_PHYSICS = 3;
|
public const int PRIM_PHYSICS = 3;
|
||||||
|
|
Loading…
Reference in New Issue