Merge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork

avinationmerge
ubit 2013-04-28 19:46:57 +02:00
commit 7000b52aeb
41 changed files with 1218 additions and 520 deletions

View File

@ -30,6 +30,7 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using log4net;
using Nini.Config;
using OpenMetaverse;
@ -68,6 +69,7 @@ namespace OpenSim.Framework.Capabilities
private IHttpServer m_httpListener;
private UUID m_agentID;
private string m_regionName;
private ManualResetEvent m_capsActive = new ManualResetEvent(false);
public UUID AgentID
{
@ -171,5 +173,16 @@ namespace OpenSim.Framework.Capabilities
}
}
}
public void Activate()
{
m_capsActive.Set();
}
public bool WaitForActivation()
{
// Wait for 30s. If that elapses, return false and run without caps
return m_capsActive.WaitOne(30000);
}
}
}

View File

@ -435,4 +435,4 @@ namespace OpenSim.Capabilities.Handlers
return llsdItem;
}
}
}
}

View File

@ -1339,7 +1339,7 @@ namespace OpenSim.Data.MySQL
prim.Density = (float)(double)row["Density"];
prim.GravityModifier = (float)(double)row["GravityModifier"];
prim.Friction = (float)(double)row["Friction"];
prim.Bounciness = (float)(double)row["Restitution"];
prim.Restitution = (float)(double)row["Restitution"];
SOPVehicle vehicle = null;
@ -1725,7 +1725,7 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("Density", (double)prim.Density);
cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier);
cmd.Parameters.AddWithValue("Friction", (double)prim.Friction);
cmd.Parameters.AddWithValue("Restitution", (double)prim.Bounciness);
cmd.Parameters.AddWithValue("Restitution", (double)prim.Restitution);
if (prim.VehicleParams != null)
cmd.Parameters.AddWithValue("Vehicle", prim.VehicleParams.ToXml2());

View File

@ -497,8 +497,6 @@ namespace OpenSim.Framework
/// </remarks>
public List<AvatarAttachment> GetAttachments()
{
lock (m_attachments)
{
List<AvatarAttachment> alist = new List<AvatarAttachment>();
@ -508,7 +506,8 @@ namespace OpenSim.Framework
alist.Add(new AvatarAttachment(attach));
}
return alist;
} }
}
}
internal void AppendAttachment(AvatarAttachment attach)
{

View File

@ -2097,4 +2097,112 @@ namespace OpenSim.Framework
}
#endregion
}
public class DoubleQueue<T> where T:class
{
private Queue<T> m_lowQueue = new Queue<T>();
private Queue<T> m_highQueue = new Queue<T>();
private object m_syncRoot = new object();
private Semaphore m_s = new Semaphore(0, 1);
public DoubleQueue()
{
}
public virtual int Count
{
get { return m_highQueue.Count + m_lowQueue.Count; }
}
public virtual void Enqueue(T data)
{
Enqueue(m_lowQueue, data);
}
public virtual void EnqueueLow(T data)
{
Enqueue(m_lowQueue, data);
}
public virtual void EnqueueHigh(T data)
{
Enqueue(m_highQueue, data);
}
private void Enqueue(Queue<T> q, T data)
{
lock (m_syncRoot)
{
m_lowQueue.Enqueue(data);
m_s.WaitOne(0);
m_s.Release();
}
}
public virtual T Dequeue()
{
return Dequeue(Timeout.Infinite);
}
public virtual T Dequeue(int tmo)
{
return Dequeue(TimeSpan.FromMilliseconds(tmo));
}
public virtual T Dequeue(TimeSpan wait)
{
T res = null;
if (!Dequeue(wait, ref res))
return null;
return res;
}
public bool Dequeue(int timeout, ref T res)
{
return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
}
public bool Dequeue(TimeSpan wait, ref T res)
{
if (!m_s.WaitOne(wait))
return false;
lock (m_syncRoot)
{
if (m_highQueue.Count > 0)
res = m_highQueue.Dequeue();
else
res = m_lowQueue.Dequeue();
if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
return true;
try
{
m_s.Release();
}
catch
{
}
return true;
}
}
public virtual void Clear()
{
lock (m_syncRoot)
{
// Make sure sem count is 0
m_s.WaitOne(0);
m_lowQueue.Clear();
m_highQueue.Clear();
}
}
}
}

View File

@ -343,6 +343,9 @@ namespace OpenSim.Region.ClientStack.Linden
m_log.DebugFormat(
"[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
if (!m_HostCapsObj.WaitForActivation())
return string.Empty;
if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
{
m_log.WarnFormat(
@ -1317,7 +1320,7 @@ namespace OpenSim.Region.ClientStack.Linden
object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
object_data["Density"] = obj.Density;
object_data["Friction"] = obj.Friction;
object_data["Restitution"] = obj.Bounciness;
object_data["Restitution"] = obj.Restitution;
object_data["GravityMultiplier"] = obj.GravityModifier;
resp[uuid.ToString()] = object_data;

View File

@ -467,8 +467,8 @@ namespace OpenSim.Region.ClientStack.Linden
responsedata["content_type"] = "text/plain";
responsedata["keepalive"] = false;
responsedata["reusecontext"] = false;
responsedata["str_response_string"] = "Upstream error: ";
responsedata["error_status_text"] = "Upstream error:";
responsedata["str_response_string"] = "<llsd></llsd>";
responsedata["error_status_text"] = "<llsd></llsd>";
responsedata["http_protocol_version"] = "HTTP/1.0";
return responsedata;
}

View File

@ -59,6 +59,8 @@ namespace OpenSim.Region.ClientStack.Linden
// private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
private Scene m_scene;
/// <summary>
@ -94,6 +96,8 @@ namespace OpenSim.Region.ClientStack.Linden
{
m_scene = s;
m_scene.EventManager.OnRegisterCaps += RegisterCaps;
m_scene.RegisterModuleInterface<ISimulatorFeaturesModule>(this);
}
public void RemoveRegion(Scene s)
@ -156,7 +160,7 @@ namespace OpenSim.Region.ClientStack.Linden
IRequestHandler reqHandler
= new RestHTTPHandler(
"GET", "/CAPS/" + UUID.Random(),
HandleSimulatorFeaturesRequest, "SimulatorFeatures", agentID.ToString());
x => { return HandleSimulatorFeaturesRequest(x, agentID); }, "SimulatorFeatures", agentID.ToString());
caps.RegisterHandler("SimulatorFeatures", reqHandler);
}
@ -185,18 +189,33 @@ namespace OpenSim.Region.ClientStack.Linden
return new OSDMap(m_features);
}
private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod)
private OSDMap DeepCopy()
{
// This isn't the cheapest way of doing this but the rate
// of occurrence is low (on sim entry only) and it's a sure
// way to get a true deep copy.
OSD copy = OSDParser.DeserializeLLSDXml(OSDParser.SerializeLLSDXmlString(m_features));
return (OSDMap)copy;
}
private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod, UUID agentID)
{
// m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request");
OSDMap copy = DeepCopy();
SimulatorFeaturesRequestDelegate handlerOnSimulatorFeaturesRequest = OnSimulatorFeaturesRequest;
if (handlerOnSimulatorFeaturesRequest != null)
handlerOnSimulatorFeaturesRequest(agentID, ref copy);
//Send back data
Hashtable responsedata = new Hashtable();
responsedata["int_response_code"] = 200;
responsedata["content_type"] = "text/plain";
responsedata["keepalive"] = false;
lock (m_features)
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(m_features);
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(copy);
return responsedata;
}

View File

@ -190,8 +190,15 @@ namespace OpenSim.Region.ClientStack.Linden
{
if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
{
cacheItems[i].TextureID =
textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID;
Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
if (face == null)
{
textureEntry.CreateFace(cacheItems[i].TextureIndex);
textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
AppearanceManager.DEFAULT_AVATAR_TEXTURE;
continue;
}
cacheItems[i].TextureID =face.TextureID;
if (m_scene.AssetService != null)
cacheItems[i].TextureAsset =
m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
@ -213,8 +220,16 @@ namespace OpenSim.Region.ClientStack.Linden
{
if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
{
Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
if (face == null)
{
textureEntry.CreateFace(cacheItems[i].TextureIndex);
textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
AppearanceManager.DEFAULT_AVATAR_TEXTURE;
continue;
}
cacheItems[i].TextureID =
textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID;
face.TextureID;
}
else
{

View File

@ -39,10 +39,13 @@ using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Framework.Capabilities;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OpenSim.Capabilities.Handlers;
using OpenSim.Framework.Monitoring;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Region.ClientStack.Linden
{
@ -52,11 +55,13 @@ namespace OpenSim.Region.ClientStack.Linden
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebFetchInvDescModule")]
public class WebFetchInvDescModule : INonSharedRegionModule
{
struct aPollRequest
class aPollRequest
{
public PollServiceInventoryEventArgs thepoll;
public UUID reqID;
public Hashtable request;
public ScenePresence presence;
public List<UUID> folders;
}
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -71,8 +76,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
private static Thread[] m_workerThreads = null;
private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
new OpenMetaverse.BlockingQueue<aPollRequest>();
private static DoubleQueue<aPollRequest> m_queue =
new DoubleQueue<aPollRequest>();
#region ISharedRegionModule Members
@ -143,12 +148,18 @@ namespace OpenSim.Region.ClientStack.Linden
private class PollServiceInventoryEventArgs : PollServiceEventArgs
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Dictionary<UUID, Hashtable> responses =
new Dictionary<UUID, Hashtable>();
public PollServiceInventoryEventArgs(UUID pId) :
private Scene m_scene;
public PollServiceInventoryEventArgs(Scene scene, UUID pId) :
base(null, null, null, null, pId, int.MaxValue)
{
m_scene = scene;
HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); };
GetEvents = (x, y) =>
{
@ -167,12 +178,68 @@ namespace OpenSim.Region.ClientStack.Linden
Request = (x, y) =>
{
ScenePresence sp = m_scene.GetScenePresence(Id);
if (sp == null)
{
m_log.ErrorFormat("[INVENTORY]: Unable to find ScenePresence for {0}", Id);
return;
}
aPollRequest reqinfo = new aPollRequest();
reqinfo.thepoll = this;
reqinfo.reqID = x;
reqinfo.request = y;
reqinfo.presence = sp;
reqinfo.folders = new List<UUID>();
m_queue.Enqueue(reqinfo);
// Decode the request here
string request = y["body"].ToString();
request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
Hashtable hash = new Hashtable();
try
{
hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
}
catch (LLSD.LLSDParseException e)
{
m_log.ErrorFormat("[INVENTORY]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
m_log.Error("Request: " + request);
return;
}
catch (System.Xml.XmlException)
{
m_log.ErrorFormat("[INVENTORY]: XML Format error");
}
ArrayList foldersrequested = (ArrayList)hash["folders"];
bool highPriority = false;
for (int i = 0; i < foldersrequested.Count; i++)
{
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
string folder = inventoryhash["folder_id"].ToString();
UUID folderID;
if (UUID.TryParse(folder, out folderID))
{
if (!reqinfo.folders.Contains(folderID))
{
if (sp.COF != UUID.Zero && sp.COF == folderID)
highPriority = true;
reqinfo.folders.Add(folderID);
}
}
}
if (highPriority)
m_queue.EnqueueHigh(reqinfo);
else
m_queue.EnqueueLow(reqinfo);
};
NoEvents = (x, y) =>
@ -208,7 +275,7 @@ namespace OpenSim.Region.ClientStack.Linden
response["reusecontext"] = false;
response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(
requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
lock (responses)
responses[requestID] = response;
@ -220,7 +287,7 @@ namespace OpenSim.Region.ClientStack.Linden
string capUrl = "/CAPS/" + UUID.Random() + "/";
// Register this as a poll service
PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID);
PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, agentID);
args.Type = PollServiceEventArgs.EventType.Inventory;
MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);

View File

@ -2654,7 +2654,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
byte physshapetype = part.PhysicsShapeType;
float density = part.Density;
float friction = part.Friction;
float bounce = part.Bounciness;
float bounce = part.Restitution;
float gravmod = part.GravityModifier;
eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
@ -3893,6 +3893,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
part.Shape.LightEntry = false;
}
}
if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
{
// Ensure that mesh has at least 8 valid faces
part.Shape.ProfileBegin = 12500;
part.Shape.ProfileEnd = 0;
part.Shape.ProfileHollow = 27500;
}
}
++updatesThisCall;
@ -4952,6 +4960,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
rotation = part.RotationOffset * presence.Rotation;
}
angularVelocity = Vector3.Zero;
}
else
{
angularVelocity = presence.AngularVelocity;
rotation = presence.Rotation;
}
attachPoint = 0;
@ -4963,9 +4977,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// in that direction, even though we don't model this on the server. Implementing this in the future
// may improve movement smoothness.
// acceleration = new Vector3(1, 0, 0);
angularVelocity = Vector3.Zero;
if (sendTexture)
textureEntry = presence.Appearance.Texture.GetBytes();
else

View File

@ -1903,112 +1903,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
}
internal class DoubleQueue<T> where T:class
{
private Queue<T> m_lowQueue = new Queue<T>();
private Queue<T> m_highQueue = new Queue<T>();
private object m_syncRoot = new object();
private Semaphore m_s = new Semaphore(0, 1);
public DoubleQueue()
{
}
public virtual int Count
{
get { return m_highQueue.Count + m_lowQueue.Count; }
}
public virtual void Enqueue(T data)
{
Enqueue(m_lowQueue, data);
}
public virtual void EnqueueLow(T data)
{
Enqueue(m_lowQueue, data);
}
public virtual void EnqueueHigh(T data)
{
Enqueue(m_highQueue, data);
}
private void Enqueue(Queue<T> q, T data)
{
lock (m_syncRoot)
{
m_lowQueue.Enqueue(data);
m_s.WaitOne(0);
m_s.Release();
}
}
public virtual T Dequeue()
{
return Dequeue(Timeout.Infinite);
}
public virtual T Dequeue(int tmo)
{
return Dequeue(TimeSpan.FromMilliseconds(tmo));
}
public virtual T Dequeue(TimeSpan wait)
{
T res = null;
if (!Dequeue(wait, ref res))
return null;
return res;
}
public bool Dequeue(int timeout, ref T res)
{
return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
}
public bool Dequeue(TimeSpan wait, ref T res)
{
if (!m_s.WaitOne(wait))
return false;
lock (m_syncRoot)
{
if (m_highQueue.Count > 0)
res = m_highQueue.Dequeue();
else
res = m_lowQueue.Dequeue();
if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
return true;
try
{
m_s.Release();
}
catch
{
}
return true;
}
}
public virtual void Clear()
{
lock (m_syncRoot)
{
// Make sure sem count is 0
m_s.WaitOne(0);
m_lowQueue.Clear();
m_highQueue.Clear();
}
}
}
}

View File

