updates agent is now wearing so outfits use multi attachments (still need to find out where the on login is set!)

This commit is contained in:
Madpeter 2020-04-24 01:47:49 +01:00
parent 1aef438b37
commit 753945dc2f

View file

@ -375,7 +375,9 @@ namespace OpenMetaverse
#region Private Members #region Private Members
/// <summary>A cache of wearables currently being worn</summary> /// <summary>A cache of wearables currently being worn</summary>
private MultiValueDictionary<WearableType, WearableData> Wearables = new MultiValueDictionary<WearableType, WearableData>(); private MultiValueDictionary<WearableType, WearableData> Wearables = new MultiValueDictionary<WearableType, WearableData>();
/// <summary>A cache of textures currently being worn</summary> /// <summary>A cache of textures currently being worn</summary>
private TextureData[] Textures = new TextureData[(int)AvatarTextureIndex.NumberOfEntries]; private TextureData[] Textures = new TextureData[(int)AvatarTextureIndex.NumberOfEntries];
/// <summary>Incrementing serial number for AgentCachedTexture packets</summary> /// <summary>Incrementing serial number for AgentCachedTexture packets</summary>
@ -456,7 +458,7 @@ namespace OpenMetaverse
/// </summary> /// </summary>
public void RequestSetAppearance() public void RequestSetAppearance()
{ {
RequestSetAppearance(false); SendAgentIsNowWearing();
} }
/// <summary> /// <summary>
@ -761,7 +763,7 @@ namespace OpenMetaverse
/// be added to the outfit</param> /// be added to the outfit</param>
public void AddToOutfit(List<InventoryItem> wearableItems) public void AddToOutfit(List<InventoryItem> wearableItems)
{ {
AddToOutfit(wearableItems, true); AddToOutfit(wearableItems, false);
} }
/// <summary> /// <summary>
@ -1005,6 +1007,7 @@ namespace OpenMetaverse
#region Attachments #region Attachments
/// <summary> /// <summary>
/// Adds a list of attachments to our agent /// Adds a list of attachments to our agent
/// </summary> /// </summary>
@ -1012,7 +1015,7 @@ namespace OpenMetaverse
/// <param name="removeExistingFirst">If true, tells simulator to remove existing attachment /// <param name="removeExistingFirst">If true, tells simulator to remove existing attachment
/// <param name="replace">If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments)</param> /// <param name="replace">If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments)</param>
/// first</param> /// first</param>
public void AddAttachments(List<InventoryItem> attachments, bool removeExistingFirst, bool replace = true) public void AddAttachments(List<InventoryItem> attachments, bool removeExistingFirst, bool replace = false)
{ {
// Use RezMultipleAttachmentsFromInv to clear out current attachments, and attach new ones // Use RezMultipleAttachmentsFromInv to clear out current attachments, and attach new ones
RezMultipleAttachmentsFromInvPacket attachmentsPacket = new RezMultipleAttachmentsFromInvPacket RezMultipleAttachmentsFromInvPacket attachmentsPacket = new RezMultipleAttachmentsFromInvPacket
@ -1198,6 +1201,58 @@ namespace OpenMetaverse
/// </summary> /// </summary>
private void SendAgentIsNowWearing() private void SendAgentIsNowWearing()
{ {
List<AgentIsNowWearingPacket.WearableDataBlock> temp_block_storage = new List<AgentIsNowWearingPacket.WearableDataBlock> ();
lock (Wearables)
{
List<WearableType> multiattached = new List<WearableType>();
int WearableData_index = 0;
for (int i = 0; i < WEARABLE_COUNT; i++)
{
WearableType type = (WearableType)i;
bool use_multi = false;
if (Wearables.ContainsKey(type) == true)
{
if (Wearables[type].Count > 1)
{
if (multiattached.Contains(type) == false)
{
multiattached.Add(type);
}
use_multi = true;
}
}
if (use_multi == false)
{
temp_block_storage.Add(new AgentIsNowWearingPacket.WearableDataBlock
{
WearableType = (byte)WearableData_index,
// This appears to be hacked on SL server side to support multi-layers
ItemID = Wearables.ContainsKey(type) ?
(Wearables[type].First()?.ItemID ?? UUID.Zero)
: UUID.Zero
});
WearableData_index++;
}
}
/* hacky multi layers
foreach(WearableType T in multiattached)
{
int index = 0;
while(index < Wearables[T].Count)
{
temp_block_storage.Add(new AgentIsNowWearingPacket.WearableDataBlock
{
WearableType = (byte)WearableData_index,
ItemID = Wearables.ContainsKey(T) ? (Wearables[T].ElementAt(index) ?.ItemID ?? UUID.Zero)
: UUID.Zero
});
WearableData_index++;
index++;
}
}
*/
}
AgentIsNowWearingPacket wearing = new AgentIsNowWearingPacket AgentIsNowWearingPacket wearing = new AgentIsNowWearingPacket
{ {
AgentData = AgentData =
@ -1205,26 +1260,16 @@ namespace OpenMetaverse
AgentID = Client.Self.AgentID, AgentID = Client.Self.AgentID,
SessionID = Client.Self.SessionID SessionID = Client.Self.SessionID
}, },
WearableData = new AgentIsNowWearingPacket.WearableDataBlock[WEARABLE_COUNT] WearableData = new AgentIsNowWearingPacket.WearableDataBlock[temp_block_storage.Count]
}; };
int blockindex = 0;
lock (Wearables) foreach (AgentIsNowWearingPacket.WearableDataBlock block in temp_block_storage)
{ {
for (int i = 0; i < WEARABLE_COUNT; i++) wearing.WearableData[blockindex] = block;
{ blockindex++;
WearableType type = (WearableType)i;
wearing.WearableData[i] = new AgentIsNowWearingPacket.WearableDataBlock
{
WearableType = (byte) i,
// This appears to be hacked on SL server side to support multi-layers
ItemID = Wearables.ContainsKey(type) ?
(Wearables[type].First()?.ItemID ?? UUID.Zero)
: UUID.Zero
};
}
} }
Client.Network.SendPacket(wearing); Client.Network.SendPacket(wearing);
} }
/// <summary> /// <summary>
@ -2267,83 +2312,40 @@ namespace OpenMetaverse
protected void AgentWearablesUpdateHandler(object sender, PacketReceivedEventArgs e) protected void AgentWearablesUpdateHandler(object sender, PacketReceivedEventArgs e)
{ {
bool changed = false;
var update = (AgentWearablesUpdatePacket)e.Packet; var update = (AgentWearablesUpdatePacket)e.Packet;
lock (Wearables) lock (Wearables)
{ {
#region Test if anything changed in this update if (Wearables.GetHashCode() != update.GetHashCode())
foreach (var block in update.WearableData)
{
if (block.AssetID != UUID.Zero)
{
WearableType type = (WearableType)block.WearableType;
if (Wearables.ContainsKey(type))
{
// HACK: I'm so tired and this is so bad.
bool match = false;
foreach (var wearable in Wearables.Where(w => w.Key == type).SelectMany(w => w.Value))
{
if (wearable.AssetID == block.AssetID || wearable.ItemID == block.ItemID)
{
match = true;
}
}
changed = !match;
if (changed) break;
}
else
{
// A wearable is now set for this index
changed = true;
break;
}
}
else if (Wearables.ContainsKey((WearableType)block.WearableType))
{
// This index is now empty
changed = true;
break;
}
}
#endregion Test if anything changed in this update
if (changed)
{ {
Logger.DebugLog("New wearables received in AgentWearablesUpdate"); Logger.DebugLog("New wearables received in AgentWearablesUpdate");
Wearables.Clear(); Wearables.Clear();
foreach (AgentWearablesUpdatePacket.WearableDataBlock block in update.WearableData) foreach (AgentWearablesUpdatePacket.WearableDataBlock block in update.WearableData)
{ {
if (block.AssetID == UUID.Zero) continue; if (block.AssetID != UUID.Zero)
WearableType type = (WearableType)block.WearableType;
WearableData data = new WearableData
{ {
Asset = null, WearableType type = (WearableType)block.WearableType;
AssetID = block.AssetID, WearableData data = new WearableData
AssetType = WearableTypeToAssetType(type), {
ItemID = block.ItemID, Asset = null,
WearableType = type AssetID = block.AssetID,
}; AssetType = WearableTypeToAssetType(type),
ItemID = block.ItemID,
WearableType = type
};
// Add this wearable to our collection // Add this wearable to our collection
Wearables.Add(type, data); Wearables.Add(type, data);
}
} }
OnAgentWearables(new AgentWearablesReplyEventArgs());
} }
else else
{ {
Logger.DebugLog("Duplicate AgentWearablesUpdate received, discarding"); Logger.DebugLog("Duplicate AgentWearablesUpdate received, discarding");
} }
} }
if (changed)
{
// Fire the callback
OnAgentWearables(new AgentWearablesReplyEventArgs());
}
} }
protected void RebakeAvatarTexturesHandler(object sender, PacketReceivedEventArgs e) protected void RebakeAvatarTexturesHandler(object sender, PacketReceivedEventArgs e)