cinderblocks / libremetaverse

An fork of the libopenmetaverse library striving for performance improvements and up-to-date compatibility with SL/OS/Halcyon
BSD 3-Clause "New" or "Revised" License
60 stars 40 forks source link

Avatars with multiple attachments on the same point don't get fully rezzed #76

Open GwynethLlewelyn opened 2 years ago

GwynethLlewelyn commented 2 years ago

After getting some reports that my bots (in SL) were 'missing parts' (e.g. shoes not showing, the avatar is barefoot) or 'see-through' — essentially, clothing that uses alpha layers to mask imperfections/irregularities on mesh clothing — I logged in using the bots' account (using both Firestorm and the official SL Viewer), and everything was rezzed properly on the default outfit; but when the avatar is logged in via LibreMetaverse, there are, indeed, 'missing attachments'.

I first thought it was just a local viewer issue, e.g. some items take longer to rez than others (like some HUDs with an insane number of textures in them). However, that theory didn't fit the facts: it's pretty much irrelevant which viewer or operating system is used, or if the cache has been freshly deleted, or wherever you log in from (different networks, local Ethernet, Wi-Fi...), or whatever region the avatars are in, it's always the same avatars that always miss the exact same items.

Because this happens to some avatars but not all I was stumped about this for quite a while, until I noticed a pattern: the avatars missing items/clothing seem to have multiple attachments/layers/clothes on the same attachment point.

This is, of course, not an issue with contemporary viewers: the ability to have multiple items on the same attachment point (or multiple layers of clothing on the same layer) has been around for quite a while (a decade or so) in SL, and it works flawlessly on OpenSimulator as well.

Obviously, this issue can be side-stepped simply by making sure that only one item is attached per attachment point.

Since I haven't seen this issue raised before, I wonder if this has some kind of workaround, or is there no other choice but to hack at the code and figure out what's not working as it should?

github-actions[bot] commented 2 years ago

Thank you for taking the time to improve LibreMetaverse! We will review your contribution shortly.

Madpeterz commented 7 months ago

I have been playing with this myself its not just a render issue the client only seems to get the packet for 1 of the objects on a attachment point

to test this I attached 2 objects to the same point with Hover text "Red" and "Yellow" (I also color coded them)

and in Packets.cs

I added

                    string T = Utils.BytesToString(Text);
                    if ((T == "Yellow") || (T == "Red"))
                    {
                        Logger.DebugLog("See packet for object: " + T);
                    }

and only 1 of the packets will turn up.

Madpeterz commented 7 months ago

the attachments are loaded before RequestSetAppearance is called so the AppearanceManager does not have anything todo with loading the attachments from the grid.

Madpeterz commented 7 months ago

still digging looks like the ObjectUpdatePacket never gets other attachments, this leads me to thinking that we are missing a flag to support multiple attachments before making the request for objects.

Madpeterz commented 7 months ago

I now have working multiple attachments (kinda hacky but it works)

AppearanceManager.cs (near line: 2158)

            GetFolderWearables(COF.UUID, out List<InventoryWearable> wearables, out List<InventoryItem> attachments);
            Client.Appearance.AddAttachments(attachments, false, false);

            return COF;

AppearanceManager.cs (near line: 2399)

        private bool GetFolderWearables(UUID folder, out List<InventoryWearable> wearables, out List<InventoryItem> attachments)
        {
            wearables = new List<InventoryWearable>();
            attachments = new List<InventoryItem>();
            KeyValuePair<string, List<InventoryBase>> reply = Client.Inventory.FolderContentsWithReply(folder, Client.Self.AgentID, true, true, InventorySortOrder.ByName, INVENTORY_TIMEOUT, false);
            foreach(InventoryBase entry in reply.Value)
            {
                if(entry == null)
                {
                    continue;
                }
                if(entry is InventoryWearable wearable)
                {
                    Logger.DebugLog("Adding wearable " + wearable.Name, Client);
                    wearables.Add(wearable);
                }
                else if (entry is InventoryAttachment attachment)
                {
                    Logger.DebugLog("Adding attachment (attachment) " + attachment.Name, Client);
                    attachments.Add(attachment);
                }
                else if (entry is InventoryObject inventoryObject)
                {
                    Logger.DebugLog("Adding attachment (object) " + inventoryObject.Name, Client);
                    attachments.Add(inventoryObject);
                }
                else
                {
                    Logger.DebugLog("Ignoring inventory item " + entry.Name, Client);
                }
            }
            return true;
        }
Ripmax commented 7 months ago

I can confirm @Madpeterz amendments solve the issue. Have implemented this into my project and is working fine now.

Thank you!