Skip to content

Added CreateLinksAsync and AddLinks #158

Open
TsengSR wants to merge 3 commits into
cinderblocks:masterfrom
TsengSR:feautre/cof-addlinks
Open

Added CreateLinksAsync and AddLinks #158
TsengSR wants to merge 3 commits into
cinderblocks:masterfrom
TsengSR:feautre/cof-addlinks

Conversation

@TsengSR
Copy link
Copy Markdown

@TsengSR TsengSR commented May 3, 2026

Added CreateLinksAsync and AddLinks which allows to create multiple Links in a single request when AIS3 is supported which drastically reduces the competition time when adding 5+ links, i.e. for adding/replacing outfits

Fixes a minor bug in ReplaceOutfit that will create a folder link for folders that are not in children of "Outfits", where its not desired to do a folder link (folder Links are only used as indicator for the currently active appearance in SL Viewers Appearance tab).

In my tests even moderately sized outfits of 17 items took 5-10 seconds until the outfit was fully work which did drive me insane.

With the batched AddLinks AIS3 Request, the outfit switchs and appears fully in-world (assuming work items existed in the Viewers Cache already) is less than 1 second now. It falls back to one request per link if AIS3 isn't supported. Dunno if the old API has similar batching capabilities.

TsengSR added 2 commits May 4, 2026 00:48
…inks in a single request when AIS3 is supported which drastically reduces the competition time when adding 5+ links, i.e. for adding/replacing outfits

Fixes a minor bug in ReplaceOutfit that will create a folder link for folders that are not in children of "Outfits", where its not desired to do a folder link (folder Links are only used as indicator for the currently active appearance in SL Viewers Appearance tab)
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds AIS3-based batched inventory/COF link creation to speed up outfit changes, and adjusts ReplaceOutfit so the special folder link is only created for folders under the Outfits system folder.

Changes:

  • Added InventoryManager.CreateLinksAsync for creating multiple inventory links in one AIS3 request.
  • Added CurrentOutfitFolder.AddLinks and switched outfit operations to use batched link creation where possible.
  • Updated ReplaceOutfit to avoid creating COF folder links for non-Outfits descendants.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
LibreMetaverse/Inventory/InventoryManager.cs Adds the new AIS3 batch link creation API.
LibreMetaverse/Appearance/CurrentOutfitFolder.cs Uses batched COF link creation and tightens outfit-folder link behavior in outfit replacement/add flows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +523 to +543
if (client.AisClient.IsAvailable)
{
await client.Inventory.CreateLinksAsync(COF.UUID, items, success =>
{
client.Inventory.RequestFolderContents(
COF.UUID,
COF.OwnerID,
fetchFolders: true,
fetchItems: true,
order: InventorySortOrder.ByName,
cancellationToken: cancellationToken
).ConfigureAwait(false);
}, cancellationToken);
}
else
{
foreach (InventoryItem item in items)
{
await AddLink(item, cancellationToken);
}
}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole point of adding AddLinks is to update all the links in a single request, instead of a long sequence request/reply/request/reply which adds tons of latency, about half a second per link created.

Comment thread LibreMetaverse/Appearance/CurrentOutfitFolder.cs Outdated
Comment on lines +2007 to +2051
OSDArray links = new OSDArray();
foreach (InventoryBase baseItem in items)
{
switch (baseItem)
{
case InventoryItem item:
{
OSDMap link = new OSDMap
{
["linked_id"] = OSD.FromUUID(item.UUID),
["type"] = OSD.FromInteger((int)AssetType.Link),
["inv_type"] = OSD.FromInteger((int)item.InventoryType),
["name"] = OSD.FromString(item.Name),
["desc"] = OSD.FromString(item.Description)
};

links.Add(link);
break;
}
case InventoryFolder folder:
{
OSDMap link = new OSDMap
{
["linked_id"] = OSD.FromUUID(folder.UUID),
["type"] = OSD.FromInteger((int)AssetType.LinkFolder),
["inv_type"] = OSD.FromInteger((int)InventoryType.Folder),
["name"] = OSD.FromString(folder.Name),
["desc"] = OSD.FromString(string.Empty)
};

links.Add(link);
}
break;
}
}

OSDMap newInventory = new OSDMap { { "links", links } };

await Client.AisClient.CreateInventory(
folderID,
newInventory,
true,
(success, reply) => callback?.Invoke(success),
cancellationToken
).ConfigureAwait(false);
Copy link
Copy Markdown
Author

@TsengSR TsengSR May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love it when bots butcher code with non-sense.

@cinderblocks
Would calling client.Inventory.RequestFetchInventoryAsync(newItem.UUID, newItem.OwnerID, cancellationToken); in the client.Inventory.CreateLinksAsync(COF.UUID, newLinks, callback be sufficient? I'm not sure it will fetch folders like RequestFolderContents does.

Though in my personal testing I didn't notice any misssing. The COF Folder and the folder containing the orignal items do update on my Radegast Viewer and show the proper attachment/worn labels

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that would be sufficient. The only issue might be on non-AISv3 regions (none exist in Second Life for about ten years, of course). Not sure how modern the inventory API is in OpenSimulator.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not modern at all. Core doesn't implement AISv3 and has no plans to. I'd like to add it to NGC but still trying to just get the basic architecture compliant with dotnet v8+. So if supporting OpenSim is a goal the code will have to handle cases where AIS isnt present at least for some time.

Copy link
Copy Markdown
Author

@TsengSR TsengSR May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual AddLinks in COF has a fallback to iterate over the list and call AddLink (current code), when AISv3 isn't supported. But the CreateLinksAsync itself doesn't throws if unsupported. I can't even remember where I found the specifications of the endpoint back then.

Tbh I don't know if the older APIs implement batch Link creation or not. I implemented it years ago (2017 or 2018) or so in my local fork, because back then libremetaverise/libopenmetaverse was rather unmaintained and dead.

But until few weeks ago it was still sync, but when rebasing my libremetavers and Radegast i noticing that replacing outfits took forever again (5-10+ seconds) and took me a while to figure out what changed/broke it.

My main movitation back then was to make changing outfits faster, as changing an outfit did freeze the client up to 15-30 seconds (on a Duo Core back in 2017),making it completley unresponsive and slow during this process (also when done via RLV). Today it doesn't freeze the client, but its still slow because of multiple sequential async operations.

Comment on lines +2053 to +2055
else
{
throw new InvalidOperationException("Creating of batch links only supported on AIS3");
Comment on lines +511 to +535
public async Task AddLinks(IEnumerable<InventoryItem> items, CancellationToken cancellationToken = default)
{
if (COF == null)
{
return;
}

if (items == null || !items.Any())
{
return;
}

if (client.AisClient.IsAvailable)
{
await client.Inventory.CreateLinksAsync(COF.UUID, items, success =>
{
client.Inventory.RequestFolderContents(
COF.UUID,
COF.OwnerID,
fetchFolders: true,
fetchItems: true,
order: InventorySortOrder.ByName,
cancellationToken: cancellationToken
).ConfigureAwait(false);
}, cancellationToken);
Comment thread LibreMetaverse/Inventory/InventoryManager.cs Outdated
@TsengSR TsengSR force-pushed the feautre/cof-addlinks branch from 9b17943 to 0f97651 Compare May 10, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants