rendered paste bodyIndex: OpenMetaverse.Http/EventQueueClient.cs
===================================================================
--- OpenMetaverse.Http/EventQueueClient.cs (revision 2945)
+++ OpenMetaverse.Http/EventQueueClient.cs (working copy)
@@ -143,13 +143,19 @@
if (error is WebException && ((WebException)error).Response != null)
code = ((HttpWebResponse)((WebException)error).Response).StatusCode;
- if (code == HttpStatusCode.NotFound || code == HttpStatusCode.Gone)
+ if ( code == HttpStatusCode.Gone)
{
Logger.Log.InfoFormat("Closing event queue at {0} due to missing caps URI", _Address);
_Running = false;
_Dead = true;
}
+ else if (code == HttpStatusCode.NotFound)
+ {
+ Logger.Log.InfoFormat("event queue at {0} got {1} message {2}", _Address, code, error.Message);
+ _Running = false;
+ _Dead = true;
+ }
else if (code == HttpStatusCode.BadGateway)
{
// This is not good (server) protocol design, but it's normal.
Index: OpenMetaverse/AgentManager.cs
===================================================================
--- OpenMetaverse/AgentManager.cs (revision 2945)
+++ OpenMetaverse/AgentManager.cs (working copy)
@@ -1049,16 +1049,15 @@
if (sittingOn != 0)
{
Primitive parent;
- if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out parent))
+ if (Client.Network.CurrentSim != null)
{
- return parent.Position + Vector3.Transform(relativePosition, Matrix4.CreateFromQuaternion(parent.Rotation));
+ lock (Client.Network.CurrentSim.ObjectsPrimitives.Dictionary)
+ if (Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out parent))
+ return parent.Position + Vector3.Transform(relativePosition, Matrix4.CreateFromQuaternion(parent.Rotation));
}
- else
- {
- Logger.Log("Currently sitting on object " + sittingOn + " which is not tracked, SimPosition will be inaccurate",
- Helpers.LogLevel.Warning, Client);
- return relativePosition;
- }
+ Logger.Log("Currently sitting on object " + sittingOn + " which is not tracked, SimPosition will be inaccurate",
+ Helpers.LogLevel.Warning, Client);
+ return relativePosition;
}
else
{
@@ -1076,16 +1075,15 @@
if (sittingOn != 0)
{
Primitive parent;
- if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out parent))
+ if (Client.Network.CurrentSim != null)
{
- return relativeRotation * parent.Rotation;
+ lock (Client.Network.CurrentSim.ObjectsPrimitives.Dictionary)
+ if (Client.Network.CurrentSim.ObjectsPrimitives.TryGetValue(sittingOn, out parent))
+ return relativeRotation*parent.Rotation;
}
- else
- {
- Logger.Log("Currently sitting on object " + sittingOn + " which is not tracked, SimRotation will be inaccurate",
- Helpers.LogLevel.Warning, Client);
- return relativeRotation;
- }
+ Logger.Log("Currently sitting on object " + sittingOn + " which is not tracked, SimRotation will be inaccurate",
+ Helpers.LogLevel.Warning, Client);
+ return relativeRotation;
}
else
{
Index: OpenMetaverse/AgentManagerMovement.cs
===================================================================
--- OpenMetaverse/AgentManagerMovement.cs (revision 2945)
+++ OpenMetaverse/AgentManagerMovement.cs (working copy)
@@ -671,7 +671,7 @@
else agentControls &= ~((uint)flag);
}
- private void ResetControlFlags()
+ public void ResetControlFlags()
{
// Reset all of the flags except for persistent settings like
// away, fly, mouselook, and crouching
Index: OpenMetaverse/AppearanceManager.cs
===================================================================
--- OpenMetaverse/AppearanceManager.cs (revision 2945)
+++ OpenMetaverse/AppearanceManager.cs (working copy)
@@ -110,6 +110,10 @@
/// <summary></summary>
public event AppearanceUpdatedCallback OnAppearanceUpdated;
+ /// <summary>
+ /// Time that wearable events will wait (140 secs)
+ /// </summary>
+ public static int WEARABLE_TIMEOUT = 140 * 1000;
/// <summary>Total number of wearables for each avatar</summary>
public const int WEARABLE_COUNT = 13;
/// <summary>Total number of baked textures on each avatar</summary>
@@ -240,7 +244,7 @@
{
WearableData wearable;
- if (Wearables.TryGetValue(type, out wearable))
+ if (Wearables.Dictionary.TryGetValue(type, out wearable))
return wearable.Item.AssetUUID;
else
return UUID.Zero;
@@ -414,9 +418,19 @@
List<InventoryBase> attachments;
if (!GetFolderWearables(wearOutfitParams.Param, out wearables, out attachments)) // get wearables in outfit folder
- return; // TODO: this error condition should be passed back to the client somehow
+ // TODO: this error condition should be passed back to the client somehow}
+ {
+ Logger.Log(
+ "GetFolderWearables did not find wearables " +
+ wearOutfitParams.Param + " " + wearables + " " +
+ attachments, Helpers.LogLevel.Error, Client);
+ return;
+ }
- WearablesRequestEvent.WaitOne(); // wait for current wearables
+ if (!WearablesRequestEvent.WaitOne(WEARABLE_TIMEOUT*2)) // wait for current wearables
+ {
+ Logger.Log("StartWearOutfitFolder timed out.", Helpers.LogLevel.Error, Client);
+ }
ReplaceOutfitWearables(wearables); // replace current wearables with outfit folder
UpdateAppearanceFromWearables(wearOutfitParams.Bake);
AddAttachments(attachments, wearOutfitParams.RemoveExistingAttachments);
@@ -433,7 +447,7 @@
string[] path = (string[])_folder;
folder = Client.Inventory.FindObjectByPath(
- Client.Inventory.Store.RootFolder.UUID, Client.Self.AgentID, String.Join("/", path), 1000 * 20);
+ Client.Inventory.Store.RootFolder.UUID, Client.Self.AgentID, String.Join("/", path), 1000 * 200);
if (folder == UUID.Zero)
{
@@ -455,22 +469,22 @@
{
if (ib is InventoryWearable)
{
- Logger.DebugLog("Adding wearable " + ib.Name, Client);
+ Logger.Log("Adding wearable " + ib.Name, Client);
wearables.Add((InventoryWearable)ib);
}
else if (ib is InventoryAttachment)
{
- Logger.DebugLog("Adding attachment (attachment) " + ib.Name, Client);
+ Logger.Log("Adding attachment (attachment) " + ib.Name, Client);
attachments.Add(ib);
}
else if (ib is InventoryObject)
{
- Logger.DebugLog("Adding attachment (object) " + ib.Name, Client);
+ Logger.Log("Adding attachment (object) " + ib.Name, Client);
attachments.Add(ib);
}
else
{
- Logger.DebugLog("Ignoring inventory item " + ib.Name, Client);
+ Logger.Log("Ignoring inventory item " + ib.Name, Client);
}
}
}
@@ -669,13 +683,18 @@
SendAgentIsNowWearing();
// Wait for cached layer check to finish
- if (bake) CachedResponseEvent.WaitOne();
+ if (bake) if (!CachedResponseEvent.WaitOne(WEARABLE_TIMEOUT))
+ {
+ Logger.Log("Giving up on CachedResponseEvent didnt complete (in time)", Client);
+ Assets.OnAssetUploaded -= uploadCallback;
+ return;
+ }
// Unregister the image download and asset upload callbacks
//Assets.OnImageReceived -= imageCallback;
Assets.OnAssetUploaded -= uploadCallback;
- Logger.DebugLog("CachedResponseEvent completed", Client);
+ Logger.Log("CachedResponseEvent completed", Client);
#region Send Appearance
@@ -705,7 +724,7 @@
}
else if (face.TextureID != AgentTextures[i] && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
{
- Logger.DebugLog("*** FACE is " + ((TextureIndex)i).ToString() + " " + face.TextureID.ToString() + " Agent Texture is " + AgentTextures[i].ToString());
+ Logger.Log("*** FACE is " + ((TextureIndex)i).ToString() + " " + face.TextureID.ToString() + " Agent Texture is " + AgentTextures[i].ToString(),Client);
match = false;
//break;
}
@@ -730,7 +749,7 @@
SendAgentSetAppearance();
// Wait for the ObjectUpdate to come in for our avatar after changing appearance
- if (UpdateEvent.WaitOne(1000 * 60, false))
+ if (UpdateEvent.WaitOne(1000 * 130, false))
{
if (OnAppearanceUpdated != null)
{
@@ -755,7 +774,7 @@
/// </summary>
public void RequestCachedBakes()
{
- Logger.DebugLog("RequestCachedBakes()", Client);
+ Logger.Log("RequestCachedBakes()", Client);
List<KeyValuePair<int, UUID>> hashes = new List<KeyValuePair<int,UUID>>();
@@ -768,6 +787,7 @@
for (int bakedIndex = 0; bakedIndex < BAKED_TEXTURE_COUNT; bakedIndex++)
{
// Don't do a cache request for a skirt bake if we're not wearing a skirt
+ lock (Wearables.Dictionary)
if (bakedIndex == (int)BakeType.Skirt &&
(!Wearables.ContainsKey(WearableType.Skirt) || Wearables.Dictionary[WearableType.Skirt].Asset.AssetID == UUID.Zero))
continue;
@@ -804,7 +824,7 @@
cache.WearableData[i].TextureIndex = (byte)hashes[i].Key;
cache.WearableData[i].ID = hashes[i].Value;
- Logger.DebugLog("Checking cache for index " + cache.WearableData[i].TextureIndex +
+ Logger.Log("Checking cache for index " + cache.WearableData[i].TextureIndex +
", ID: " + cache.WearableData[i].ID, Client);
}
@@ -825,6 +845,7 @@
for (int i = 0; i < BAKED_TEXTURE_COUNT; i++)
{
// Don't bake skirt if not wearing one
+ lock (Wearables.Dictionary)
if (i == (int)BakeType.Skirt && (!Wearables.ContainsKey(WearableType.Skirt) || Wearables.Dictionary[WearableType.Skirt].Asset.AssetID == UUID.Zero))
{
continue;
@@ -884,11 +905,12 @@
private void SendAgentSetAppearance()
{
+ const bool UseExtraParams = false;
AgentSetAppearancePacket set = new AgentSetAppearancePacket();
set.AgentData.AgentID = Client.Self.AgentID;
set.AgentData.SessionID = Client.Self.SessionID;
set.AgentData.SerialNum = SetAppearanceSerialNum++;
- set.VisualParam = new AgentSetAppearancePacket.VisualParamBlock[218];
+ set.VisualParam = new AgentSetAppearancePacket.VisualParamBlock[UseExtraParams ? 258 : 218];
float AgentSizeVPHeight = 0.0f;
float AgentSizeVPHeelHeight = 0.0f;
@@ -952,6 +974,19 @@
++vpIndex;
}
+ else
+ {
+ if (UseExtraParams)
+ {
+ if ((vp.Wearable != null) && vp.Wearable.Equals("shape"))
+ {
+ set.VisualParam[vpIndex] = new AgentSetAppearancePacket.VisualParamBlock();
+ set.VisualParam[vpIndex].ParamValue = Utils.FloatToByte(vp.DefaultValue, vp.MinValue,
+ vp.MaxValue);
+ ++vpIndex;
+ }
+ }
+ }
}
// Build the texture entry for our agent
@@ -979,7 +1014,7 @@
Primitive.TextureEntryFace face = te.CreateFace((uint)texture.Key);
face.TextureID = texture.Value;
- Logger.DebugLog("Setting agent texture " + ((TextureIndex)texture.Key).ToString() + " to " +
+ Logger.Log("Setting agent texture " + ((TextureIndex)texture.Key).ToString() + " to " +
texture.Value.ToString(), Client);
}
}
@@ -1031,7 +1066,7 @@
set.WearableData[bakedIndex] = new AgentSetAppearancePacket.WearableDataBlock();
set.WearableData[bakedIndex].TextureIndex = (byte)bakedIndex;
set.WearableData[bakedIndex].CacheID = hash;
- Logger.DebugLog("Setting baked agent texture hash " + ((BakeType)bakedIndex).ToString() + " to " + hash, Client);
+ Logger.Log("Setting baked agent texture hash " + ((BakeType)bakedIndex).ToString() + " to " + hash, Client);
}
@@ -1042,7 +1077,7 @@
private void SendAgentIsNowWearing()
{
- Logger.DebugLog("SendAgentIsNowWearing()", Client);
+ Logger.Log("SendAgentIsNowWearing()", Client);
AgentIsNowWearingPacket wearing = new AgentIsNowWearingPacket();
wearing.AgentData.AgentID = Client.Self.AgentID;
@@ -1055,6 +1090,7 @@
wearing.WearableData[i] = new AgentIsNowWearingPacket.WearableDataBlock();
wearing.WearableData[i].WearableType = (byte)i;
+ lock (Wearables.Dictionary)
if (Wearables.ContainsKey(type))
wearing.WearableData[i].ItemID = Wearables.Dictionary[type].Item.UUID;
else
@@ -1091,7 +1127,7 @@
{
foreach (KeyValuePair<WearableType, WearableData> kvp in Wearables.Dictionary)
{
- Logger.DebugLog("Requesting asset for wearable item " + kvp.Value.Item.WearableType + " (" + kvp.Value.Item.AssetUUID + ")", Client);
+ Logger.Log("Requesting asset for wearable item " + kvp.Value.Item.WearableType + " (" + kvp.Value.Item.AssetUUID + ")", Client);
AssetDownloads.Enqueue(new PendingAssetDownload(kvp.Value.Item.AssetUUID, kvp.Value.Item.AssetType));
}
}
@@ -1144,7 +1180,7 @@
PendingUploads.Add(UUID.Combine(id, Client.Self.SecureSessionID), BakeTypeToAgentTextureIndex(bake.BakeType));
}
- Logger.DebugLog(String.Format("Bake {0} completed. Uploading asset {1}", bake.BakeType,
+ Logger.Log(String.Format("Bake {0} completed. Uploading asset {1}", bake.BakeType,
bake.BakedTexture.AssetID.ToString()), Client);
}
@@ -1157,7 +1193,7 @@
{
if (!ImageDownloads.ContainsKey(image))
{
- Logger.DebugLog("Downloading layer " + index.ToString(), Client);
+ Logger.Log("Downloading layer " + index.ToString(), Client);
ImageDownloads.Add(image, index);
}
@@ -1184,7 +1220,7 @@
// Try and find this value in our collection of downloaded wearables
foreach (WearableData data in Wearables.Dictionary.Values)
{
- if (data.Asset.Params.ContainsKey(vp.ParamID))
+ if (data.Asset!=null && data.Asset.Params.ContainsKey(vp.ParamID))
{
paramValues.Add(vp.ParamID, data.Asset.Params[vp.ParamID]);
found = true;
@@ -1293,7 +1329,7 @@
private void AgentCachedTextureResponseHandler(Packet packet, Simulator simulator)
{
- Logger.DebugLog("AgentCachedTextureResponseHandler()", Client);
+ Logger.Log("AgentCachedTextureResponseHandler()", Client);
AgentCachedTextureResponsePacket response = (AgentCachedTextureResponsePacket)packet;
@@ -1307,12 +1343,12 @@
{
//UUID hash=new UUID();
// For each missing element we need to bake our own texture
- Logger.DebugLog("Cache response, index: " + block.TextureIndex + ", ID: " +
+ Logger.Log("Cache response, index: " + block.TextureIndex + ", ID: " +
block.TextureID.ToString(), Client);
// FIXME: Use this. Right now we treat baked images on other sims as if they were missing
string host = Utils.BytesToString(block.HostName);
- if (host.Length > 0) Logger.DebugLog("Cached bake exists on foreign host " + host, Client);
+ if (host.Length > 0) Logger.Log("Cached bake exists on foreign host " + host, Client);
BakeType bakeType = (BakeType)block.TextureIndex;
@@ -1332,7 +1368,7 @@
if (!PendingBakes.ContainsKey(bakeType))
{
- Logger.DebugLog("Initializing " + bakeType.ToString() + " bake with " + imageCount + " textures", Client);
+ Logger.Log("Initializing " + bakeType.ToString() + " bake with " + imageCount + " textures", Client);
Dictionary<int, float> paramValues=MakeParamValues();
// Build a dictionary of appearance parameter indices and values from the wearables
@@ -1393,7 +1429,7 @@
{
kvp.Value.Asset = (AssetWearable)asset;
- Logger.DebugLog("Downloaded wearable asset " + kvp.Value.Asset.Name, Client);
+ Logger.Log("Downloaded wearable asset " + kvp.Value.Asset.Name, Client);
if (!kvp.Value.Asset.Decode())
{
@@ -1407,7 +1443,7 @@
{
if (texture.Value != DEFAULT_AVATAR_TEXTURE) // this texture is not meant to be displayed
{
- Logger.DebugLog("Setting " + texture.Key + " to " + texture.Value, Client);
+ Logger.Log("Setting " + texture.Key + " to " + texture.Value, Client);
AgentTextures[(int)texture.Key] = texture.Value;
}
}
@@ -1470,7 +1506,7 @@
{
if (state == TextureRequestState.Finished)
{
- Logger.DebugLog("Finished downloading texture for " + index.ToString(), Client);
+ Logger.Log("Finished downloading texture for " + index.ToString(), Client);
OpenJPEG.DecodeToImage(assetTexture.AssetData, out assetTexture.Image);
baked = PendingBakes[type].AddTexture(index, assetTexture, false);
}
@@ -1492,12 +1528,12 @@
{
// This is a failsafe catch, as the upload completed callback should normally
// be triggering the event
- Logger.DebugLog("No pending downloads or uploads detected in OnImageReceived", Client);
+ Logger.Log("No pending downloads or uploads detected in OnImageReceived", Client);
CachedResponseEvent.Set();
}
else
{
- Logger.DebugLog("Pending uploads: " + PendingUploads.Count + ", pending downloads: " +
+ Logger.Log("Pending uploads: " + PendingUploads.Count + ", pending downloads: " +
ImageDownloads.Count, Client);
}
@@ -1522,10 +1558,19 @@
{
// Setup the TextureEntry with the new baked upload
TextureIndex index = PendingUploads[upload.AssetID];
- AgentTextures[(int)index] = upload.AssetID;
+ int u = (int) index;
+ if (u < 0)
+ {
+ Logger.Log("Invalid Index, AgentTextures " + index.ToString() + " set to " +
+ upload.AssetID.ToString(), Client);
+ }
+ else
+ {
+ AgentTextures[u] = upload.AssetID;
- Logger.DebugLog("Upload complete, AgentTextures " + index.ToString() + " set to " +
- upload.AssetID.ToString(), Client);
+ Logger.Log("Upload complete, AgentTextures " + index.ToString() + " set to " +
+ upload.AssetID.ToString(), Client);
+ }
}
else
{
@@ -1535,12 +1580,12 @@
PendingUploads.Remove(upload.AssetID);
- Logger.DebugLog("Pending uploads: " + PendingUploads.Count + ", pending downloads: " +
+ Logger.Log("Pending uploads: " + PendingUploads.Count + ", pending downloads: " +
ImageDownloads.Count, Client);
if (PendingUploads.Count == 0 && ImageDownloads.Count == 0)
{
- Logger.DebugLog("All pending image downloads and uploads complete", Client);
+ Logger.Log("All pending image downloads and uploads complete", Client);
CachedResponseEvent.Set();
}
@@ -1548,7 +1593,7 @@
else
{
// TEMP
- Logger.DebugLog("Upload " + upload.AssetID.ToString() + " was not found in PendingUploads", Client);
+ Logger.Log("Upload " + upload.AssetID.ToString() + " was not found in PendingUploads", Client);
}
}
}
Index: OpenMetaverse/Assets/AssetTypes/AssetWearable.cs
===================================================================
--- OpenMetaverse/Assets/AssetTypes/AssetWearable.cs (revision 2945)
+++ OpenMetaverse/Assets/AssetTypes/AssetWearable.cs (working copy)
@@ -118,22 +118,29 @@
if (fields[0] == "parameters")
{
int count = Int32.Parse(fields[1]) + stri;
- for (; stri < count; )
+ for (; stri < count;)
{
stri++;
+ if (stri >= lines.Length) return false;
line = lines[stri].Trim();
fields = line.Split(' ');
- int id = Int32.Parse(fields[0]);
- if (fields[1] == ",")
- fields[1] = "0";
- else
- fields[1] = fields[1].Replace(',', '.');
+ int id;
+ if (int.TryParse(fields[0], out id))
+ {
+ if (fields.Length > 1)
+ {
+ if (fields[1] == ",")
+ fields[1] = "0";
+ else
+ fields[1] = fields[1].Replace(',', '.');
- float weight = float.Parse(fields[1], System.Globalization.NumberStyles.Float,
- Utils.EnUsCulture.NumberFormat);
+ float weight = float.Parse(fields[1], System.Globalization.NumberStyles.Float,
+ Utils.EnUsCulture.NumberFormat);
- Params[id] = weight;
+ Params[id] = weight;
+ }
+ }
}
}
else if (fields[0] == "textures")
Index: OpenMetaverse/AvatarManager.cs
===================================================================
--- OpenMetaverse/AvatarManager.cs (revision 2945)
+++ OpenMetaverse/AvatarManager.cs (working copy)
@@ -492,7 +492,7 @@
InternalDictionary<UUID, int> signaledAnims = new InternalDictionary<UUID, int>();
for(int i=0; i < anims.AnimationList.Length; i++)
- signaledAnims.Add(anims.AnimationList[i].AnimID, anims.AnimationList[i].AnimSequenceID);
+ signaledAnims.Dictionary.Add(anims.AnimationList[i].AnimID, anims.AnimationList[i].AnimSequenceID);
try { OnAvatarAnimation(anims.Sender.ID, signaledAnims); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
Index: OpenMetaverse/BVHDecoder.cs
===================================================================
--- OpenMetaverse/BVHDecoder.cs (revision 2945)
+++ OpenMetaverse/BVHDecoder.cs (working copy)
@@ -343,14 +343,148 @@
}
return m_keys;
}
+
+ public bool Equals(BinBVHAnimationReader other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return other.Loop.Equals(Loop) && other.OutPoint == OutPoint && other.InPoint == InPoint && other.Length == Length && other.HandPose == HandPose && other.JointCount == JointCount && Equals(other.joints, joints) && other.EaseInTime == EaseInTime && other.EaseOutTime == EaseOutTime && other.Priority == Priority && other.unknown1 == unknown1 && other.unknown0 == unknown0 && other.positionkeys == positionkeys && other.rotationkeys == rotationkeys;
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <returns>
+ /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
+ /// </returns>
+ /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.
+ /// </param><exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.
+ /// </exception><filterpriority>2</filterpriority>
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != typeof (BinBVHAnimationReader)) return false;
+ return Equals((BinBVHAnimationReader) obj);
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int result = Loop.GetHashCode();
+ result = (result*397) ^ OutPoint.GetHashCode();
+ result = (result*397) ^ InPoint.GetHashCode();
+ result = (result*397) ^ Length.GetHashCode();
+ result = (result*397) ^ HandPose.GetHashCode();
+ result = (result*397) ^ JointCount.GetHashCode();
+ result = (result*397) ^ (joints != null ? joints.GetHashCode() : 0);
+ result = (result*397) ^ EaseInTime.GetHashCode();
+ result = (result*397) ^ EaseOutTime.GetHashCode();
+ result = (result*397) ^ Priority;
+ result = (result*397) ^ unknown1.GetHashCode();
+ result = (result*397) ^ unknown0.GetHashCode();
+ result = (result*397) ^ positionkeys;
+ result = (result*397) ^ rotationkeys;
+ return result;
+ }
+ }
+
+ public static bool Equals(binBVHJoint[] arr1, binBVHJoint[] arr2)
+ {
+ if (arr1.Length == arr2.Length)
+ {
+ for (int i = 0; i < arr1.Length; i++)
+ if (!arr1[i].Equals(arr2[i]))
+ return false;
+ /* not same*/
+ return true;
+ }
+ return false;
+ }
+
}
+
/// <summary>
/// A Joint and it's associated meta data and keyframes
/// </summary>
public struct binBVHJoint
{
+ public static bool Equals(binBVHJointKey[] arr1, binBVHJointKey[] arr2)
+ {
+ if (arr1.Length == arr2.Length)
+ {
+ for (int i = 0; i < arr1.Length; i++)
+ if (!Equals(arr1[i], arr2[i]))
+ return false;
+ /* not same*/
+ return true;
+ }
+ return false;
+ }
+ public static bool Equals(binBVHJointKey arr1, binBVHJointKey arr2)
+ {
+ return (arr1.time == arr2.time && arr1.key_element == arr2.key_element);
+ }
+
+ public bool Equals(binBVHJoint other)
+ {
+ return other.Priority == Priority && Equals(other.rotationkeys, rotationkeys) && Equals(other.Name, Name) && Equals(other.positionkeys, positionkeys);
+ }
+
/// <summary>
+ /// Indicates whether this instance and a specified object are equal.
+ /// </summary>
+ /// <returns>
+ /// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
+ /// </returns>
+ /// <param name="obj">Another object to compare to.
+ /// </param><filterpriority>2</filterpriority>
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (obj.GetType() != typeof (binBVHJoint)) return false;
+ return Equals((binBVHJoint) obj);
+ }
+
+ /// <summary>
+ /// Returns the hash code for this instance.
+ /// </summary>
+ /// <returns>
+ /// A 32-bit signed integer that is the hash code for this instance.
+ /// </returns>
+ /// <filterpriority>2</filterpriority>
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int result = Priority;
+ result = (result*397) ^ (rotationkeys != null ? rotationkeys.GetHashCode() : 0);
+ result = (result*397) ^ (Name != null ? Name.GetHashCode() : 0);
+ result = (result*397) ^ (positionkeys != null ? positionkeys.GetHashCode() : 0);
+ return result;
+ }
+ }
+
+ public static bool operator ==(binBVHJoint left, binBVHJoint right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(binBVHJoint left, binBVHJoint right)
+ {
+ return !left.Equals(right);
+ }
+
+ /// <summary>
/// Name of the Joint. Matches the avatar_skeleton.xml in client distros
/// </summary>
public string Name;
Index: OpenMetaverse/EventDictionary.cs
===================================================================
--- OpenMetaverse/EventDictionary.cs (revision 2945)
+++ OpenMetaverse/EventDictionary.cs (working copy)
@@ -34,11 +34,14 @@
namespace OpenMetaverse
{
+ public delegate bool SkipEventCallback(PacketType type, Simulator sim);
/// <summary>
/// Registers, unregisters, and fires events generated by incoming packets
/// </summary>
public class PacketEventDictionary
{
+ public event SkipEventCallback SkipEvent;
+
/// <summary>
/// Object that is passed to worker threads in the ThreadPool for
/// firing packet callbacks
@@ -112,6 +115,7 @@
{
NetworkManager.PacketCallback callback;
+ if (SkipEvent != null && SkipEvent(packetType, simulator)) return;
// Default handler first, if one exists
if (_EventTable.TryGetValue(PacketType.Default, out callback))
{
@@ -135,7 +139,7 @@
if (packetType != PacketType.Default && packetType != PacketType.PacketAck)
{
- Logger.DebugLog("No handler registered for packet event " + packetType, Client);
+ Logger.Log("No handler registered for packet event " + packetType, Client);
}
}
@@ -147,6 +151,7 @@
/// <param name="simulator">Simulator this packet was received from</param>
internal void BeginRaiseEvent(PacketType packetType, Packet packet, Simulator simulator)
{
+ if (SkipEvent != null && SkipEvent(packetType, simulator)) return;
NetworkManager.PacketCallback callback;
PacketCallbackWrapper wrapper;
@@ -177,7 +182,7 @@
if (packetType != PacketType.Default && packetType != PacketType.PacketAck)
{
- Logger.DebugLog("No handler registered for packet event " + packetType, Client);
+ Logger.Log("No handler registered for packet event " + packetType, Client);
}
}
Index: OpenMetaverse/GroupManager.cs
===================================================================
--- OpenMetaverse/GroupManager.cs (revision 2945)
+++ OpenMetaverse/GroupManager.cs (working copy)
@@ -488,35 +488,37 @@
/// </summary>
/// <param name="requestID"><seealso cref="UUID"/> returned by RequestGroupMembers</param>
/// <param name="groupID"><seealso cref="UUID"/> of the group</param>
+ /// <param name="memberCount">Total number of members in the group</param>
/// <param name="members">A dictionary containing the members of a group
/// where key is member <seealso cref="UUID"/> and value is <seealso cref="GroupMember"/> struct</param>
- public delegate void GroupMembersCallback(UUID requestID, UUID groupID, Dictionary<UUID, GroupMember> members);
+ public delegate void GroupMembersCallback(UUID requestID, UUID groupID, int memberCount, Dictionary<UUID, GroupMember> members);
/// <summary>
/// Callback for retrieving group roles
/// </summary>
/// <param name="requestID"><seealso cref="UUID"/> of the request returned from RequestGroupRoles</param>
/// <param name="groupID"><seealso cref="UUID"/> of the group</param>
+ /// <param name="roleCount">Total number of roles defined in the group</param>
/// <param name="roles">A dictionary containing role <seealso cref="UUID"/>s as the key
/// and <seealso cref="GroupRole"/> structs as values</param>
- public delegate void GroupRolesCallback(UUID requestID, UUID groupID, Dictionary<UUID, GroupRole> roles);
+ public delegate void GroupRolesCallback(UUID requestID, UUID groupID, int roleCount, Dictionary<UUID, GroupRole> roles);
/// <summary>
/// Callback for a pairing of roles to members
/// </summary>
/// <param name="requestID"><seealso cref="UUID"/> of the request returned from RequestGroupRolesMembers</param>
/// <param name="groupID"><seealso cref="UUID"/> of the group</param>
+ /// <param name="totalPairs">Total number of role/member mappings</param>
/// <param name="rolesMembers">List containing role/member pairs</param>
- public delegate void GroupRolesMembersCallback(UUID requestID, UUID groupID, List<KeyValuePair<UUID, UUID>> rolesMembers);
+ public delegate void GroupRolesMembersCallback(UUID requestID, UUID groupID, uint totalPairs, List<KeyValuePair<UUID, UUID>> rolesMembers);
/// <summary>
/// Callback for the title list of a group
/// </summary>
- /// <param name="requestID"><seealso cref="UUID"/> of the request returned from RequestGroupTitles</param>
/// <param name="groupID">Group <seealso cref="UUID"/></param>
/// <param name="titles">A dictionary containing the titles of a group
/// where the Key is the role <seealso cref="UUID"/>, and the values are the title details</param>
- public delegate void GroupTitlesCallback(UUID requestID, UUID groupID, Dictionary<UUID, GroupTitle> titles);
+ public delegate void GroupTitlesCallback(UUID groupID, Dictionary<UUID, GroupTitle> titles);
/// <summary>
/// Callback fired when group account summary information is received
@@ -1207,7 +1209,7 @@
group.Contribution = msg.GroupDataBlock[i].Contribution;
group.AcceptNotices = msg.GroupDataBlock[i].AcceptNotices;
group.Powers = msg.GroupDataBlock[i].GroupPowers;
- group.ListInProfile = msg.NewGroupDataBlock[i].ListInProfile;
+ // group.ListInProfile = msg.NewGroupDataBlock[i].ListInProfile;
currentGroups.Add(group.ID, group);
@@ -1280,7 +1282,7 @@
groupTitleCache[block.RoleID] = groupTitle;
}
- try { OnGroupTitles(titles.AgentData.RequestID, titles.AgentData.GroupID, groupTitleCache); }
+ try { OnGroupTitles(titles.AgentData.GroupID, groupTitleCache); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
@@ -1326,9 +1328,9 @@
}
}
- if (OnGroupMembers != null && groupMemberCache != null && groupMemberCache.Count >= members.GroupData.MemberCount)
+ if (OnGroupMembers != null && groupMemberCache != null)
{
- try { OnGroupMembers(members.GroupData.RequestID, members.GroupData.GroupID, groupMemberCache); }
+ try { OnGroupMembers(members.GroupData.RequestID, members.GroupData.GroupID, members.GroupData.MemberCount, groupMemberCache); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
@@ -1376,9 +1378,9 @@
}
}
- if (OnGroupRoles != null && groupRoleCache != null && groupRoleCache.Count >= roles.GroupData.RoleCount)
+ if (OnGroupRoles != null && groupRoleCache != null)
{
- try { OnGroupRoles(roles.GroupData.RequestID, roles.GroupData.GroupID, groupRoleCache); }
+ try { OnGroupRoles(roles.GroupData.RequestID, roles.GroupData.GroupID, roles.GroupData.RoleCount, groupRoleCache); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
@@ -1425,9 +1427,9 @@
Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e);
}
- if (OnGroupRolesMembers != null && groupRoleMemberCache != null && groupRoleMemberCache.Count >= members.AgentData.TotalPairs)
+ if (OnGroupRolesMembers != null && groupRoleMemberCache != null)
{
- try { OnGroupRolesMembers(members.AgentData.RequestID, members.AgentData.GroupID, groupRoleMemberCache); }
+ try { OnGroupRolesMembers(members.AgentData.RequestID, members.AgentData.GroupID, members.AgentData.TotalPairs, groupRoleMemberCache); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
Index: OpenMetaverse/Imaging/BakeLayer.cs
===================================================================
--- OpenMetaverse/Imaging/BakeLayer.cs (revision 2945)
+++ OpenMetaverse/Imaging/BakeLayer.cs (working copy)
@@ -125,7 +125,8 @@
}
}
- _textures.Add(index, texture);
+ //_textures.Add(index, texture);
+ _textures[index] = texture;
Logger.DebugLog(String.Format("Added texture {0} (ID: {1}) to bake {2}", index, texture.AssetID, _bakeType), _client);
}
Index: OpenMetaverse/InternalDictionary.cs
===================================================================
--- OpenMetaverse/InternalDictionary.cs (revision 2945)
+++ OpenMetaverse/InternalDictionary.cs (working copy)
@@ -26,6 +26,8 @@
using System;
using System.Collections.Generic;
+using System.Reflection;
+using System.Threading;
namespace OpenMetaverse
{
@@ -43,7 +45,7 @@
/// <summary>Internal dictionary that this class wraps around. Do not
/// modify or enumerate the contents of this dictionary without locking
/// on this member</summary>
- internal Dictionary<TKey, TValue> Dictionary;
+ public Dictionary<TKey, TValue> Dictionary;
/// <summary>
/// Gets the number of Key/Value pairs contained in the <seealso cref="T:InternalDictionary"/>
@@ -125,6 +127,7 @@
/// </example>
public bool TryGetValue(TKey key, out TValue value)
{
+ ConfirmOuterModifierIsLocking();
lock (Dictionary)
{
return Dictionary.TryGetValue(key, out value);
@@ -274,6 +277,7 @@
/// <returns><see langword="true"/> if found, <see langword="false"/> otherwise</returns>
public bool ContainsKey(TKey key)
{
+ ConfirmOuterModifierIsLocking();
return Dictionary.ContainsKey(key);
}
@@ -282,6 +286,7 @@
/// <returns><see langword="true"/> if found, <see langword="false"/> otherwise</returns>
public bool ContainsValue(TValue value)
{
+ ConfirmOuterModifierIsLocking();
return Dictionary.ContainsValue(value);
}
@@ -293,6 +298,7 @@
/// <param name="value">The value</param>
internal void Add(TKey key, TValue value)
{
+ ConfirmOuterModifierIsLocking();
lock (Dictionary)
Dictionary.Add(key, value);
}
@@ -304,6 +310,7 @@
/// <returns><see langword="true"/> if successful, <see langword="false"/> otherwise</returns>
internal bool Remove(TKey key)
{
+ ConfirmOuterModifierIsLocking();
lock (Dictionary)
return Dictionary.Remove(key);
}
@@ -317,14 +324,44 @@
{
get
{
+ ConfirmOuterModifierIsLocking();
lock (Dictionary)
return Dictionary[key];
}
internal set
{
+ ConfirmOuterModifierIsLocking();
lock (Dictionary)
Dictionary[key] = value;
}
}
+ private void ConfirmOuterModifierIsLocking()
+ {
+ System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(2);
+ System.Diagnostics.StackFrame sf = st.GetFrame(0);
+ MethodBase mb = sf.GetMethod();
+ if (!mb.DeclaringType.Namespace.StartsWith("OpenMetaverse")) return;
+
+ bool badGuy = false;
+ Thread t = new Thread(() =>
+ {
+ if (!Monitor.TryEnter(Dictionary))
+ {
+ //all is good!
+ }
+ else
+ {
+ Monitor.Exit(Dictionary);
+ //throw badGuy;
+ badGuy = true;
+ }
+ });
+ t.Start();
+ t.Join();
+ if (!badGuy) return;
+ throw new Exception(string.Format("{0}.{1} forgot to lock!", mb.DeclaringType.FullName, mb.Name));
+ }
+
+
}
}
Index: OpenMetaverse/Logger.cs
===================================================================
--- OpenMetaverse/Logger.cs (revision 2945)
+++ OpenMetaverse/Logger.cs (working copy)
@@ -82,6 +82,10 @@
Log(message, level, null, null);
}
+ public static void Log(object message, GridClient client)
+ {
+ Log(message, Helpers.LogLevel.Info, client);
+ }
/// <summary>
/// Send a log message to the logging engine
/// </summary>
@@ -183,5 +187,10 @@
LogInstance.Debug(message);
}
}
+
+ public static void Log(string message)
+ {
+ Log(message, Helpers.LogLevel.Info);
+ }
}
}
Index: OpenMetaverse/Login.cs
===================================================================
--- OpenMetaverse/Login.cs (revision 2945)
+++ OpenMetaverse/Login.cs (working copy)
@@ -1083,7 +1083,7 @@
InternalStatusCode = status;
InternalLoginMessage = message;
- Logger.DebugLog("Login status: " + status.ToString() + ": " + message, Client);
+ Logger.Log("Login status: " + status.ToString() + ": " + message, Client);
// If we reached a login resolution trigger the event
if (status == LoginStatus.Success || status == LoginStatus.Failed)
Index: OpenMetaverse/Messages/LindenMessages.cs
===================================================================
--- OpenMetaverse/Messages/LindenMessages.cs (revision 2945)
+++ OpenMetaverse/Messages/LindenMessages.cs (working copy)
@@ -1167,7 +1167,7 @@
AgentID = agentMap["AgentID"].AsUUID();
OSDArray groupArray = (OSDArray)map["GroupData"];
- OSDArray newGroupArray = (OSDArray)map["NewGroupData"];
+ //OSDArray newGroupArray = (OSDArray)map["NewGroupData"];
GroupDataBlock = new GroupData[groupArray.Count];
@@ -1187,15 +1187,15 @@
GroupDataBlock[i] = groupData;
}
- NewGroupDataBlock = new NewGroupData[newGroupArray.Count];
+ //NewGroupDataBlock = new NewGroupData[newGroupArray.Count];
- for (int i = 0; i < newGroupArray.Count; i++)
- {
- OSDMap newGroupMap = (OSDMap)newGroupArray[i];
- NewGroupData newGroupData = new NewGroupData();
- newGroupData.ListInProfile = newGroupMap["ListInProfile"].AsBoolean();
- NewGroupDataBlock[i] = newGroupData;
- }
+ //for (int i = 0; i < newGroupArray.Count; i++)
+ //{
+ // OSDMap newGroupMap = (OSDMap)newGroupArray[i];
+ // NewGroupData newGroupData = new NewGroupData();
+ // newGroupData.ListInProfile = newGroupMap["ListInProfile"].AsBoolean();
+ // NewGroupDataBlock[i] = newGroupData;
+ //}
}
}
Index: OpenMetaverse/NetworkManager.cs
===================================================================
--- OpenMetaverse/NetworkManager.cs (revision 2945)
+++ OpenMetaverse/NetworkManager.cs (working copy)
@@ -64,6 +64,8 @@
ClientInitiated,
/// <summary>The server notified us that it is disconnecting</summary>
ServerInitiated,
+ /// <summary>The server notified us that it is disconnecting</summary>
+ TeleportInitiated,
/// <summary>Either a socket was closed or network traffic timed out</summary>
NetworkTimeout,
/// <summary>The last active simulator shut down</summary>
@@ -267,7 +269,7 @@
/// <summary>Handlers for incoming capability events</summary>
internal CapsEventDictionary CapsEvents;
/// <summary>Handlers for incoming packets</summary>
- internal PacketEventDictionary PacketEvents;
+ public PacketEventDictionary PacketEvents;
/// <summary>Incoming packets that are awaiting handling</summary>
internal BlockingQueue<IncomingPacket> PacketInbox = new BlockingQueue<IncomingPacket>(Settings.PACKET_INBOX_SIZE);
/// <summary>Outgoing packets that are awaiting handling</summary>
@@ -292,6 +294,7 @@
// Register internal CAPS callbacks
RegisterEventCallback("EnableSimulator", new Caps.EventQueueCallback(EnableSimulatorHandler));
+ RegisterEventCallback("DisableSimulator", new Caps.EventQueueCallback(DisableSimulatorCapsHandler));
// Register the internal callbacks
RegisterCallback(PacketType.RegionHandshake, new PacketCallback(RegionHandshakeHandler));
@@ -414,7 +417,7 @@
if (simulator == null)
{
// We're not tracking this sim, create a new Simulator object
- simulator = new Simulator(Client, endPoint, handle);
+ simulator = Simulator.Create(Client, endPoint, handle);
// Immediately add this simulator to the list of current sims. It will be removed if the
// connection fails
@@ -482,9 +485,14 @@
}
else
{
+ //if (OnSimDisconnected != null)
+ //{
+ // try { OnSimDisconnected(simulator,DisconnectType.NetworkTimeout); }
+ // catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
+ //}
// Connection failed, remove this simulator from our list and destroy it
- lock (Simulators) Simulators.Remove(simulator);
- return null;
+ // lock (Simulators) Simulators.Remove(simulator);
+ return simulator;
}
}
else if (setDefault)
@@ -564,22 +572,23 @@
/// </summary>
/// <param name="sim"></param>
/// <param name="sendCloseCircuit"></param>
- public void DisconnectSim(Simulator sim, bool sendCloseCircuit)
+ public void DisconnectSim(Simulator sim, bool sendCloseCircuit,DisconnectType disconnectType)
{
if (sim != null)
{
- sim.Disconnect(sendCloseCircuit);
+ sim.Disconnect(sendCloseCircuit, disconnectType);
// Fire the SimDisconnected event if a handler is registered
if (OnSimDisconnected != null)
{
- try { OnSimDisconnected(sim, DisconnectType.NetworkTimeout); }
+ try { OnSimDisconnected(sim, disconnectType); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
- lock (Simulators) Simulators.Remove(sim);
+ //if (disconnectType == DisconnectType.ClientInitiated)
+ lock (Simulators) Simulators.Remove(sim);
- if (Simulators.Count == 0) Shutdown(DisconnectType.SimShutdown);
+ if (Simulators.Count == 0) Shutdown(disconnectType/* | DisconnectType.SimShutdown*/);
}
else
{
@@ -623,7 +632,7 @@
if (CurrentSim != null)
{
// Kill the connection to the curent simulator
- CurrentSim.Disconnect(sendCloseCircuit);
+ CurrentSim.Disconnect(sendCloseCircuit,type);
// Fire the SimDisconnected event if a handler is registered
if (OnSimDisconnected != null)
@@ -780,6 +789,7 @@
Timer timer = DisconnectTimer;
if (timer != null)
timer.Dispose();
+ timer = null;
connected = false;
}
else if (CurrentSim.DisconnectCandidate)
@@ -1034,11 +1044,18 @@
}
}
+ private void DisableSimulatorCapsHandler(string capsKey, IMessage message, Simulator simulator)
+ {
+ if (!Client.Settings.MULTIPLE_SIMS) return;
+ Logger.Log("Received a CAPS Based DisableSimulator packet from " + simulator + ", shutting it down", Client);
+ DisconnectSim(simulator, false, DisconnectType.ServerInitiated);
+ }
+
private void DisableSimulatorHandler(Packet packet, Simulator simulator)
{
Logger.DebugLog("Received a DisableSimulator packet from " + simulator + ", shutting it down", Client);
- DisconnectSim(simulator, false);
+ DisconnectSim(simulator, false, DisconnectType.ServerInitiated);
}
private void KickUserHandler(Packet packet, Simulator simulator)
Index: OpenMetaverse/ObjectManager.cs
===================================================================
--- OpenMetaverse/ObjectManager.cs (revision 2945)
+++ OpenMetaverse/ObjectManager.cs (working copy)
@@ -2863,6 +2863,10 @@
protected void InterpolationTimer_Elapsed(object obj)
{
int elapsed = 0;
+ if (!Client.Settings.USE_INTERPOLATION_TIMER)
+ {
+ return;
+ }
if (Client.Network.Connected)
{
Index: OpenMetaverse/ParcelManager.cs
===================================================================
--- OpenMetaverse/ParcelManager.cs (revision 2945)
+++ OpenMetaverse/ParcelManager.cs (working copy)
@@ -411,6 +411,73 @@
#endregion Structs
+ /// <summary>
+ /// Parcel Media Command used in ParcelMediaCommandMessage
+ /// </summary>
+ public enum ParcelMediaCommand: uint
+ {
+ /// <summary>
+ /// 0 - stop the media stream and go back to the first frame
+ /// </summary>
+ Stop = 0,
+ /// <summary>
+ /// 1 - pause the media stream (stop playing but stay on current frame)
+ /// </summary>
+ Pause,
+ /// <summary>
+ /// 2 - start the current media stream playing and stop when the end is reached
+ /// </summary>
+ Play,
+ /// <summary>
+ /// 3 - start the current media stream playing,
+ /// loop to the beginning when the end is reached and continue to play
+ /// </summary>
+ Loop,
+ /// <summary>
+ /// 4 - [key texture] specifies the texture to replace with video
+ /// Note: If passing the key of a texture, it must be explicitly typecast as a key,
+ /// not just passed within double quotes.
+ /// </summary>
+ Texture,
+ /// <summary>
+ /// 5 - [string url] specifies the movie URL (254 characters)
+ /// </summary>
+ URL,
+ /// <summary>
+ /// 6 - [float time] specifies the time index at which to begin playing
+ /// </summary>
+ Time,
+ /// <summary>
+ /// 7 - [key agent] specifies a single agent to apply the media command to
+ /// </summary>
+ Agent,
+ /// <summary>
+ /// 8 - unloads the stream. While the stop command sets the texture to the first frame of the movie,
+ /// unload resets it to the real texture that the movie was replacing.
+ /// </summary>
+ Unload,
+ /// <summary>
+ /// 9 - [integer enable]
+ /// turns on/off the auto align feature, similar to the auto align checkbox in the parcel media properties
+ /// (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter.
+ /// </summary>
+ AutoAlign,
+ /// <summary>
+ /// 10 - [string] Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only).
+ /// Use "text/html" for HTML.
+ /// </summary>
+ Type,
+ /// <summary>
+ /// 11 - [integer x, integer y] Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only).
+ /// Note: this might still not be working
+ /// </summary>
+ Size,
+ /// <summary>
+ /// 12 - [string] Sets a description for the media being displayed (1.19.1 RC0 and later only).
+ /// </summary>
+ Desc
+ }
+
#region Parcel Class
/// <summary>
@@ -839,6 +906,16 @@
/// <param name="media">A struct containing updated media information</param>
public delegate void ParcelMediaUpdateReplyCallback(Simulator simulator, ParcelMedia media);
+ /// <summary>
+ /// Fired when a ParcelMediaCommandMessage packet is received, this occurs when the media on the parcel sends a specialized event
+ /// </summary>
+ /// <param name="simulator">A reference to the simulator object</param>
+ /// <param name="sequence">The sequence the parcel command belongs to</param>
+ /// <param name="flags">Updated parcel information</param>
+ /// <param name="command">The command executed on the Parcel</param>
+ /// <param name="time">The time operand for some parcel commands</param>
+ public delegate void ParcelMediaCommandMessageCallback(Simulator simulator, uint sequence, ParcelFlags flags, ParcelMediaCommand command, float time);
+
#endregion Delegates
#region Events
@@ -867,6 +944,10 @@
/// <summary>Fired when the Agent receives a <seealso cref="Packets.ParcelMediaUpdatePacket"/> which
/// occurs when the parcel media information is changed for the current parcel the Agent is over</summary>
public event ParcelMediaUpdateReplyCallback OnParcelMediaUpdate;
+ /// <summary>Fired when the Agent receives a <seealso cref="Packets.ParcelMediaCommandMessage"/> which
+ /// occurs when the parcel media has a specialized event like starting and looping command on the media is raised
+ /// for the current parcel the Agent is over</summary>
+ public event ParcelMediaCommandMessageCallback OnParcelMediaCommandMessage;
#endregion Events
@@ -891,6 +972,7 @@
Client.Network.RegisterCallback(PacketType.ParcelAccessListReply, new NetworkManager.PacketCallback(ParcelAccessListReplyHandler));
Client.Network.RegisterCallback(PacketType.ForceObjectSelect, new NetworkManager.PacketCallback(SelectParcelObjectsReplyHandler));
Client.Network.RegisterCallback(PacketType.ParcelMediaUpdate, new NetworkManager.PacketCallback(ParcelMediaUpdateHandler));
+ Client.Network.RegisterCallback(PacketType.ParcelMediaCommandMessage, new NetworkManager.PacketCallback(ParcelMediaCommandMessageHandler));
Client.Network.RegisterCallback(PacketType.ParcelOverlay, new NetworkManager.PacketCallback(ParcelOverlayHandler));
}
@@ -1792,6 +1874,17 @@
}
}
+ private void ParcelMediaCommandMessageHandler(Packet packet, Simulator simulator)
+ {
+ if (OnParcelMediaCommandMessage != null)
+ {
+ ParcelMediaCommandMessagePacket pmc = (ParcelMediaCommandMessagePacket)packet;
+ ParcelMediaCommandMessagePacket.CommandBlockBlock block = pmc.CommandBlock;
+ try { OnParcelMediaCommandMessage(simulator, pmc.Header.Sequence, (ParcelFlags)block.Flags, (ParcelMediaCommand)block.Command, block.Time); }
+ catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
+ }
+ }
+
private void ParcelOverlayHandler(Packet packet, Simulator simulator)
{
const int OVERLAY_COUNT = 4;
Index: OpenMetaverse/Simulator.cs
===================================================================
--- OpenMetaverse/Simulator.cs (revision 2945)
+++ OpenMetaverse/Simulator.cs (working copy)
@@ -448,18 +448,46 @@
/// <param name="client">Reference to the GridClient object</param>
/// <param name="address">IPEndPoint of the simulator</param>
/// <param name="handle">handle of the simulator</param>
- public Simulator(GridClient client, IPEndPoint address, ulong handle)
+ private Simulator(GridClient client, IPEndPoint address, ulong handle)
: base(address)
{
Client = client;
Handle = handle;
+ ReInit();
+ }
+
+ private void ReInit()
+ {
Network = Client.Network;
PacketArchive = new IncomingPacketIDCollection(Settings.PACKET_ARCHIVE_SIZE);
InBytes = new Queue<long>(Client.Settings.STATS_QUEUE_SIZE);
OutBytes = new Queue<long>(Client.Settings.STATS_QUEUE_SIZE);
}
+
+ readonly static Dictionary<GridClient, Dictionary<ulong, Simulator>> savedSims = new Dictionary<GridClient, Dictionary<ulong, Simulator>>();
+ public static Simulator Create(GridClient client, IPEndPoint point, ulong handle)
+ {
+ Dictionary<ulong, Simulator> dict;
+ lock (savedSims) if (!savedSims.TryGetValue(client, out dict))
+ {
+ dict = new Dictionary<ulong, Simulator>();
+ savedSims.Add(client, dict);
+ }
+ Simulator sim;
+ lock (dict) if (!dict.TryGetValue(handle, out sim))
+ {
+ sim = new Simulator(client, point, handle);
+ dict.Add(handle,sim);
+ } else
+ {
+ sim.ReInit();
+ }
+ return sim;
+
+ }
+
/// <summary>
/// Called when this Simulator object is being destroyed
/// </summary>
@@ -529,7 +557,7 @@
if (Client.Settings.SEND_AGENT_UPDATES)
Client.Self.Movement.SendUpdate(true, this);
- if (!ConnectedEvent.WaitOne(Client.Settings.SIMULATOR_TIMEOUT, false))
+ if (!ConnectedEvent.WaitOne(Client.Settings.LOGIN_TIMEOUT, false))
{
Logger.Log("Giving up on waiting for RegionHandshake for " + this.ToString(),
Helpers.LogLevel.Warning, Client);
@@ -571,22 +599,36 @@
/// Disconnect from this simulator
/// </summary>
public void Disconnect(bool sendCloseCircuit)
+ {
+ Disconnect(sendCloseCircuit,NetworkManager.DisconnectType.ClientInitiated);
+ }
+ public void Disconnect(bool sendCloseCircuit, NetworkManager.DisconnectType disconnectType)
{
+ //lets wait until the server makes a desision
+ if (disconnectType == NetworkManager.DisconnectType.TeleportInitiated
+ || disconnectType == NetworkManager.DisconnectType.NetworkTimeout) return;
if (connected)
{
connected = false;
+ if (disconnectType != NetworkManager.DisconnectType.ServerInitiated)
+ {
+
// Destroy the timers
if (AckTimer != null) AckTimer.Dispose();
+ AckTimer = null;
if (StatsTimer != null) StatsTimer.Dispose();
+ StatsTimer = null;
if (PingTimer != null) PingTimer.Dispose();
+ PingTimer = null;
// Kill the current CAPS system
- if (Caps != null)
+ if (Caps != null )
{
Caps.Disconnect(true);
Caps = null;
}
+ }
if (sendCloseCircuit)
{
Index: OpenMetaverse/TexturePipeline.cs
===================================================================
--- OpenMetaverse/TexturePipeline.cs (revision 2945)
+++ OpenMetaverse/TexturePipeline.cs (working copy)
@@ -130,13 +130,13 @@
/// <summary>An array of worker slots which shows the availablity status of the slot</summary>
private readonly int[] threadpoolSlots;
/// <summary>The primary thread which manages the requests.</summary>
- private readonly Thread downloadMaster;
+ private Thread downloadMaster;
/// <summary>true if the TexturePipeline is currently running</summary>
bool _Running;
/// <summary>A synchronization object used by the primary thread</summary>
- private object lockerObject = new object();
+ readonly private object lockerObject = new object();
/// <summary>A refresh timer used to increase the priority of stalled requests</summary>
- private readonly System.Timers.Timer RefreshDownloadsTimer =
+ private System.Timers.Timer RefreshDownloadsTimer =
new System.Timers.Timer(Settings.PIPELINE_REFRESH_INTERVAL);
/// <summary>Current number of pending and in-process transfers</summary>
@@ -168,12 +168,6 @@
client.Network.OnConnected += delegate { Startup(); };
client.Network.OnDisconnected += delegate { Shutdown(); };
- // Instantiate master thread that manages the request pool
- downloadMaster = new Thread(DownloadThread);
- downloadMaster.Name = "TexturePipeline";
- downloadMaster.IsBackground = true;
-
- RefreshDownloadsTimer.Elapsed += RefreshDownloadsTimer_Elapsed;
}
/// <summary>
@@ -186,6 +180,21 @@
_Running = true;
+ if (downloadMaster==null)
+ {
+ // Instantiate master thread that manages the request pool
+ downloadMaster = new Thread(DownloadThread);
+ downloadMaster.Name = "TexturePipeline";
+ downloadMaster.IsBackground = true;
+ }
+ if (RefreshDownloadsTimer==null)
+ {
+ RefreshDownloadsTimer =
+ new System.Timers.Timer(Settings.PIPELINE_REFRESH_INTERVAL);
+ RefreshDownloadsTimer.Elapsed += RefreshDownloadsTimer_Elapsed;
+ }
+
+
_Client.Network.RegisterCallback(PacketType.ImageData, ImageDataHandler);
_Client.Network.RegisterCallback(PacketType.ImagePacket, ImagePacketHandler);
_Client.Network.RegisterCallback(PacketType.ImageNotInDatabase, ImageNotInDatabaseHandler);
@@ -205,6 +214,8 @@
TotalTime, NetworkTime, Math.Round(TotalBytes / NetworkTime.TotalSeconds / 60, 2), TotalBytes), Helpers.LogLevel.Debug);
#endif
RefreshDownloadsTimer.Stop();
+ RefreshDownloadsTimer = null;
+ downloadMaster = null;
_Client.Network.UnregisterCallback(PacketType.ImageNotInDatabase, ImageNotInDatabaseHandler);
_Client.Network.UnregisterCallback(PacketType.ImageData, ImageDataHandler);
@@ -657,7 +668,10 @@
task.Transfer.ID, Helpers.LogLevel.Warning, _Client);
_Transfers.Remove(task.Transfer.ID);
- resetEvents[task.RequestSlot].Set(); // free up request slot
+ if (task.RequestSlot >= 0) resetEvents[task.RequestSlot].Set(); // free up request slot
+ else
+ Logger.Log("Negative slot in download for " +
+ task.Transfer.ID, Helpers.LogLevel.Warning, _Client);
foreach (TextureDownloadCallback callback in task.Callbacks)
callback(TextureRequestState.Timeout, new AssetTexture(task.RequestID, task.Transfer.AssetData));
Index: OpenMetaverseTypes/DoubleDictionary.cs
===================================================================
--- OpenMetaverseTypes/DoubleDictionary.cs (revision 2945)
+++ OpenMetaverseTypes/DoubleDictionary.cs (working copy)
@@ -28,11 +28,11 @@
using System.Threading;
using System.Collections.Generic;
-#if VISUAL_STUDIO
+//#if VISUAL_STUDIO
using ReaderWriterLockImpl = System.Threading.ReaderWriterLockSlim;
-#else
-using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim;
-#endif
+//#else
+//using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim;
+//#endif
namespace OpenMetaverse
{