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);
|
||||
|
||||
// Agent management
|
||||
availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod);
|
||||
availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod);
|
||||
|
||||
// User management
|
||||
|
@ -1901,6 +1902,71 @@ namespace OpenSim.ApplicationPlugins.RemoteController
|
|||
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)
|
||||
{
|
||||
Hashtable responseData = (Hashtable)response.Value;
|
||||
|
|
|
@ -97,6 +97,14 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
+ " >= 1 - turns on outgoing event logging\n"
|
||||
+ " >= 2 - turns on poll notification",
|
||||
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)
|
||||
|
@ -138,7 +146,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -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>
|
||||
/// Always returns a valid queue
|
||||
/// </summary>
|
||||
|
|
|
@ -70,6 +70,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
|
||||
private string m_MapImageServerURL = string.Empty;
|
||||
private string m_SearchURL = string.Empty;
|
||||
private bool m_ExportSupported = false;
|
||||
|
||||
#region ISharedRegionModule Members
|
||||
|
||||
|
@ -87,6 +88,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
}
|
||||
|
||||
m_SearchURL = config.GetString("SearchServerURI", string.Empty);
|
||||
|
||||
m_ExportSupported = config.GetBoolean("ExportSupported", m_ExportSupported);
|
||||
}
|
||||
|
||||
AddDefaultFeatures();
|
||||
|
@ -152,6 +155,9 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
if (m_SearchURL != string.Empty)
|
||||
gridServicesMap["search"] = m_SearchURL;
|
||||
m_features["GridServices"] = gridServicesMap;
|
||||
|
||||
if (m_ExportSupported)
|
||||
m_features["ExportSupported"] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
#region INonSharedRegionModule
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public int DebugLevel { get; set; }
|
||||
|
||||
private Scene m_scene;
|
||||
private IInventoryAccessModule m_invAccessModule;
|
||||
|
||||
|
@ -76,11 +78,67 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
|
||||
|
||||
if (Enabled)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!Enabled)
|
||||
|
@ -165,10 +219,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (null == sp.Appearance)
|
||||
{
|
||||
m_log.WarnFormat("[ATTACHMENTS MODULE]: Appearance has not been initialized for agent {0}", sp.UUID);
|
||||
|
||||
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();
|
||||
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
|
||||
// inventory right now.
|
||||
if (sp.PresenceType == PresenceType.Npc)
|
||||
RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null, true);
|
||||
else
|
||||
RezSingleAttachmentFromInventory(sp, attach.ItemID, p | (uint)0x80, d);
|
||||
RezSingleAttachmentFromInventoryInternal(
|
||||
sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -254,7 +318,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (!Enabled)
|
||||
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();
|
||||
|
||||
|
@ -287,9 +352,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (!Enabled)
|
||||
return;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
|
||||
// m_scene.RegionInfo.RegionName, sp.Name, silent);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
|
||||
m_scene.RegionInfo.RegionName, sp.Name, silent);
|
||||
|
||||
foreach (SceneObjectGroup sop in sp.GetAttachments())
|
||||
{
|
||||
|
@ -299,12 +365,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
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)
|
||||
return false;
|
||||
|
||||
return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, false, append);
|
||||
return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -315,9 +381,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
/// <param name='group'>The object to attach.</param>
|
||||
/// <param name='attachmentPt'></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>
|
||||
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(
|
||||
// "[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)
|
||||
{
|
||||
// m_log.WarnFormat(
|
||||
// "[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());
|
||||
if (DebugLevel > 0)
|
||||
m_log.WarnFormat(
|
||||
"[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;
|
||||
}
|
||||
|
@ -372,6 +439,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
|
||||
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
|
||||
while (attachments.Count >= 5)
|
||||
{
|
||||
|
@ -395,8 +472,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
group.AttachmentPoint = attachmentPt;
|
||||
group.AbsolutePosition = attachPos;
|
||||
|
||||
if (sp.PresenceType != PresenceType.Npc)
|
||||
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append);
|
||||
if (addToInventory && sp.PresenceType != PresenceType.Npc)
|
||||
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
|
||||
|
||||
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
|
||||
|
||||
|
@ -415,17 +492,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
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.
|
||||
if (!temp)
|
||||
{
|
||||
UUID newAttachmentItemID = group.FromItemID;
|
||||
if (newAttachmentItemID == UUID.Zero)
|
||||
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
|
||||
UUID newAttachmentItemID = group.FromItemID;
|
||||
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)
|
||||
|
@ -438,40 +512,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (!Enabled)
|
||||
return null;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2} in {3}",
|
||||
// (AttachmentPoint)AttachmentPt, itemID, sp.Name, m_scene.Name);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[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;
|
||||
AttachmentPt &= 0x7f;
|
||||
|
||||
// Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
|
||||
// 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.
|
||||
// We check the attachments in the avatar appearance here rather than the objects attached to the
|
||||
// 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
|
||||
// because pre-outfit folder viewers (most version 1 viewers) require it.
|
||||
bool alreadyOn = false;
|
||||
List<SceneObjectGroup> existingAttachments = sp.GetAttachments();
|
||||
foreach (SceneObjectGroup so in existingAttachments)
|
||||
List<AvatarAttachment> existingAttachments = sp.Appearance.GetAttachments();
|
||||
foreach (AvatarAttachment existingAttachment in existingAttachments)
|
||||
{
|
||||
if (so.FromItemID == itemID)
|
||||
if (existingAttachment.ItemID == itemID)
|
||||
{
|
||||
alreadyOn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if (sp.Appearance.GetAttachmentForItem(itemID) != null)
|
||||
if (alreadyOn)
|
||||
{
|
||||
// m_log.WarnFormat(
|
||||
// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
|
||||
// sp.Name, itemID, AttachmentPt);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
|
||||
sp.Name, itemID, AttachmentPt);
|
||||
|
||||
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)
|
||||
|
@ -479,7 +553,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (!Enabled)
|
||||
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)
|
||||
{
|
||||
|
@ -497,9 +574,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (!Enabled)
|
||||
return;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
|
||||
// sp.UUID, soLocalId);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
|
||||
sp.UUID, soLocalId);
|
||||
|
||||
SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
|
||||
|
||||
|
@ -515,9 +593,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (inventoryID == UUID.Zero)
|
||||
return;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
|
||||
// so.Name, so.LocalId, inventoryID);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
|
||||
so.Name, so.LocalId, inventoryID);
|
||||
|
||||
lock (sp.AttachmentsSyncLock)
|
||||
{
|
||||
|
@ -572,9 +651,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
return;
|
||||
}
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
|
||||
// so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[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
|
||||
// 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
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
|
||||
// grp.UUID, grp.AttachmentPoint);
|
||||
// }
|
||||
else if (DebugLevel > 0)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
|
||||
grp.UUID, grp.AttachmentPoint);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -723,9 +803,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
private void AttachToAgent(
|
||||
IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
|
||||
// so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[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();
|
||||
|
||||
|
@ -750,9 +831,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
{
|
||||
if (so.HasPrivateAttachmentPoint)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Killing private HUD {0} for avatars other than {1} at attachment point {2}",
|
||||
// so.Name, sp.Name, so.AttachmentPoint);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[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
|
||||
// scene that it's no longer in their awareness.
|
||||
|
@ -786,9 +868,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (m_invAccessModule == null)
|
||||
return null;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
|
||||
// grp.Name, grp.LocalId, remoteClient.Name);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
|
||||
grp.Name, grp.LocalId, sp.Name);
|
||||
|
||||
InventoryItemBase newItem
|
||||
= m_invAccessModule.CopyToInventory(
|
||||
|
@ -872,7 +955,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
}
|
||||
|
||||
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)
|
||||
return null;
|
||||
|
@ -897,6 +980,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
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.
|
||||
objatt.HasGroupChanged = false;
|
||||
bool tainted = false;
|
||||
|
@ -917,7 +1005,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
objatt.ResetOwnerChangeFlag();
|
||||
}
|
||||
|
||||
AttachObjectInternal(sp, objatt, attachmentPt, false, true, false, true, append);
|
||||
AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -971,9 +1059,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID);
|
||||
if (changed && m_scene.AvatarFactory != null)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
|
||||
// sp.Name, att.Name, AttachmentPt);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: Queueing appearance save for {0}, attachment {1} point {2} in ShowAttachInUserInventory()",
|
||||
sp.Name, att.Name, AttachmentPt);
|
||||
|
||||
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
|
||||
}
|
||||
|
@ -988,9 +1077,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
if (!Enabled)
|
||||
return null;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
|
||||
// (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
|
||||
(AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
|
||||
|
||||
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)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
|
||||
// objectLocalID, remoteClient.Name, AttachmentPt, silent);
|
||||
if (DebugLevel > 0)
|
||||
m_log.DebugFormat(
|
||||
"[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
|
||||
objectLocalID, remoteClient.Name, AttachmentPt, silent);
|
||||
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
@ -1056,11 +1147,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
|||
AttachmentPt &= 0x7f;
|
||||
|
||||
// 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(
|
||||
// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
|
||||
// + ", AttachmentPoint: " + AttachmentPt);
|
||||
if (DebugLevel > 0)
|
||||
m_log.Debug(
|
||||
"[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
|
||||
+ ", AttachmentPoint: " + AttachmentPt);
|
||||
|
||||
// Save avatar attachment information
|
||||
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.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
|
||||
|
||||
modules.Add(new AttachmentsModule());
|
||||
AttachmentsModule attMod = new AttachmentsModule();
|
||||
attMod.DebugLevel = 1;
|
||||
modules.Add(attMod);
|
||||
modules.Add(new BasicInventoryAccessModule());
|
||||
}
|
||||
|
||||
|
@ -197,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
|||
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
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
|
||||
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.
|
||||
{
|
||||
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
|
||||
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.
|
||||
{
|
||||
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
|
||||
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.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(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||
|
@ -728,7 +730,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
|||
public void TestRezAttachmentsOnAvatarEntrance()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// log4net.Config.XmlConfigurator.Configure();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
Scene scene = CreateTestScene();
|
||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
|
||||
|
|
|
@ -154,7 +154,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
|
|||
(uint)presence.AbsolutePosition.Y,
|
||||
(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;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ using System.Threading;
|
|||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Capabilities;
|
||||
using OpenSim.Framework.Client;
|
||||
using OpenSim.Framework.Monitoring;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
@ -77,6 +78,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
/// </remarks>
|
||||
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;
|
||||
|
||||
public Scene Scene { get; private set; }
|
||||
|
@ -91,6 +117,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
|
||||
|
||||
private IEventQueue m_eqModule;
|
||||
private IRegionCombinerModule m_regionCombinerModule;
|
||||
|
||||
#region ISharedRegionModule
|
||||
|
||||
|
@ -156,6 +183,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
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.EventManager.OnNewClient += OnNewClient;
|
||||
}
|
||||
|
@ -173,7 +254,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
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)
|
||||
{
|
||||
|
@ -181,6 +271,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
return;
|
||||
|
||||
m_eqModule = Scene.RequestModuleInterface<IEventQueue>();
|
||||
m_regionCombinerModule = Scene.RequestModuleInterface<IRegionCombinerModule>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -291,8 +382,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
Vector3 emergencyPos = new Vector3(128, 128, 128);
|
||||
|
||||
m_log.WarnFormat(
|
||||
"[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
|
||||
position, sp.Name, sp.UUID, emergencyPos);
|
||||
"[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2} in {3}. Substituting {4}",
|
||||
position, sp.Name, sp.UUID, Scene.Name, emergencyPos);
|
||||
|
||||
position = emergencyPos;
|
||||
}
|
||||
|
@ -548,6 +639,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
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);
|
||||
|
||||
// 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;
|
||||
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
|
||||
{
|
||||
m_interRegionTeleportFailures.Value++;
|
||||
|
||||
sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
|
||||
|
||||
m_log.DebugFormat(
|
||||
|
@ -611,6 +709,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
|
||||
{
|
||||
m_interRegionTeleportCancels.Value++;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
|
||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||
|
@ -619,6 +719,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
}
|
||||
else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||
{
|
||||
m_interRegionTeleportAborts.Value++;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
|
||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||
|
@ -635,6 +737,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
IClientIPEndpoint ipepClient;
|
||||
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...");
|
||||
#region IP Translation for NAT
|
||||
// Uses ipepClient above
|
||||
|
@ -688,6 +794,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
// establish th econnection to the destination which makes it return true.
|
||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||
{
|
||||
m_interRegionTeleportAborts.Value++;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
|
||||
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)
|
||||
{
|
||||
m_interRegionTeleportAborts.Value++;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[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);
|
||||
|
@ -720,6 +830,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
|
||||
{
|
||||
m_interRegionTeleportCancels.Value++;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
|
||||
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)
|
||||
{
|
||||
m_interRegionTeleportAborts.Value++;
|
||||
|
||||
m_log.DebugFormat(
|
||||
"[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);
|
||||
|
@ -767,6 +881,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
||||
|
||||
Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -808,15 +923,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
// now we have a child agent in this region.
|
||||
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>
|
||||
|
@ -852,6 +958,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
{
|
||||
CleanupFailedInterRegionTeleport(sp, finalDestination);
|
||||
|
||||
m_interRegionTeleportFailures.Value++;
|
||||
|
||||
sp.ControllingClient.SendTeleportFailed(
|
||||
string.Format(
|
||||
"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)
|
||||
{
|
||||
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)
|
||||
|
@ -1011,6 +1133,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
{
|
||||
version = String.Empty;
|
||||
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 neighboury = scene.RegionInfo.RegionLocY;
|
||||
const float boundaryDistance = 1.7f;
|
||||
|
@ -1183,6 +1309,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
{
|
||||
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>();
|
||||
if (im != null)
|
||||
{
|
||||
|
@ -1217,6 +1355,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
});
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar)
|
||||
|
@ -1724,6 +1863,37 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
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>
|
||||
/// Return the list of regions that are considered to be neighbours to the given scene.
|
||||
/// </summary>
|
||||
|
@ -1736,15 +1906,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
Scene pScene = avatar.Scene;
|
||||
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
|
||||
// clear what should be done with a "far view" given that megaregions already extended the
|
||||
// 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;
|
||||
|
||||
|
@ -1762,27 +1927,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
Vector2 swCorner, neCorner;
|
||||
GetMegaregionViewRange(out swCorner, out neCorner);
|
||||
|
||||
// Loss of fraction on purpose
|
||||
extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1;
|
||||
extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1;
|
||||
List<GridRegion> neighbours
|
||||
= pScene.GridService.GetRegionRange(
|
||||
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; });
|
||||
|
||||
return neighbours;
|
||||
|
|
|
@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
public override void RemoveRegion(Scene scene)
|
||||
{
|
||||
base.AddRegion(scene);
|
||||
base.RemoveRegion(scene);
|
||||
|
||||
if (m_Enabled)
|
||||
scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
|
||||
|
|
|
@ -189,6 +189,45 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
|||
case (int)HttpRequestConstants.HTTP_VERIFY_CERT:
|
||||
htc.HttpVerifyCert = (int.Parse(parms[i + 1]) != 0);
|
||||
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_MIMETYPE = 1;
|
||||
// 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;
|
||||
public bool Finished
|
||||
{
|
||||
|
@ -367,6 +409,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
|||
public bool HttpVerifyCert = true;
|
||||
public IWorkItemResult WorkItem = null;
|
||||
|
||||
//public bool HttpVerboseThrottle = true; // not implemented
|
||||
public List<string> HttpCustomHeaders = null;
|
||||
public bool HttpPragmaNoCache = true;
|
||||
private Thread httpThread;
|
||||
|
||||
// Request info
|
||||
private UUID _itemID;
|
||||
public UUID ItemID
|
||||
|
@ -434,12 +481,26 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
|
|||
Request.Method = HttpMethod;
|
||||
Request.ContentType = HttpMIMEType;
|
||||
|
||||
if(!HttpVerifyCert)
|
||||
if (!HttpVerifyCert)
|
||||
{
|
||||
// We could hijack Connection Group Name to identify
|
||||
// a desired security exception. But at the moment we'll use a dummy header instead.
|
||||
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 (proxyexcepts != null && proxyexcepts.Length > 0)
|
||||
|
|
|
@ -597,6 +597,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
cdl.AddRow("LightFalloff", s.LightFalloff);
|
||||
cdl.AddRow("LightIntensity", s.LightIntensity);
|
||||
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("PathBegin", s.PathBegin);
|
||||
cdl.AddRow("PathEnd", s.PathEnd);
|
||||
|
@ -619,6 +620,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
|
|||
cdl.AddRow("ProjectionFocus", s.ProjectionFocus);
|
||||
cdl.AddRow("ProjectionFOV", s.ProjectionFOV);
|
||||
cdl.AddRow("ProjectionTextureUUID", s.ProjectionTextureUUID);
|
||||
cdl.AddRow("Rotation (Relative)", sop.RotationOffset);
|
||||
cdl.AddRow("Rotation (World)", sop.GetWorldRotation());
|
||||
cdl.AddRow("Scale", s.Scale);
|
||||
cdl.AddRow(
|
||||
"SculptData",
|
||||
|
|
|
@ -54,6 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
/// 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>
|
||||
/// <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>
|
||||
void RezAttachments(IScenePresence sp);
|
||||
|
||||
|
@ -77,14 +81,16 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
void DeleteAttachmentsFromScene(IScenePresence sp, bool silent);
|
||||
|
||||
/// <summary>
|
||||
/// Attach an object to an avatar
|
||||
/// Attach an object to an avatar.
|
||||
/// </summary>
|
||||
/// <param name="sp"></param>
|
||||
/// <param name="grp"></param>
|
||||
/// <param name="AttachmentPt"></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>
|
||||
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>
|
||||
/// 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_BODY_MAXLENGTH = 2,
|
||||
HTTP_VERIFY_CERT = 3,
|
||||
HTTP_VERBOSE_THROTTLE = 4,
|
||||
HTTP_CUSTOM_HEADER = 5,
|
||||
HTTP_PRAGMA_NO_CACHE = 6
|
||||
}
|
||||
|
||||
public interface IHttpRequestModule
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
public class Border
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Line perpendicular to the Direction Cardinal. Z value is the
|
||||
/// </summary>
|
||||
|
@ -81,6 +80,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
TriggerRegionY = triggerRegionY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests to see if the given position would cross this border.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool TestCross(Vector3 position)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
|
@ -2645,7 +2645,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -2863,6 +2862,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
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)
|
||||
AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
|
||||
}
|
||||
|
@ -2979,35 +2981,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_eventManager.TriggerOnNewPresence(sp);
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -4344,33 +4317,33 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an agent crosses into this sim. Also happens on initial login.
|
||||
/// </summary>
|
||||
/// <param name="agentID"></param>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="isFlying"></param>
|
||||
public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
|
||||
{
|
||||
ScenePresence presence = GetScenePresence(agentID);
|
||||
if (presence != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
presence.MakeRootAgent(position, isFlying);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[SCENE]: Could not find presence for agent {0} crossing into scene {1}",
|
||||
agentID, RegionInfo.RegionName);
|
||||
}
|
||||
}
|
||||
// /// <summary>
|
||||
// /// Triggered when an agent crosses into this sim. Also happens on initial login.
|
||||
// /// </summary>
|
||||
// /// <param name="agentID"></param>
|
||||
// /// <param name="position"></param>
|
||||
// /// <param name="isFlying"></param>
|
||||
// public virtual void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
|
||||
// {
|
||||
// ScenePresence presence = GetScenePresence(agentID);
|
||||
// if (presence != null)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// presence.MakeRootAgent(position, isFlying);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// m_log.ErrorFormat("[SCENE]: Unable to do agent crossing, exception {0}{1}", e.Message, e.StackTrace);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// m_log.ErrorFormat(
|
||||
// "[SCENE]: Could not find presence for agent {0} crossing into scene {1}",
|
||||
// agentID, RegionInfo.RegionName);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
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;
|
||||
lock (m_scriptEvents)
|
||||
{
|
||||
|
|
|
@ -456,9 +456,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
m_pos = PhysicsActor.Position;
|
||||
|
||||
//m_log.DebugFormat(
|
||||
// "[SCENE PRESENCE]: Set position {0} for {1} in {2} via getting AbsolutePosition!",
|
||||
// m_pos, Name, Scene.RegionInfo.RegionName);
|
||||
// m_log.DebugFormat(
|
||||
// "[SCENE PRESENCE]: Set position of {0} in {1} to {2} via getting AbsolutePosition!",
|
||||
// Name, Scene.Name, m_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -485,6 +485,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
set
|
||||
{
|
||||
// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value);
|
||||
// Util.PrintCallStack();
|
||||
|
||||
if (PhysicsActor != null)
|
||||
{
|
||||
try
|
||||
|
@ -938,8 +941,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
"[SCENE]: Upgrading child to root agent for {0} in {1}",
|
||||
Name, m_scene.RegionInfo.RegionName);
|
||||
|
||||
bool wasChild = IsChildAgent;
|
||||
|
||||
if (ParentUUID != UUID.Zero)
|
||||
{
|
||||
m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
|
||||
|
@ -972,6 +973,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
IsLoggingIn = false;
|
||||
}
|
||||
|
||||
//m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
|
||||
|
||||
IsChildAgent = false;
|
||||
|
||||
IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
|
||||
if (gm != null)
|
||||
|
@ -1065,6 +1069,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
else
|
||||
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)
|
||||
{
|
||||
Flying = true;
|
||||
|
@ -1085,22 +1096,43 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// and it has already rezzed the attachments and started their scripts.
|
||||
// We do the following only for non-login agents, because their scripts
|
||||
// haven't started yet.
|
||||
lock (m_attachments)
|
||||
if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0)
|
||||
{
|
||||
if (wasChild && 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)
|
||||
// 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.
|
||||
if (Scene.AttachmentsModule != null)
|
||||
Util.FireAndForget(
|
||||
o =>
|
||||
{
|
||||
sog.ScheduleGroupForFullUpdate();
|
||||
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
|
||||
sog.ResumeScripts();
|
||||
}
|
||||
});
|
||||
// if (PresenceType != PresenceType.Npc && Util.FireAndForgetMethod != FireAndForgetMethod.None)
|
||||
// System.Threading.Thread.Sleep(7000);
|
||||
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
bool needsTransit = false;
|
||||
if (m_scene.TestBorderCross(pos2, Cardinals.W))
|
||||
|
|
|
@ -184,7 +184,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
|||
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 updates is true then any frame which exceeds double the maximum desired frame time is logged.",
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
// 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.
|
||||
public void ComputeAngularVerticalAttraction()
|
||||
{
|
||||
|
||||
// If vertical attaction timescale is reasonable
|
||||
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 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
|
||||
|
||||
// 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)
|
||||
// is now:
|
||||
|
@ -1334,13 +1372,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
|
||||
// Correction happens over a number of seconds.
|
||||
Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
|
||||
|
||||
// The correction happens over the user's time period
|
||||
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}",
|
||||
Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
|
||||
m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,11 +180,14 @@ public static class BSMaterials
|
|||
// Use reflection to set the value in the attribute structure.
|
||||
private static void SetAttributeValue(int matType, string attribName, float val)
|
||||
{
|
||||
// Get the current attribute values for this material
|
||||
MaterialAttributes thisAttrib = Attributes[matType];
|
||||
// Find the field for the passed attribute name (eg, find field named 'friction')
|
||||
FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
|
||||
if (fieldInfo != null)
|
||||
{
|
||||
fieldInfo.SetValue(thisAttrib, val);
|
||||
// Copy new attributes back to array -- since MaterialAttributes is 'struct', passed by value, not reference.
|
||||
Attributes[matType] = thisAttrib;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,6 +142,14 @@ public static class BSParam
|
|||
public static float VehicleAngularBankingTimescaleFudge { 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
|
||||
public static float LinksetImplementation { 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 sealed class ParameterDefn<T> : ParameterDefnBase
|
||||
{
|
||||
T defaultValue;
|
||||
PSetValue<T> setter;
|
||||
PGetValue<T> getter;
|
||||
PSetOnObject<T> objectSet;
|
||||
private T defaultValue;
|
||||
private PSetValue<T> setter;
|
||||
private PGetValue<T> getter;
|
||||
private PSetOnObject<T> objectSet;
|
||||
public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
|
||||
: base(pName, pDesc)
|
||||
{
|
||||
|
@ -215,13 +223,23 @@ public static class BSParam
|
|||
getter = pGetter;
|
||||
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)
|
||||
{
|
||||
setter(s, defaultValue);
|
||||
}
|
||||
public override string GetValue(BSScene s)
|
||||
{
|
||||
return String.Format("{0}", getter(s));
|
||||
return getter(s).ToString();
|
||||
}
|
||||
public override void SetValue(BSScene s, string valAsString)
|
||||
{
|
||||
|
@ -244,6 +262,7 @@ public static class BSParam
|
|||
try
|
||||
{
|
||||
T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString });
|
||||
// Store the parsed value
|
||||
setter(s, setValue);
|
||||
// s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue);
|
||||
}
|
||||
|
@ -463,7 +482,7 @@ public static class BSParam
|
|||
(s) => { return TerrainImplementation; },
|
||||
(s,v) => { TerrainImplementation = v; } ),
|
||||
new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
|
||||
3,
|
||||
2,
|
||||
(s) => { return TerrainMeshMagnification; },
|
||||
(s,v) => { TerrainMeshMagnification = v; } ),
|
||||
new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||
|
@ -623,6 +642,31 @@ public static class BSParam
|
|||
(s) => { return GlobalContactBreakingThreshold; },
|
||||
(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)",
|
||||
(float)BSLinkset.LinksetImplementation.Compound,
|
||||
(s) => { return LinksetImplementation; },
|
||||
|
|
|
@ -86,7 +86,7 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
PhysBody = new BulletBody(localID);
|
||||
PhysShape = new BulletShape();
|
||||
|
||||
LastAssetBuildFailed = false;
|
||||
PrimAssetState = PrimAssetCondition.Unknown;
|
||||
|
||||
// Default material type. Also sets Friction, Restitution and Density.
|
||||
SetMaterial((int)MaterialAttributes.Material.Wood);
|
||||
|
@ -133,9 +133,13 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
// Reference to the physical shape (btCollisionShape) of this object
|
||||
public BulletShape PhysShape;
|
||||
|
||||
// 'true' if the mesh's underlying asset failed to build.
|
||||
// This will keep us from looping after the first time the build failed.
|
||||
public bool LastAssetBuildFailed { get; set; }
|
||||
// The physical representation of the prim might require an asset fetch.
|
||||
// The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
|
||||
public enum PrimAssetCondition
|
||||
{
|
||||
Unknown, Waiting, Failed, Fetched
|
||||
}
|
||||
public PrimAssetCondition PrimAssetState { get; set; }
|
||||
|
||||
// The objects base shape information. Null if not a prim type shape.
|
||||
public PrimitiveBaseShape BaseShape { get; protected set; }
|
||||
|
|
|
@ -155,7 +155,7 @@ public class BSPrim : BSPhysObject
|
|||
public override PrimitiveBaseShape Shape {
|
||||
set {
|
||||
BaseShape = value;
|
||||
LastAssetBuildFailed = false;
|
||||
PrimAssetState = PrimAssetCondition.Unknown;
|
||||
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 (!haveShape
|
||||
&& nativeShapePossible
|
||||
&& pbs != null
|
||||
&& !pbs.SculptEntry
|
||||
&& nativeShapePossible
|
||||
&& ((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) ) )
|
||||
&& ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) )
|
||||
{
|
||||
// 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;
|
||||
|
@ -508,6 +501,18 @@ public sealed class BSShapeCollection : IDisposable
|
|||
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.
|
||||
public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
|
||||
{
|
||||
|
@ -518,7 +523,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
|
||||
{
|
||||
// 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}",
|
||||
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.
|
||||
// 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)
|
||||
{
|
||||
BulletShape newShape;
|
||||
|
@ -717,6 +723,7 @@ public sealed class BSShapeCollection : IDisposable
|
|||
DereferenceShape(prim.PhysShape, shapeCallback);
|
||||
|
||||
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);
|
||||
|
||||
ReferenceShape(newShape);
|
||||
|
@ -735,13 +742,13 @@ public sealed class BSShapeCollection : IDisposable
|
|||
HullDesc 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();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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
|
||||
// Build a new hull in the physical world.
|
||||
// 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);
|
||||
if (meshData != null)
|
||||
{
|
||||
|
@ -761,15 +768,35 @@ public sealed class BSShapeCollection : IDisposable
|
|||
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
|
||||
m_hulls = new List<ConvexResult>();
|
||||
DecompDesc dcomp = new DecompDesc();
|
||||
dcomp.mIndices = convIndices;
|
||||
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);
|
||||
// create the hull into the _hulls variable
|
||||
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.
|
||||
// The hull information is passed as a large floating point array.
|
||||
// The format is:
|
||||
|
@ -904,58 +931,79 @@ public sealed class BSShapeCollection : IDisposable
|
|||
if (newShape.HasPhysicalShape)
|
||||
return newShape;
|
||||
|
||||
// If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
|
||||
if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero)
|
||||
// VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
|
||||
// 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);
|
||||
// This will prevent looping through this code as we keep trying to get the failed shape
|
||||
prim.LastAssetBuildFailed = true;
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
|
||||
PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
|
||||
LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
|
||||
}
|
||||
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}",
|
||||
LogHeader, prim.LocalID, prim.BaseShape.SculptTexture);
|
||||
DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
|
||||
// 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.
|
||||
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
|
||||
BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
|
||||
m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
|
||||
|
@ -145,14 +146,18 @@ public sealed class BSTerrainManager : IDisposable
|
|||
m_groundPlane.collisionType = CollisionType.Groundplane;
|
||||
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);
|
||||
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
|
||||
public void ReleaseGroundPlaneAndTerrain()
|
||||
{
|
||||
DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName);
|
||||
if (m_groundPlane.HasPhysicalBody)
|
||||
{
|
||||
if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane))
|
||||
|
@ -193,11 +198,16 @@ public sealed class BSTerrainManager : IDisposable
|
|||
// the terrain is added to our parent
|
||||
if (MegaRegionParentPhysicsScene is BSScene)
|
||||
{
|
||||
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
|
||||
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||
((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
|
||||
BSScene.CHILDTERRAIN_ID, localHeightMap,
|
||||
m_worldOffset, m_worldOffset + DefaultRegionSize, true);
|
||||
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||
// This looks really odd but this region is passing its terrain to its mega-region root region
|
||||
// and the creation of the terrain must happen on the root region's taint thread and not
|
||||
// my taint thread.
|
||||
((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
|
||||
|
@ -206,16 +216,16 @@ public sealed class BSTerrainManager : IDisposable
|
|||
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
||||
|
||||
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
|
||||
// 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.
|
||||
// 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.
|
||||
// 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.)
|
||||
|
@ -223,8 +233,8 @@ public sealed class BSTerrainManager : IDisposable
|
|||
private void UpdateTerrain(uint id, float[] heightMap,
|
||||
Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
|
||||
{
|
||||
DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
|
||||
BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
|
||||
DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1},minC={2},maxC={3},inTaintTime={4}",
|
||||
BSScene.DetailLogZero, id, minCoords, maxCoords, inTaintTime);
|
||||
|
||||
// Find high and low points of passed heightmap.
|
||||
// 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))
|
||||
{
|
||||
// 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);
|
||||
|
||||
// Remove old terrain from the collection
|
||||
|
@ -292,7 +302,7 @@ public sealed class BSTerrainManager : IDisposable
|
|||
if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
|
||||
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);
|
||||
BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
|
||||
m_terrains.Add(terrainRegionBase, newTerrainPhys);
|
||||
|
@ -343,37 +353,35 @@ public sealed class BSTerrainManager : IDisposable
|
|||
{
|
||||
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.
|
||||
if (m_terrains.Count == 0)
|
||||
return ret;
|
||||
|
||||
int loopPrevention = 5;
|
||||
int loopPrevention = 10;
|
||||
Vector3 terrainBaseXYZ;
|
||||
BSTerrainPhys physTerrain;
|
||||
while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ))
|
||||
{
|
||||
// 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.
|
||||
if (ret.X < 0f || ret.Y < 0f)
|
||||
{
|
||||
if (ret.X < 0f)
|
||||
ret.X = 0f;
|
||||
if (ret.Y < 0f)
|
||||
ret.Y = 0f;
|
||||
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);
|
||||
// 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 + (ret.X % DefaultRegionSize.X));
|
||||
ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + (ret.X % DefaultRegionSize.Y));
|
||||
DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
|
||||
BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
|
||||
|
||||
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)
|
||||
{
|
||||
// The 'while' is a little dangerous so this prevents looping forever if the
|
||||
|
@ -383,6 +391,7 @@ public sealed class BSTerrainManager : IDisposable
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -479,11 +488,20 @@ public sealed class BSTerrainManager : IDisposable
|
|||
private Vector3 FindAdjacentTerrainBase(Vector3 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;
|
||||
|
||||
lock (m_terrains)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
|
|
|
@ -98,20 +98,20 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
if (!meshCreationSuccess)
|
||||
{
|
||||
// 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);
|
||||
// Something is very messed up and a crash is in our future.
|
||||
return;
|
||||
}
|
||||
|
||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
|
||||
ID, indicesCount, indices.Length, verticesCount, vertices.Length);
|
||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
|
||||
BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);
|
||||
|
||||
m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices);
|
||||
if (!m_terrainShape.HasPhysicalShape)
|
||||
{
|
||||
// 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);
|
||||
// Something is very messed up and a crash is in our future.
|
||||
return;
|
||||
|
@ -151,7 +151,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -415,18 +415,17 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
*/
|
||||
#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
|
||||
//xxy
|
||||
//xxx
|
||||
|
||||
if (rootConn.PosX + rootConn.XEnd >= newConn.PosX && rootConn.PosY >= newConn.PosY)
|
||||
{
|
||||
connectedYN = DoWorkForOneRegionOverPlusXY(rootConn, newConn, scene);
|
||||
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
|
||||
//xxx
|
||||
//xxx
|
||||
|
@ -436,7 +435,7 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
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
|
||||
//xxx
|
||||
//xxx
|
||||
|
@ -646,7 +645,6 @@ namespace OpenSim.Region.RegionCombinerModule
|
|||
{
|
||||
if (rootConn.RegionScene.EastBorders.Count == 1)// && conn.RegionScene.EastBorders.Count == 2)
|
||||
{
|
||||
|
||||
rootConn.RegionScene.EastBorders[0].BorderLine.Z += (int)Constants.RegionSize;
|
||||
|
||||
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 System.Reflection;
|
||||
using Timer = System.Timers.Timer;
|
||||
using System.Linq;
|
||||
using PermissionMask = OpenSim.Framework.PermissionMask;
|
||||
|
||||
namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
@ -150,6 +151,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
{"TURNLEFT", "Turning Left"},
|
||||
{"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(
|
||||
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
|
||||
|
@ -1750,7 +1767,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
if (tex.FaceTextures[i] != null)
|
||||
{
|
||||
tex.FaceTextures[i].Shiny = sval;
|
||||
tex.FaceTextures[i].Bump = bump;;
|
||||
tex.FaceTextures[i].Bump = bump;
|
||||
}
|
||||
tex.DefaultTexture.Shiny = sval;
|
||||
tex.DefaultTexture.Bump = bump;
|
||||
|
@ -2038,12 +2055,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
|
||||
UUID textureID = new UUID();
|
||||
|
||||
textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
|
||||
if (textureID == UUID.Zero)
|
||||
{
|
||||
if (!UUID.TryParse(texture, out textureID))
|
||||
return;
|
||||
}
|
||||
textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
|
||||
if (textureID == UUID.Zero)
|
||||
{
|
||||
if (!UUID.TryParse(texture, out textureID))
|
||||
return;
|
||||
}
|
||||
|
||||
Primitive.TextureEntry tex = part.Shape.Textures;
|
||||
|
||||
|
@ -11127,9 +11144,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
IHttpRequestModule httpScriptMod =
|
||||
m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
|
||||
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;
|
||||
|
|
|
@ -356,6 +356,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
|||
public const int HTTP_MIMETYPE = 1;
|
||||
public const int HTTP_BODY_MAXLENGTH = 2;
|
||||
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_PHYSICS = 3;
|
||||
|
|
Loading…
Reference in New Issue