@ -260,10 +260,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
{
CompleteTaskItemUpdate(m_updateTaskItemData);
}
// else if (m_storeLocal)
// {
// m_Scene.AssetService.Store(m_asset);
// }
else if (m_asset.Local)
{
m_Scene.AssetService.Store(m_asset);
}
}
m_log.DebugFormat(
@ -339,7 +339,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
// to avoid a race condition when the appearance module retrieves the item to set the asset id in
// the AvatarAppearance structure.
item.AssetID = m_asset.FullID;
m_Scene.InventoryService.UpdateItem(item);
if (item.AssetID != UUID.Zero)
m_Scene.InventoryService.UpdateItem(item);
if (m_uploadState == UploadState.Complete)
{
@ -390,6 +391,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
// m_asset.FullID, item.Name, ourClient.Name);
m_Scene.AssetService.Store(m_asset);
if (m_asset.FullID != UUID.Zero)
{
item.AssetID = m_asset.FullID;
m_Scene.InventoryService.UpdateItem(item);
}
m_transactions.RemoveXferUploader(m_transactionID);
}

View File

@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Asset
AssetBase asset = null;
string filename = GetFileName(id);
if (File.Exists(filename))
while (File.Exists(filename))
{
FileStream stream = null;
try
@ -380,6 +380,8 @@ namespace OpenSim.Region.CoreModules.Asset
asset = (AssetBase)bformatter.Deserialize(stream);
m_DiskHits++;
break;
}
catch (System.Runtime.Serialization.SerializationException e)
{
@ -392,12 +394,24 @@ namespace OpenSim.Region.CoreModules.Asset
// {different version of AssetBase} -- we should attempt to
// delete it and re-cache
File.Delete(filename);
break;
}
catch (IOException e)
{
// This is a sharing violation: File exists but can't be opened because it's
// being written
Thread.Sleep(100);
continue;
}
catch (Exception e)
{
m_log.ErrorFormat(
"[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
filename, id, e.Message, e.StackTrace);
break;
}
finally
{

View File

@ -236,9 +236,9 @@ 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);
RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null, true);
else
RezSingleAttachmentFromInventory(sp, attach.ItemID, p, d);
RezSingleAttachmentFromInventory(sp, attach.ItemID, p | (uint)0x80, d);
}
catch (Exception e)
{
@ -284,12 +284,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
sp.ClearAttachments();
}
public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append)
{
if (!Enabled)
return false;
if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp))
if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, append))
{
m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
return true;
@ -298,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return false;
}
private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append)
{
lock (sp.AttachmentsSyncLock)
{
@ -326,10 +326,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
Vector3 attachPos = group.AbsolutePosition;
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim
attachmentPt &= 0x7f;
// If the attachment point isn't the same as the one previously used
// set it's offset position = 0 so that it appears on the attachment point
// and not in a weird location somewhere unknown.
@ -375,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
group.AbsolutePosition = attachPos;
if (sp.PresenceType != PresenceType.Npc)
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp);
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append);
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
}
@ -383,21 +379,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return true;
}
private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp)
private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp, bool append)
{
// Remove any previous attachments
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
// At the moment we can only deal with a single attachment
if (attachments.Count != 0)
// If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
while (attachments.Count >= 5)
{
if (attachments[0].FromItemID != UUID.Zero)
DetachSingleAttachmentToInvInternal(sp, attachments[0]);
// Error logging commented because UUID.Zero now means temp attachment
// else
// m_log.WarnFormat(
// "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
// attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
attachments.RemoveAt(0);
}
// If we're not appending, remove the rest as well
if (attachments.Count != 0 && !append)
{
foreach (SceneObjectGroup g in attachments)
{
if (g.FromItemID != UUID.Zero)
DetachSingleAttachmentToInvInternal(sp, g);
}
}
// Add the new attachment to inventory if we don't already have it.
@ -407,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (newAttachmentItemID == UUID.Zero)
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
}
}
@ -425,8 +426,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}",
// (AttachmentPoint)AttachmentPt, itemID, sp.Name);
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim
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).
@ -455,7 +455,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return null;
}
return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc);
return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc, append);
}
public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@ -847,7 +847,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
}
protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc)
IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc, bool append)
{
if (m_invAccessModule == null)
return null;
@ -885,7 +885,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// This will throw if the attachment fails
try
{
AttachObjectInternal(sp, objatt, attachmentPt, false, false, false);
AttachObjectInternal(sp, objatt, attachmentPt, false, false, false, append);
}
catch (Exception e)
{
@ -936,7 +936,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// <param name="AttachmentPt"></param>
/// <param name="itemID"></param>
/// <param name="att"></param>
private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att, bool append)
{
// m_log.DebugFormat(
// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
@ -959,7 +959,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (item == null)
return;
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
int attFlag = append ? 0x80 : 0;
bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID);
if (changed && m_scene.AvatarFactory != null)
{
// m_log.DebugFormat(
@ -1043,12 +1044,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return;
}
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim
bool append = (AttachmentPt & 0x80) != 0;
AttachmentPt &= 0x7f;
// Calls attach with a Zero position
if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false))
if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false, append))
{
// m_log.Debug(
// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId

View File

@ -197,7 +197,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);
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false);
// Check status on scene presence
Assert.That(sp.HasAttachments(), Is.True);
@ -254,7 +254,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);
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false);
Assert.That(sp.HasAttachments(), Is.False);
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));

View File

@ -674,26 +674,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
{
IInventoryService invService = m_scene.InventoryService;
bool resetwearable = false;
if (invService.GetRootFolder(userID) != null)
{
for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
{
for (int j = 0; j < appearance.Wearables[i].Count; j++)
{
// Check if the default wearables are not set
if (appearance.Wearables[i][j].ItemID == UUID.Zero)
continue;
{
switch ((WearableType) i)
{
case WearableType.Eyes:
case WearableType.Hair:
case WearableType.Shape:
case WearableType.Skin:
//case WearableType.Underpants:
TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
resetwearable = true;
m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values.");
resetwearable = true;
break;
// Ignore ruth's assets
}
continue;
}
// Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1
if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
continue;
{
switch ((WearableType)i)
{
case WearableType.Eyes:
case WearableType.Hair:
case WearableType.Shape:
case WearableType.Skin:
//case WearableType.Underpants:
TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i);
resetwearable = true;
break;
}
continue;
}
InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
baseItem = invService.GetItem(baseItem);
if (baseItem != null)
{
appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID);
int unmodifiedWearableIndexForClosure = i;
m_scene.AssetService.Get(baseItem.AssetID.ToString(), this,
delegate(string x, object y, AssetBase z)
{
if (z == null)
{
TryAndRepairBrokenWearable(
(WearableType)unmodifiedWearableIndexForClosure, invService,
userID, appearance);
}
});
}
else
{
@ -701,17 +745,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
"[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
appearance.Wearables[i][j].ItemID, (WearableType)i);
appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID);
TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
resetwearable = true;
}
}
}
// I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
if (appearance.Wearables[(int) WearableType.Eyes] == null)
{
m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes));
TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
resetwearable = true;
}
else
{
if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero)
{
m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}",
appearance.Wearables[(int) WearableType.Eyes][0].ItemID,
appearance.Wearables[(int) WearableType.Eyes][0].AssetID);
TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
resetwearable = true;
}
}
// I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
if (appearance.Wearables[(int)WearableType.Shape] == null)
{
m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape));
TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance);
resetwearable = true;
}
else
{
if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero)
{
m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}",
appearance.Wearables[(int)WearableType.Shape][0].ItemID,
appearance.Wearables[(int)WearableType.Shape][0].AssetID);
TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance);
resetwearable = true;
}
}
// I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
if (appearance.Wearables[(int)WearableType.Hair] == null)
{
m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair));
TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance);
resetwearable = true;
}
else
{
if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero)
{
m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}",
appearance.Wearables[(int)WearableType.Hair][0].ItemID,
appearance.Wearables[(int)WearableType.Hair][0].AssetID);
TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance);
resetwearable = true;
}
}
// I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
if (appearance.Wearables[(int)WearableType.Skin] == null)
{
m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin));
TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance);
resetwearable = true;
}
else
{
if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero)
{
m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}",
appearance.Wearables[(int)WearableType.Skin][0].ItemID,
appearance.Wearables[(int)WearableType.Skin][0].AssetID);
TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance);
resetwearable = true;
}
}
if (resetwearable)
{
ScenePresence presence = null;
if (m_scene.TryGetScenePresence(userID, out presence))
{
presence.ControllingClient.SendWearables(presence.Appearance.Wearables,
presence.Appearance.Serial++);
}
}
}
else
{
m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
}
}
private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance)
{
UUID defaultwearable = GetDefaultItem(type);
if (defaultwearable != UUID.Zero)
{
UUID newInvItem = UUID.Random();
InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID)
{
AssetID =
defaultwearable,
AssetType
=
(int)
AssetType
.Bodypart,
CreatorId
=
userID
.ToString
(),
//InvType = (int)InventoryType.Wearable,
Description
=
"Failed Wearable Replacement",
Folder =
invService
.GetFolderForType
(userID,
AssetType
.Bodypart)
.ID,
Flags = (uint) type,
Name = Enum.GetName(typeof (WearableType), type),
BasePermissions = (uint) PermissionMask.Copy,
CurrentPermissions = (uint) PermissionMask.Copy,
EveryOnePermissions = (uint) PermissionMask.Copy,
GroupPermissions = (uint) PermissionMask.Copy,
NextPermissions = (uint) PermissionMask.Copy
};
invService.AddItem(itembase);
UUID LinkInvItem = UUID.Random();
itembase = new InventoryItemBase(LinkInvItem, userID)
{
AssetID =
newInvItem,
AssetType
=
(int)
AssetType
.Link,
CreatorId
=
userID
.ToString
(),
InvType = (int) InventoryType.Wearable,
Description
=
"Failed Wearable Replacement",
Folder =
invService
.GetFolderForType
(userID,
AssetType
.CurrentOutfitFolder)
.ID,
Flags = (uint) type,
Name = Enum.GetName(typeof (WearableType), type),
BasePermissions = (uint) PermissionMask.Copy,
CurrentPermissions = (uint) PermissionMask.Copy,
EveryOnePermissions = (uint) PermissionMask.Copy,
GroupPermissions = (uint) PermissionMask.Copy,
NextPermissions = (uint) PermissionMask.Copy
};
invService.AddItem(itembase);
appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type));
ScenePresence presence = null;
if (m_scene.TryGetScenePresence(userID, out presence))
{
m_scene.SendInventoryUpdate(presence.ControllingClient,
invService.GetFolderForType(userID,
AssetType
.CurrentOutfitFolder),
false, true);
}
}
}
private UUID GetDefaultItem(WearableType wearable)
{
// These are ruth
UUID ret = UUID.Zero;
switch (wearable)
{
case WearableType.Eyes:
ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7");
break;
case WearableType.Hair:
ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66");
break;
case WearableType.Pants:
ret = new UUID("00000000-38f9-1111-024e-222222111120");
break;
case WearableType.Shape:
ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73");
break;
case WearableType.Shirt:
ret = new UUID("00000000-38f9-1111-024e-222222111110");
break;
case WearableType.Skin:
ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb");
break;
case WearableType.Undershirt:
ret = new UUID("16499ebb-3208-ec27-2def-481881728f47");
break;
case WearableType.Underpants:
ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d");
break;
}
return ret;
}
#endregion
#region Client Event Handlers

View File

@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.Framework
/// <summary>
/// Each agent has its own capabilities handler.
/// </summary>
protected Dictionary<UUID, Caps> m_capsObjects = new Dictionary<UUID, Caps>();
protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>();
protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>();
protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds
@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.Framework
get { return null; }
}
public void CreateCaps(UUID agentId)
public void CreateCaps(UUID agentId, uint circuitCode)
{
int flags = m_scene.GetUserFlags(agentId);
if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
@ -108,9 +108,9 @@ namespace OpenSim.Region.CoreModules.Framework
String capsObjectPath = GetCapsPath(agentId);
if (m_capsObjects.ContainsKey(agentId))
if (m_capsObjects.ContainsKey(circuitCode))
{
Caps oldCaps = m_capsObjects[agentId];
Caps oldCaps = m_capsObjects[circuitCode];
m_log.DebugFormat(
"[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ",
@ -125,12 +125,12 @@ namespace OpenSim.Region.CoreModules.Framework
(MainServer.Instance == null) ? 0: MainServer.Instance.Port,
capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
m_capsObjects[agentId] = caps;
m_capsObjects[circuitCode] = caps;
m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps);
}
public void RemoveCaps(UUID agentId)
public void RemoveCaps(UUID agentId, uint circuitCode)
{
if (childrenSeeds.ContainsKey(agentId))
{
@ -139,11 +139,11 @@ namespace OpenSim.Region.CoreModules.Framework
lock (m_capsObjects)
{
if (m_capsObjects.ContainsKey(agentId))
if (m_capsObjects.ContainsKey(circuitCode))
{
m_capsObjects[agentId].DeregisterHandlers();
m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]);
m_capsObjects.Remove(agentId);
m_capsObjects[circuitCode].DeregisterHandlers();
m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[circuitCode]);
m_capsObjects.Remove(circuitCode);
}
else
{
@ -154,19 +154,30 @@ namespace OpenSim.Region.CoreModules.Framework
}
}
public Caps GetCapsForUser(UUID agentId)
public Caps GetCapsForUser(uint circuitCode)
{
lock (m_capsObjects)
{
if (m_capsObjects.ContainsKey(agentId))
if (m_capsObjects.ContainsKey(circuitCode))
{
return m_capsObjects[agentId];
return m_capsObjects[circuitCode];
}
}
return null;
}
public void ActivateCaps(uint circuitCode)
{
lock (m_capsObjects)
{
if (m_capsObjects.ContainsKey(circuitCode))
{
m_capsObjects[circuitCode].Activate();
}
}
}
public void SetAgentCapsSeeds(AgentCircuitData agent)
{
capsPaths[agent.AgentID] = agent.CapsPath;
@ -237,9 +248,9 @@ namespace OpenSim.Region.CoreModules.Framework
StringBuilder caps = new StringBuilder();
caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects)
foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
{
caps.AppendFormat("** User {0}:\n", kvp.Key);
caps.AppendFormat("** Circuit {0}:\n", kvp.Key);
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); )
{

View File

@ -150,7 +150,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
client.OnTeleportHomeRequest += TriggerTeleportHome;
client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
client.OnTeleportCancel += TeleportCancel;
}
public virtual void Close() {}
@ -995,11 +994,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return neighbourRegion;
}
private void TeleportCancel(IClientAPI remoteClient)
{
m_entityTransferStateMachine.ResetFromTransit(remoteClient.AgentId);
}
public bool Cross(ScenePresence agent, bool isFlying)
{
uint x;

View File

@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
public string url;
public UUID urlcode;
public Dictionary<UUID, RequestData> requests;
public bool isSsl;
}
public class RequestData
@ -184,6 +185,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
urlData.engine = engine;
urlData.url = url;
urlData.urlcode = urlcode;
urlData.isSsl = false;
urlData.requests = new Dictionary<UUID, RequestData>();
m_UrlMap[url] = urlData;
@ -229,6 +231,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
urlData.engine = engine;
urlData.url = url;
urlData.urlcode = urlcode;
urlData.isSsl = true;
urlData.requests = new Dictionary<UUID, RequestData>();
@ -394,7 +397,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
private void RemoveUrl(UrlData data)
{
m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
if (data.isSsl)
m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/");
else
m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
}
private Hashtable NoEvents(UUID requestID, UUID sessionID)

View File

@ -262,6 +262,8 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
return "modInvokeR";
else if (sid.ReturnType == typeof(object[]))
return "modInvokeL";
else if (sid.ReturnType == typeof(void))
return "modInvokeN";
m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
}

View File

@ -84,7 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="AttachmentPt"></param>
/// <param name="silent"></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 AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool temp, bool append);
/// <summary>
/// Rez an attachment from user inventory and change inventory status to match.

View File

@ -40,19 +40,19 @@ namespace OpenSim.Region.Framework.Interfaces
/// </summary>
/// <param name="agentId"></param>
/// <param name="capsObjectPath"></param>
void CreateCaps(UUID agentId);
void CreateCaps(UUID agentId, uint circuitCode);
/// <summary>
/// Remove the caps handler for a given agent.
/// </summary>
/// <param name="agentId"></param>
void RemoveCaps(UUID agentId);
void RemoveCaps(UUID agentId, uint circuitCode);
/// <summary>
/// Will return null if the agent doesn't have a caps handler registered
/// </summary>
/// <param name="agentId"></param>
Caps GetCapsForUser(UUID agentId);
Caps GetCapsForUser(uint circuitCode);
void SetAgentCapsSeeds(AgentCircuitData agent);
@ -65,5 +65,7 @@ namespace OpenSim.Region.Framework.Interfaces
void DropChildSeed(UUID agentID, ulong handle);
string GetCapsPath(UUID agentId);
void ActivateCaps(uint circuitCode);
}
}

View File

@ -26,18 +26,22 @@
*/
using System;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Region.Framework.Interfaces
{
public delegate void SimulatorFeaturesRequestDelegate(UUID agentID, ref OSDMap features);
/// <summary>
/// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability.
/// </summary>
public interface ISimulatorFeaturesModule
{
event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
void AddFeature(string name, OSD value);
bool RemoveFeature(string name);
bool TryGetFeature(string name, out OSD value);
OSDMap GetFeatures();
}
}
}

View File

@ -22,6 +22,115 @@ using log4net;
namespace OpenSim.Region.Framework.Scenes
{
public class KeyframeTimer
{
private static Dictionary<Scene, KeyframeTimer>m_timers =
new Dictionary<Scene, KeyframeTimer>();
private Timer m_timer;
private Dictionary<KeyframeMotion, object> m_motions = new Dictionary<KeyframeMotion, object>();
private object m_lockObject = new object();
private object m_timerLock = new object();
private const double m_tickDuration = 50.0;
private Scene m_scene;
public double TickDuration
{
get { return m_tickDuration; }
}
public KeyframeTimer(Scene scene)
{
m_timer = new Timer();
m_timer.Interval = TickDuration;
m_timer.AutoReset = true;
m_timer.Elapsed += OnTimer;
m_scene = scene;
m_timer.Start();
}
private void OnTimer(object sender, ElapsedEventArgs ea)
{
if (!Monitor.TryEnter(m_timerLock))
return;
try
{
List<KeyframeMotion> motions;
lock (m_lockObject)
{
motions = new List<KeyframeMotion>(m_motions.Keys);
}
foreach (KeyframeMotion m in motions)
{
try
{
m.OnTimer(TickDuration);
}
catch (Exception inner)
{
// Don't stop processing
}
}
}
catch (Exception e)
{
// Keep running no matter what
}
finally
{
Monitor.Exit(m_timerLock);
}
}
public static void Add(KeyframeMotion motion)
{
KeyframeTimer timer;
if (motion.Scene == null)
return;
lock (m_timers)
{
if (!m_timers.TryGetValue(motion.Scene, out timer))
{
timer = new KeyframeTimer(motion.Scene);
m_timers[motion.Scene] = timer;
}
}
lock (timer.m_lockObject)
{
timer.m_motions[motion] = null;
}
}
public static void Remove(KeyframeMotion motion)
{
KeyframeTimer timer;
if (motion.Scene == null)
return;
lock (m_timers)
{
if (!m_timers.TryGetValue(motion.Scene, out timer))
{
return;
}
}
lock (timer.m_lockObject)
{
timer.m_motions.Remove(motion);
}
}
}
[Serializable]
public class KeyframeMotion
{
@ -63,18 +172,6 @@ namespace OpenSim.Region.Framework.Scenes
private Keyframe[] m_keyframes;
[NonSerialized()]
protected Timer m_timer = null;
// timer lock
[NonSerialized()]
private object m_onTimerLock;
// timer overrun detect
// prevents overlap or timer events threads frozen on the lock
[NonSerialized()]
private bool m_inOnTimer;
// skip timer events.
//timer.stop doesn't assure there aren't event threads still being fired
[NonSerialized()]
@ -97,12 +194,21 @@ namespace OpenSim.Region.Framework.Scenes
private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation;
private bool m_running = false;
[NonSerialized()]
private bool m_selected = false;
private int m_iterations = 0;
private const double timerInterval = 50.0;
private int m_skipLoops = 0;
[NonSerialized()]
private Scene m_scene;
public Scene Scene
{
get { return m_scene; }
}
public DataFormat Data
{
@ -139,31 +245,16 @@ namespace OpenSim.Region.Framework.Scenes
private void StartTimer()
{
if (m_timer == null)
return;
KeyframeTimer.Add(this);
m_timerStopped = false;
m_timer.Start();
}
private void StopTimer()
{
if (m_timer == null || m_timerStopped)
return;
m_timerStopped = true;
m_timer.Stop();
KeyframeTimer.Remove(this);
}
private void RemoveTimer()
{
if (m_timer == null)
return;
m_timerStopped = true;
m_timer.Stop();
m_timer.Elapsed -= OnTimer;
m_timer = null;
}
public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
{
KeyframeMotion newMotion = null;
@ -177,12 +268,15 @@ namespace OpenSim.Region.Framework.Scenes
newMotion.m_group = grp;
if (grp != null && grp.IsSelected)
newMotion.m_selected = true;
if (grp != null)
{
newMotion.m_scene = grp.Scene;
if (grp.IsSelected)
newMotion.m_selected = true;
}
newMotion.m_onTimerLock = new object();
newMotion.m_timerStopped = false;
newMotion.m_inOnTimer = false;
newMotion.m_running = true;
newMotion.m_isCrossing = false;
newMotion.m_waitingCrossing = false;
}
@ -196,37 +290,36 @@ namespace OpenSim.Region.Framework.Scenes
public void UpdateSceneObject(SceneObjectGroup grp)
{
// lock (m_onTimerLock)
m_isCrossing = false;
m_waitingCrossing = false;
StopTimer();
if (grp == null)
return;
m_group = grp;
m_scene = grp.Scene;
Vector3 grppos = grp.AbsolutePosition;
Vector3 offset = grppos - m_serializedPosition;
// avoid doing it more than once
// current this will happen draging a prim to other region
m_serializedPosition = grppos;
m_basePosition += offset;
m_currentFrame.Position += offset;
m_nextPosition += offset;
for (int i = 0; i < m_frames.Count; i++)
{
m_isCrossing = false;
m_waitingCrossing = false;
StopTimer();
if (grp == null)
return;
m_group = grp;
Vector3 grppos = grp.AbsolutePosition;
Vector3 offset = grppos - m_serializedPosition;
// avoid doing it more than once
// current this will happen draging a prim to other region
m_serializedPosition = grppos;
m_basePosition += offset;
m_currentFrame.Position += offset;
m_nextPosition += offset;
for (int i = 0; i < m_frames.Count; i++)
{
Keyframe k = m_frames[i];
k.Position += offset;
m_frames[i]=k;
}
if (m_running)
Start();
Keyframe k = m_frames[i];
k.Position += offset;
m_frames[i]=k;
}
if (m_running)
Start();
}
public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
@ -239,11 +332,10 @@ namespace OpenSim.Region.Framework.Scenes
{
m_basePosition = grp.AbsolutePosition;
m_baseRotation = grp.GroupRotation;
m_scene = grp.Scene;
}
m_onTimerLock = new object();
m_timerStopped = true;
m_inOnTimer = false;
m_isCrossing = false;
m_waitingCrossing = false;
}
@ -260,6 +352,7 @@ namespace OpenSim.Region.Framework.Scenes
KeyframeMotion newmotion = new KeyframeMotion(null, m_mode, m_data);
newmotion.m_group = newgrp;
newmotion.m_scene = newgrp.Scene;
if (m_keyframes != null)
{
@ -296,7 +389,7 @@ namespace OpenSim.Region.Framework.Scenes
public void Delete()
{
m_running = false;
RemoveTimer();
StopTimer();
m_isCrossing = false;
m_waitingCrossing = false;
m_frames.Clear();
@ -309,27 +402,13 @@ namespace OpenSim.Region.Framework.Scenes
m_waitingCrossing = false;
if (m_keyframes != null && m_group != null && m_keyframes.Length > 0)
{
if (m_timer == null)
{
m_timer = new Timer();
m_timer.Interval = timerInterval;
m_timer.AutoReset = true;
m_timer.Elapsed += OnTimer;
}
else
{
StopTimer();
m_timer.Interval = timerInterval;
}
m_inOnTimer = false;
StartTimer();
m_running = true;
}
else
{
m_running = false;
RemoveTimer();
StopTimer();
}
}
@ -339,7 +418,7 @@ namespace OpenSim.Region.Framework.Scenes
m_isCrossing = false;
m_waitingCrossing = false;
RemoveTimer();
StopTimer();
m_basePosition = m_group.AbsolutePosition;
m_baseRotation = m_group.GroupRotation;
@ -354,7 +433,7 @@ namespace OpenSim.Region.Framework.Scenes
public void Pause()
{
m_running = false;
RemoveTimer();
StopTimer();
m_group.RootPart.Velocity = Vector3.Zero;
m_group.RootPart.AngularVelocity = Vector3.Zero;
@ -377,15 +456,11 @@ namespace OpenSim.Region.Framework.Scenes
int start = 0;
int end = m_keyframes.Length;
// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
// end = m_keyframes.Length - 1;
if (direction < 0)
{
start = m_keyframes.Length - 1;
end = -1;
// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
// end = 0;
}
for (int i = start; i != end ; i += direction)
@ -463,189 +538,172 @@ namespace OpenSim.Region.Framework.Scenes
}
}
protected void OnTimer(object sender, ElapsedEventArgs e)
public void OnTimer(double tickDuration)
{
if (m_timerStopped) // trap events still in air even after a timer.stop
return;
if (m_inOnTimer) // don't let overruns to happen
if (m_skipLoops > 0)
{
m_log.Warn("[KeyFrame]: timer overrun");
m_skipLoops--;
return;
}
if (m_timerStopped) // trap events still in air even after a timer.stop
return;
if (m_group == null)
return;
lock (m_onTimerLock)
bool update = false;
if (m_selected)
{
m_inOnTimer = true;
bool update = false;
try
if (m_group.RootPart.Velocity != Vector3.Zero)
{
if (m_selected)
{
if (m_group.RootPart.Velocity != Vector3.Zero)
{
m_group.RootPart.Velocity = Vector3.Zero;
m_group.SendGroupRootTerseUpdate();
// m_group.RootPart.ScheduleTerseUpdate();
m_group.RootPart.Velocity = Vector3.Zero;
m_group.SendGroupRootTerseUpdate();
}
m_inOnTimer = false;
return;
}
return;
}
if (m_isCrossing)
{
// if crossing and timer running then cross failed
// wait some time then
// retry to set the position that evtually caused the outbound
// if still outside region this will call startCrossing below
m_isCrossing = false;
m_group.AbsolutePosition = m_nextPosition;
if (!m_isCrossing)
{
StopTimer();
StartTimer();
}
return;
}
if (m_frames.Count == 0)
{
GetNextList();
if (m_frames.Count == 0)
{
Stop();
Scene scene = m_group.Scene;
IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
foreach (IScriptModule m in scriptModules)
{
if (m == null)
continue;
m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
}
if (m_isCrossing)
return;
}
m_currentFrame = m_frames[0];
m_currentFrame.TimeMS += (int)tickDuration;
//force a update on a keyframe transition
update = true;
}
m_currentFrame.TimeMS -= (int)tickDuration;
// Do the frame processing
double steps = (double)m_currentFrame.TimeMS / tickDuration;
if (steps <= 0.0)
{
m_group.RootPart.Velocity = Vector3.Zero;
m_group.RootPart.AngularVelocity = Vector3.Zero;
m_nextPosition = (Vector3)m_currentFrame.Position;
m_group.AbsolutePosition = m_nextPosition;
// we are sending imediate updates, no doing force a extra terseUpdate
// m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
m_frames.RemoveAt(0);
if (m_frames.Count > 0)
m_currentFrame = m_frames[0];
update = true;
}
else
{
float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
Vector3 motionThisFrame = v / (float)steps;
v = v * 1000 / m_currentFrame.TimeMS;
if (Vector3.Mag(motionThisFrame) >= 0.05f)
{
// m_group.AbsolutePosition += motionThisFrame;
m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
m_group.AbsolutePosition = m_nextPosition;
m_group.RootPart.Velocity = v;
update = true;
}
if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
{
Quaternion current = m_group.GroupRotation;
Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
step.Normalize();
/* use simpler change detection
* float angle = 0;
float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
float aa_bb = aa * bb;
if (aa_bb == 0)
{
// if crossing and timer running then cross failed
// wait some time then
// retry to set the position that evtually caused the outbound
// if still outside region this will call startCrossing below
m_isCrossing = false;
m_group.AbsolutePosition = m_nextPosition;
if (!m_isCrossing)
{
StopTimer();
m_timer.Interval = timerInterval;
StartTimer();
}
m_inOnTimer = false;
return;
}
if (m_frames.Count == 0)
{
GetNextList();
if (m_frames.Count == 0)
{
Stop();
m_inOnTimer = false;
return;
}
m_currentFrame = m_frames[0];
m_currentFrame.TimeMS += (int)timerInterval;
//force a update on a keyframe transition
update = true;
}
m_currentFrame.TimeMS -= (int)timerInterval;
// Do the frame processing
double steps = (double)m_currentFrame.TimeMS / timerInterval;
if (steps <= 0.0)
{
m_group.RootPart.Velocity = Vector3.Zero;
m_group.RootPart.AngularVelocity = Vector3.Zero;
m_nextPosition = (Vector3)m_currentFrame.Position;
m_group.AbsolutePosition = m_nextPosition;
// we are sending imediate updates, no doing force a extra terseUpdate
// m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
m_frames.RemoveAt(0);
if (m_frames.Count > 0)
m_currentFrame = m_frames[0];
update = true;
angle = 0;
}
else
{
float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
float ab = current.X * step.X +
current.Y * step.Y +
current.Z * step.Z +
current.W * step.W;
float q = (ab * ab) / aa_bb;
Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
Vector3 motionThisFrame = v / (float)steps;
v = v * 1000 / m_currentFrame.TimeMS;
if (Vector3.Mag(motionThisFrame) >= 0.05f)
if (q > 1.0f)
{
// m_group.AbsolutePosition += motionThisFrame;
m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
m_group.AbsolutePosition = m_nextPosition;
m_group.RootPart.Velocity = v;
update = true;
angle = 0;
}
if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
else
{
Quaternion current = m_group.GroupRotation;
Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
step.Normalize();
/* use simpler change detection
* float angle = 0;
float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
float aa_bb = aa * bb;
if (aa_bb == 0)
{
angle = 0;
}
else
{
float ab = current.X * step.X +
current.Y * step.Y +
current.Z * step.Z +
current.W * step.W;
float q = (ab * ab) / aa_bb;
if (q > 1.0f)
{
angle = 0;
}
else
{
angle = (float)Math.Acos(2 * q - 1);
}
}
if (angle > 0.01f)
*/
if(Math.Abs(step.X - current.X) > 0.001f
|| Math.Abs(step.Y - current.Y) > 0.001f
|| Math.Abs(step.Z - current.Z) > 0.001f)
// assuming w is a dependente var
{
// m_group.UpdateGroupRotationR(step);
m_group.RootPart.RotationOffset = step;
//m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
update = true;
}
angle = (float)Math.Acos(2 * q - 1);
}
}
if (update)
m_group.SendGroupRootTerseUpdate();
// m_group.RootPart.ScheduleTerseUpdate();
if (angle > 0.01f)
*/
if(Math.Abs(step.X - current.X) > 0.001f
|| Math.Abs(step.Y - current.Y) > 0.001f
|| Math.Abs(step.Z - current.Z) > 0.001f)
// assuming w is a dependente var
{
// m_group.UpdateGroupRotationR(step);
m_group.RootPart.RotationOffset = step;
//m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
update = true;
}
}
catch ( Exception ex)
{
// still happening sometimes
// lets try to see where
m_log.Warn("[KeyFrame]: timer overrun" + ex.Message);
}
}
finally
{
// make sure we do not let this frozen
m_inOnTimer = false;
}
if (update)
{
m_group.SendGroupRootTerseUpdate();
}
}
@ -677,7 +735,7 @@ namespace OpenSim.Region.Framework.Scenes
m_isCrossing = true;
m_waitingCrossing = true;
// to remove / retune to smoth crossings
// to remove / retune to smoth crossings
if (m_group.RootPart.Velocity != Vector3.Zero)
{
m_group.RootPart.Velocity = Vector3.Zero;
@ -696,9 +754,10 @@ namespace OpenSim.Region.Framework.Scenes
m_group.SendGroupRootTerseUpdate();
// m_group.RootPart.ScheduleTerseUpdate();
if (m_running && m_timer != null)
if (m_running)
{
m_timer.Interval = 60000;
StopTimer();
m_skipLoops = 1200; // 60 seconds
StartTimer();
}
}

View File

@ -401,17 +401,17 @@ namespace OpenSim.Region.Framework.Scenes
if (item.Owner != remoteClient.AgentId)
return;
if (UUID.Zero == transactionID)
{
item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
item.Name = itemUpd.Name;
item.Description = itemUpd.Description;
item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
item.Name = itemUpd.Name;
item.Description = itemUpd.Description;
// m_log.DebugFormat(
// "[USER INVENTORY]: itemUpd {0} {1} {2} {3}, item {4} {5} {6} {7}",
// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags,
// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions);
if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid
{
if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner;
item.NextPermissions = itemUpd.NextPermissions & item.BasePermissions;
@ -446,7 +446,8 @@ namespace OpenSim.Region.Framework.Scenes
InventoryService.UpdateItem(item);
}
else
if (UUID.Zero != transactionID)
{
if (AgentTransactionsModule != null)
{

View File

@ -2769,8 +2769,6 @@ namespace OpenSim.Region.Framework.Scenes
if (newPosition != Vector3.Zero)
newObject.RootPart.GroupPosition = newPosition;
if (newObject.RootPart.KeyframeMotion != null)
newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
if (!AddSceneObject(newObject))
{
@ -2798,6 +2796,9 @@ namespace OpenSim.Region.Framework.Scenes
// before we restart the scripts, or else some functions won't work.
newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
newObject.ResumeScripts();
if (newObject.RootPart.KeyframeMotion != null)
newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
}
// Do this as late as possible so that listeners have full access to the incoming object
@ -2865,7 +2866,7 @@ namespace OpenSim.Region.Framework.Scenes
RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
if (AttachmentsModule != null)
AttachmentsModule.AttachObject(sp, grp, 0, false, false, false);
AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
}
else
{
@ -2970,6 +2971,13 @@ namespace OpenSim.Region.Framework.Scenes
SubscribeToClientEvents(client);
sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
if (cof == null)
sp.COF = UUID.Zero;
else
sp.COF = cof.ID;
m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF);
m_eventManager.TriggerOnNewPresence(sp);
sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
@ -3615,7 +3623,7 @@ namespace OpenSim.Region.Framework.Scenes
// TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
// unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
if (closeChildAgents && CapsModule != null)
CapsModule.RemoveCaps(agentID);
CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
// // this method is doing is HORRIBLE!!!
@ -3846,20 +3854,36 @@ namespace OpenSim.Region.Framework.Scenes
return false;
}
ScenePresence sp = GetScenePresence(agent.AgentID);
if (sp != null && !sp.IsChildAgent)
// If we have noo presence here or if that presence is a zombie root
// presence that will be kicled, we need a new CAPS object.
if (sp == null || (sp != null && !sp.IsChildAgent))
{
// We have a zombie from a crashed session.
// Or the same user is trying to be root twice here, won't work.
// Kill it.
m_log.WarnFormat(
"[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
sp.Name, sp.UUID, RegionInfo.RegionName);
if (CapsModule != null)
{
lock (agent)
{
CapsModule.SetAgentCapsSeeds(agent);
CapsModule.CreateCaps(agent.AgentID, agent.circuitcode);
}
}
}
sp.ControllingClient.Close(true, true);
sp = null;
if (sp != null)
{
if (!sp.IsChildAgent)
{
// We have a zombie from a crashed session.
// Or the same user is trying to be root twice here, won't work.
// Kill it.
m_log.WarnFormat(
"[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
sp.Name, sp.UUID, RegionInfo.RegionName);
sp.ControllingClient.Close(true, true);
sp = null;
}
}
lock (agent)
@ -3900,7 +3924,9 @@ namespace OpenSim.Region.Framework.Scenes
if (vialogin || (!m_seeIntoBannedRegion))
{
if (!AuthorizeUser(agent, out reason))
{
return false;
}
}
}
catch (Exception e)
@ -3915,11 +3941,6 @@ namespace OpenSim.Region.Framework.Scenes
RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
agent.AgentID, agent.circuitcode);
if (CapsModule != null)
{
CapsModule.SetAgentCapsSeeds(agent);
CapsModule.CreateCaps(agent.AgentID);
}
}
else
{
@ -3945,6 +3966,11 @@ namespace OpenSim.Region.Framework.Scenes
agent.teleportFlags = teleportFlags;
m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent);
if (CapsModule != null)
{
CapsModule.ActivateCaps(agent.circuitcode);
}
if (vialogin)
{
// CleanDroppedAttachments();
@ -5122,7 +5148,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
{
if (grp.RootPart.Expires <= DateTime.Now)
if (grp.GetSittingAvatarsCount() == 0 && grp.RootPart.Expires <= DateTime.Now)
DeleteSceneObject(grp, false);
}
}

View File

@ -1689,6 +1689,10 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup != null)
ParentGroup.HasGroupChanged = true;
PhysicsActor pa = PhysActor;
if (pa != null)
pa.Density = Density;
}
}
@ -1708,6 +1712,9 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup != null)
ParentGroup.HasGroupChanged = true;
PhysicsActor pa = PhysActor;
if (pa != null)
pa.GravModifier = GravityModifier;
}
}
@ -1726,10 +1733,14 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup != null)
ParentGroup.HasGroupChanged = true;
PhysicsActor pa = PhysActor;
if (pa != null)
pa.Friction = Friction;
}
}
public float Bounciness
public float Restitution
{
get { return m_bounce; }
set
@ -1744,6 +1755,10 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup != null)
ParentGroup.HasGroupChanged = true;
PhysicsActor pa = PhysActor;
if (pa != null)
pa.Restitution = Restitution;
}
}
@ -4493,8 +4508,8 @@ namespace OpenSim.Region.Framework.Scenes
GravityModifier = physdata.GravitationModifier;
if(Friction != physdata.Friction)
Friction = physdata.Friction;
if(Bounciness != physdata.Bounce)
Bounciness = physdata.Bounce;
if(Restitution != physdata.Bounce)
Restitution = physdata.Bounce;
}
/// <summary>
/// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
@ -4657,6 +4672,11 @@ namespace OpenSim.Region.Framework.Scenes
pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
pa.SetMaterial(Material);
pa.Density = Density;
pa.GravModifier = GravityModifier;
pa.Friction = Friction;
pa.Restitution = Restitution;
if (VolumeDetectActive) // change if not the default only
pa.SetVolumeDetect(1);

View File

@ -204,6 +204,11 @@ namespace OpenSim.Region.Framework.Scenes
private const int LAND_VELOCITYMAG_MAX = 12;
private const float FLY_ROLL_MAX_RADIANS = 1.1f;
private const float FLY_ROLL_RADIANS_PER_UPDATE = 0.06f;
private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f;
private float m_health = 100f;
protected ulong crossingFromRegion;
@ -438,6 +443,8 @@ namespace OpenSim.Region.Framework.Scenes
get { return (IClientCore)ControllingClient; }
}
public UUID COF { get; set; }
// public Vector3 ParentPosition { get; set; }
/// <summary>
@ -606,6 +613,14 @@ namespace OpenSim.Region.Framework.Scenes
}
}
// Used for limited viewer 'fake' user rotations.
private Vector3 m_AngularVelocity = Vector3.Zero;
public Vector3 AngularVelocity
{
get { return m_AngularVelocity; }
}
public bool IsChildAgent { get; set; }
public bool IsLoggingIn { get; set; }
@ -736,6 +751,8 @@ namespace OpenSim.Region.Framework.Scenes
#endregion
#region Constructor(s)
public ScenePresence(
@ -1225,6 +1242,85 @@ namespace OpenSim.Region.Framework.Scenes
ControllingClient.StopFlying(this);
}
/// <summary>
/// Applies a roll accumulator to the avatar's angular velocity for the avatar fly roll effect.
/// </summary>
/// <param name="amount">Postive or negative roll amount in radians</param>
private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown)
{
float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS);
m_AngularVelocity.Z = rollAmount;
// APPLY EXTRA consideration for flying up and flying down during this time.
// if we're turning left
if (amount > 0)
{
// If we're at the max roll and pressing up, we want to swing BACK a bit
// Automatically adds noise
if (PressingUp)
{
if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS - 0.04f)
m_AngularVelocity.Z -= 0.9f;
}
// If we're at the max roll and pressing down, we want to swing MORE a bit
if (PressingDown)
{
if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS && m_AngularVelocity.Z < FLY_ROLL_MAX_RADIANS + 0.6f)
m_AngularVelocity.Z += 0.6f;
}
}
else // we're turning right.
{
// If we're at the max roll and pressing up, we want to swing BACK a bit
// Automatically adds noise
if (PressingUp)
{
if (m_AngularVelocity.Z <= (-FLY_ROLL_MAX_RADIANS))
m_AngularVelocity.Z += 0.6f;
}
// If we're at the max roll and pressing down, we want to swing MORE a bit
if (PressingDown)
{
if (m_AngularVelocity.Z >= -FLY_ROLL_MAX_RADIANS - 0.6f)
m_AngularVelocity.Z -= 0.6f;
}
}
}
/// <summary>
/// incrementally sets roll amount to zero
/// </summary>
/// <param name="amount">Positive roll amount in radians</param>
/// <returns></returns>
private float CalculateFlyingRollResetToZero(float amount)
{
const float rollMinRadians = 0f;
if (m_AngularVelocity.Z > 0)
{
float leftOverToMin = m_AngularVelocity.Z - rollMinRadians;
if (amount > leftOverToMin)
return -leftOverToMin;
else
return -amount;
}
else
{
float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians;
if (amount > leftOverToMin)
return leftOverToMin;
else
return amount;
}
}
// neighbouring regions we have enabled a child agent in
// holds the seed cap for the child agent in that region
private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
@ -1430,17 +1526,42 @@ namespace OpenSim.Region.Framework.Scenes
m_doingCamRayCast = false;
if (hitYN && localid != LocalId)
{
CameraConstraintActive = true;
pNormal.X = (float)Math.Round(pNormal.X, 2);
pNormal.Y = (float)Math.Round(pNormal.Y, 2);
pNormal.Z = (float)Math.Round(pNormal.Z, 2);
pNormal.Normalize();
collisionPoint.X = (float)Math.Round(collisionPoint.X, 1);
collisionPoint.Y = (float)Math.Round(collisionPoint.Y, 1);
collisionPoint.Z = (float)Math.Round(collisionPoint.Z, 1);
SceneObjectGroup group = m_scene.GetGroupByPrim(localid);
bool IsPrim = group != null;
if (IsPrim)
{
SceneObjectPart part = group.GetPart(localid);
if (part != null && !part.VolumeDetectActive)
{
CameraConstraintActive = true;
pNormal.X = (float) Math.Round(pNormal.X, 2);
pNormal.Y = (float) Math.Round(pNormal.Y, 2);
pNormal.Z = (float) Math.Round(pNormal.Z, 2);
pNormal.Normalize();
collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z, Vector3.Dot(collisionPoint, pNormal));
UpdateCameraCollisionPlane(plane);
Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
Vector3.Dot(collisionPoint, pNormal));
UpdateCameraCollisionPlane(plane);
}
}
else
{
CameraConstraintActive = true;
pNormal.X = (float) Math.Round(pNormal.X, 2);
pNormal.Y = (float) Math.Round(pNormal.Y, 2);
pNormal.Z = (float) Math.Round(pNormal.Z, 2);
pNormal.Normalize();
collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
Vector3.Dot(collisionPoint, pNormal));
UpdateCameraCollisionPlane(plane);
}
}
else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
@ -1741,6 +1862,33 @@ namespace OpenSim.Region.Framework.Scenes
bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
//m_log.Debug("[CONTROL]: " +flags);
// Applies a satisfying roll effect to the avatar when flying.
if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0) && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0))
{
ApplyFlyingRoll(FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0));
}
else if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0) &&
((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0))
{
ApplyFlyingRoll(-FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0));
}
else
{
if (m_AngularVelocity.Z != 0)
m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
}
if (Flying && IsColliding && controlland)
{
// nesting this check because LengthSquared() is expensive and we don't

View File

@ -633,7 +633,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader)
{
obj.Bounciness = reader.ReadElementContentAsFloat("Bounce", String.Empty);
obj.Restitution = reader.ReadElementContentAsFloat("Bounce", String.Empty);
}
private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader)
@ -1363,8 +1363,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
writer.WriteElementString("Density", sop.Density.ToString().ToLower());
if (sop.Friction != 0.6f)
writer.WriteElementString("Friction", sop.Friction.ToString().ToLower());
if (sop.Bounciness != 0.5f)
writer.WriteElementString("Bounce", sop.Bounciness.ToString().ToLower());
if (sop.Restitution != 0.5f)
writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower());
if (sop.GravityModifier != 1.0f)
writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());

View File

@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
}
return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0;
return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true, true) ? 1 : 0;
}
}
}

View File

@ -274,7 +274,7 @@ namespace OpenSim.Region.Physics.Manager
public virtual float Density { get; set; }
public virtual float GravModifier { get; set; }
public virtual float Friction { get; set; }
public virtual float Bounce { get; set; }
public virtual float Restitution { get; set; }
/// <summary>
/// Position of this actor.

View File

@ -1014,8 +1014,8 @@ namespace OpenSim.Region.Physics.OdePlugin
offset.Y += contact.pos.Y;
offset.Z += contact.pos.Z;
_position = offset;
return false;
//_position = offset;
//return false;
}
offset.X = contact.pos.X - _position.X;

View File

@ -3332,7 +3332,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
if (attachmentsModule != null)
return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false);
return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false, true);
else
return false;
}
@ -4724,7 +4724,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID av = new UUID();
if (!UUID.TryParse(agent,out av))
{
//LSLError("First parameter to llDialog needs to be a key");
return;
}
@ -7222,20 +7221,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
if (buttons.Length > 12)
{
LSLError("No more than 12 buttons can be shown");
return;
ShoutError("button list too long, must be 12 or fewer entries");
}
string[] buts = new string[buttons.Length];
for (int i = 0; i < buttons.Length; i++)
int length = buttons.Length;
if (length > 12)
length = 12;
string[] buts = new string[length];
for (int i = 0; i < length; i++)
{
if (buttons.Data[i].ToString() == String.Empty)
{
LSLError("button label cannot be blank");
ShoutError("button label cannot be blank");
return;
}
if (buttons.Data[i].ToString().Length > 24)
{
llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters");
ShoutError("button label cannot be longer than 24 characters");
return;
}
buts[i] = buttons.Data[i].ToString();
@ -7843,7 +7845,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
physdata.Density = part.Density;
physdata.Friction = part.Friction;
physdata.Bounce = part.Bounciness;
physdata.Bounce = part.Restitution;
physdata.GravitationModifier = part.GravityModifier;
if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
@ -8236,7 +8238,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ExtraPhysicsData physdata = new ExtraPhysicsData();
physdata.Density = part.Density;
physdata.Bounce = part.Bounciness;
physdata.Bounce = part.Restitution;
physdata.GravitationModifier = part.GravityModifier;
physdata.PhysShapeType = (PhysShapeType)shape_type;

View File

@ -123,7 +123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void modInvokeN(string fname, params object[] parms)
{
Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(string))
if (returntype != typeof(void))
MODError(String.Format("return type mismatch for {0}",fname));
modInvoke(fname,parms);
@ -264,6 +264,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (result != null)
return result;
Type returntype = m_comms.LookupReturnType(fname);
if (returntype == typeof(void))
return null;
MODError(String.Format("Invocation of {0} failed; null return value",fname));
}
catch (Exception e)

View File

@ -1619,7 +1619,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
public Object osParseJSONNew(string JSON)
private Object osParseJSONNew(string JSON)
{
CheckThreatLevel(ThreatLevel.None, "osParseJSONNew");

View File

@ -259,7 +259,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
string osGetScriptEngineName();
string osGetSimulatorVersion();
Object osParseJSONNew(string JSON);
Hashtable osParseJSON(string JSON);
void osMessageObject(key objectUUID,string message);

View File

@ -430,11 +430,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_OSSL_Functions.osParseJSON(JSON);
}
public Object osParseJSONNew(string JSON)
{
return m_OSSL_Functions.osParseJSONNew(JSON);
}
public void osMessageObject(key objectUUID,string message)
{
m_OSSL_Functions.osMessageObject(objectUUID,message);

View File

@ -512,7 +512,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
else if (o is LSL_Types.LSLFloat)
size += 8;
else if (o is LSL_Types.LSLString)
size += ((LSL_Types.LSLString)o).m_string.Length;
size += ((LSL_Types.LSLString)o).m_string == null ? 0 : ((LSL_Types.LSLString)o).m_string.Length;
else if (o is LSL_Types.key)
size += ((LSL_Types.key)o).value.Length;
else if (o is LSL_Types.Vector3)

View File

@ -180,11 +180,18 @@ namespace OpenSim.Services.Interfaces
// Attachments
List<AvatarAttachment> attachments = appearance.GetAttachments();
Dictionary<int, List<string>> atts = new Dictionary<int, List<string>>();
foreach (AvatarAttachment attach in attachments)
{
if (attach.ItemID != UUID.Zero)
Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString();
{
if (!atts.ContainsKey(attach.AttachPoint))
atts[attach.AttachPoint] = new List<string>();
atts[attach.AttachPoint].Add(attach.ItemID.ToString());
}
}
foreach (KeyValuePair<int, List<string>> kvp in atts)
Data["_ap_" + kvp.Key] = string.Join(",", kvp.Value.ToArray());
}
public AvatarAppearance ToAvatarAppearance()
@ -320,10 +327,16 @@ namespace OpenSim.Services.Interfaces
if (!Int32.TryParse(pointStr, out point))
continue;
UUID uuid = UUID.Zero;
UUID.TryParse(_kvp.Value, out uuid);
List<string> idList = new List<string>(_kvp.Value.Split(new char[] {','}));
appearance.SetAttachment(point, uuid, UUID.Zero);
appearance.SetAttachment(point, UUID.Zero, UUID.Zero);
foreach (string id in idList)
{
UUID uuid = UUID.Zero;
UUID.TryParse(id, out uuid);
appearance.SetAttachment(point | 0x80, uuid, UUID.Zero);
}
}
if (appearance.Wearables[AvatarWearable.BODY].Count == 0)

View File

@ -1597,9 +1597,10 @@
<Reference name="System.Drawing"/>
<Reference name="System.Xml"/>
<Reference name="System.Web"/>
<Reference name="OpenMetaverse" path="../../../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../../../bin/"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../../../bin/"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Capabilities"/>
<Reference name="OpenSim.Capabilities.Handlers"/>