Merge branch 'release/2025.03' of https://github.com/secondlife/viewer

# Conflicts:
#	indra/newview/llcallingcard.cpp
#	indra/newview/llinventorybridge.cpp
#	indra/newview/skins/default/xui/en/menu_inventory.xml
#	indra/newview/skins/default/xui/en/menu_viewer.xml
#	indra/newview/skins/default/xui/ja/strings.xml
#	indra/newview/skins/default/xui/zh/strings.xml
master
Ansariel 2025-03-19 15:23:20 +01:00
commit 4e2bfd7327
30 changed files with 467 additions and 65 deletions

View File

@ -95,6 +95,8 @@ LLExperienceCache::LLExperienceCache()
LLExperienceCache::~LLExperienceCache()
{
// can exit without cleanup()
sShutdown = true;
}
void LLExperienceCache::initSingleton()

View File

@ -344,6 +344,12 @@ bool LLPacketRing::expandRing()
return true;
}
F32 LLPacketRing::getBufferLoadRate() const
{
// goes up to MAX_BUFFER_RING_SIZE
return (F32)mNumBufferedPackets / (F32)DEFAULT_BUFFER_RING_SIZE;
}
void LLPacketRing::dumpPacketRingStats()
{
mNumDroppedPacketsTotal += mNumDroppedPackets;

View File

@ -64,6 +64,7 @@ public:
S32 getNumBufferedBytes() const { return mNumBufferedBytes; }
S32 getNumDroppedPackets() const { return mNumDroppedPacketsTotal + mNumDroppedPackets; }
F32 getBufferLoadRate() const; // from 0 to 4 (0 - empty, 1 - default size is full)
void dumpPacketRingStats();
protected:
// returns 'true' if we should intentionally drop a packet

View File

@ -538,7 +538,6 @@ public:
//void buildMessage();
S32 zeroCode(U8 **data, S32 *data_size);
S32 zeroCodeExpand(U8 **data, S32 *data_size);
S32 zeroCodeAdjustCurrentSendTotal();
@ -755,6 +754,7 @@ public:
S32 getReceiveBytes() const;
S32 getUnackedListSize() const { return mUnackedListSize; }
F32 getBufferLoadRate() const { return mPacketRing.getBufferLoadRate(); }
//const char* getCurrentSMessageName() const { return mCurrentSMessageName; }
//const char* getCurrentSBlockName() const { return mCurrentSBlockName; }
@ -845,12 +845,10 @@ private:
LLUUID mSessionID;
void addTemplate(LLMessageTemplate *templatep);
bool decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
void logMsgFromInvalidCircuit( const LLHost& sender, bool recv_reliable );
void logTrustedMsgFromUntrustedCircuit( const LLHost& sender );
void logValidMsg(LLCircuitData *cdp, const LLHost& sender, bool recv_reliable, bool recv_resent, bool recv_acks );
void logRanOffEndOfPacket( const LLHost& sender );
class LLMessageCountInfo
{

View File

@ -413,6 +413,7 @@ set(viewer_SOURCE_FILES
llfloatersettingscolor.cpp
llfloatersettingsdebug.cpp
llfloatersidepanelcontainer.cpp
llfloaterslapptest.cpp
llfloatersnapshot.cpp
llfloatersounddevices.cpp
llfloaterspellchecksettings.cpp
@ -1233,6 +1234,7 @@ set(viewer_HEADER_FILES
llfloatersettingscolor.h
llfloatersettingsdebug.h
llfloatersidepanelcontainer.h
llfloaterslapptest.h
llfloatersnapshot.h
llfloatersounddevices.h
llfloaterspellchecksettings.h

View File

@ -6267,6 +6267,17 @@
<key>Value</key>
<integer>5000</integer>
</map>
<key>InventoryExposeFolderID</key>
<map>
<key>Comment</key>
<string>Allows copying folder id from context menu</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>MarketplaceListingsSortOrder</key>
<map>
<key>Comment</key>

View File

@ -5187,48 +5187,64 @@ void wear_multiple(const uuid_vec_t& ids, bool replace)
LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, replace, cb);
}
// SLapp for easy-wearing of a stock (library) avatar
//
bool wear_category(const LLSD& query_map, bool append)
{
LLUUID folder_uuid;
if (query_map.has("folder_name"))
{
std::string outfit_folder_name = query_map["folder_name"];
folder_uuid = findDescendentCategoryIDByName(gInventory.getLibraryRootFolderID(), outfit_folder_name);
if (folder_uuid.isNull())
LL_WARNS() << "Couldn't find " << std::quoted(outfit_folder_name) << " in the Library" << LL_ENDL;
}
if (folder_uuid.isNull() && query_map.has("folder_id"))
{
folder_uuid = query_map["folder_id"].asUUID();
}
if (folder_uuid.notNull())
{
if (LLViewerInventoryCategory* cat = gInventory.getCategory(folder_uuid))
{
if (bool is_library = gInventory.isObjectDescendentOf(folder_uuid, gInventory.getRootFolderID()))
{
LLPointer<LLInventoryCategory> new_category = new LLInventoryCategory(folder_uuid, LLUUID::null, LLFolderType::FT_CLOTHING, "Quick Appearance");
LLAppearanceMgr::getInstance()->wearInventoryCategory(new_category, true, append);
}
else
{
LLAppearanceMgr::getInstance()->wearInventoryCategory(cat, true, append);
}
return true;
}
else
{
LL_WARNS() << "Couldn't find folder id" << folder_uuid << " in Inventory" << LL_ENDL;
}
}
return false;
}
class LLWearFolderHandler : public LLCommandHandler
{
public:
// not allowed from outside the app
LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) { }
LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) {}
bool handle(const LLSD& tokens,
const LLSD& query_map,
const std::string& grid,
LLMediaCtrl* web)
{
LLSD::UUID folder_uuid;
if (folder_uuid.isNull() && query_map.has("folder_name"))
if (wear_category(query_map, false))
{
std::string outfit_folder_name = query_map["folder_name"];
folder_uuid = findDescendentCategoryIDByName(
gInventory.getLibraryRootFolderID(),
outfit_folder_name);
}
if (folder_uuid.isNull() && query_map.has("folder_id"))
{
folder_uuid = query_map["folder_id"].asUUID();
}
// Assume this is coming from the predefined avatars web floater
LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance");
if (folder_uuid.notNull())
{
LLPointer<LLInventoryCategory> category = new LLInventoryCategory(folder_uuid,
LLUUID::null,
LLFolderType::FT_CLOTHING,
"Quick Appearance");
if ( gInventory.getCategory( folder_uuid ) != NULL )
{
// Assume this is coming from the predefined avatars web floater
LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance");
LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false);
// *TODOw: This may not be necessary if initial outfit is chosen already -- josh
gAgent.setOutfitChosen(true);
}
// *TODOw: This may not be necessary if initial outfit is chosen already -- josh
gAgent.setOutfitChosen(true);
}
// release avatar picker keyboard focus
@ -5238,4 +5254,46 @@ public:
}
};
class LLAddFolderHandler : public LLCommandHandler
{
public:
// not allowed from outside the app
LLAddFolderHandler() : LLCommandHandler("add_folder", UNTRUSTED_BLOCK) {}
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
{
wear_category(query_map, true);
return true;
}
};
class LLRemoveFolderHandler : public LLCommandHandler
{
public:
LLRemoveFolderHandler() : LLCommandHandler("remove_folder", UNTRUSTED_BLOCK) {}
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
{
if (query_map.has("folder_id"))
{
LLUUID folder_id = query_map["folder_id"].asUUID();
if (folder_id.notNull())
{
if (LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id))
{
LLAppearanceMgr::instance().takeOffOutfit(cat->getLinkedUUID());
}
else
{
LL_WARNS() << "Couldn't find folder id" << folder_id << " in Inventory" << LL_ENDL;
}
}
}
return true;
}
};
LLWearFolderHandler gWearFolderHandler;
LLAddFolderHandler gAddFolderHandler;
LLRemoveFolderHandler gRemoveFolderHandler;

View File

@ -6359,6 +6359,7 @@ void LLAppViewer::idleNetwork()
// Retransmit unacknowledged packets.
gXferManager->retransmitUnackedPackets();
gAssetStorage->checkForTimeouts();
gViewerThrottle.setBufferLoadRate(gMessageSystem->getBufferLoadRate());
gViewerThrottle.updateDynamicThrottle();
// Check that the circuit between the viewer and the agent's current

View File

@ -42,6 +42,7 @@
#include "llinventorymodel.h"
#include "llnotifications.h"
#include "llslurl.h"
#include "llstartup.h"
#include "llimview.h"
#include "lltrans.h"
#include "llviewercontrol.h"
@ -279,6 +280,22 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
<< "]" << LL_ENDL;
}
}
// It's possible that the buddy list getting propagated from the inventory may have happened after we actually got the buddy list.
// Any buddies that we got prior will reside in a special queue that we must process and update statuses accordingly with.
// Do that here.
// -Geenz 2025-03-12
while (!mBuddyStatusQueue.empty())
{
auto buddyStatus = mBuddyStatusQueue.front();
mBuddyStatusQueue.pop();
if (mBuddyInfo.find(buddyStatus.first) != mBuddyInfo.end())
{
setBuddyOnline(buddyStatus.first, buddyStatus.second);
}
}
// do not notify observers here - list can be large so let it be done on idle.
return new_buddy_count;
@ -343,9 +360,12 @@ void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
{
//<FS:LO> Fix possible log spam with a large friendslist when SL messes up.
//LL_WARNS() << "!! No buddy info found for " << id
LL_WARNS() << "Did we receive a buddy status update before the buddy info?" << LL_ENDL;
LL_DEBUGS() << "!! No buddy info found for " << id
<< ", setting to " << (is_online ? "Online" : "Offline") << LL_ENDL;
LL_DEBUGS() << "Did we receive a buddy status update before the buddy info?" << LL_ENDL;
//</FS:LO>
mBuddyStatusQueue.push(std::make_pair(id, is_online));
}
}
@ -790,6 +810,8 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
{
LL_WARNS() << "Received online notification for unknown buddy: "
<< agent_id << " is " << (online ? "ONLINE" : "OFFLINE") << LL_ENDL;
LL_WARNS() << "Adding buddy to buddy queue." << LL_ENDL;
mBuddyStatusQueue.push(std::make_pair(agent_id, true));
}
if(tracking_id == agent_id)
@ -812,7 +834,11 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
mModifyMask |= LLFriendObserver::ONLINE;
instance().notifyObservers();
gInventory.notifyObservers();
// Skip if we had received the friends list before the inventory callbacks were properly initialized
if (LLStartUp::getStartupState() > STATE_INVENTORY_CALLBACKS)
{
gInventory.notifyObservers();
}
}
}

View File

@ -110,6 +110,7 @@ public:
// add or remove agents from buddy list. Each method takes a set
// of buddies and returns how many were actually added or removed.
typedef std::map<LLUUID, LLRelationship*> buddy_map_t;
typedef std::queue<std::pair<LLUUID, bool>> buddy_status_queue_t;
S32 addBuddyList(const buddy_map_t& buddies);
//S32 removeBuddyList(const buddy_list_t& exes);
@ -200,6 +201,7 @@ protected:
//LLInventoryObserver* mInventoryObserver;
buddy_map_t mBuddyInfo;
buddy_status_queue_t mBuddyStatusQueue;
typedef std::set<LLUUID> changed_buddy_t;
changed_buddy_t mChangedBuddyIDs;

View File

@ -0,0 +1,51 @@
/**
* @file llfloaterslapptest.cpp
*
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2025, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterslapptest.h"
#include "lluictrlfactory.h"
#include "lllineeditor.h"
#include "lltextbox.h"
LLFloaterSLappTest::LLFloaterSLappTest(const LLSD& key)
: LLFloater("floater_test_slapp")
{
}
LLFloaterSLappTest::~LLFloaterSLappTest()
{}
bool LLFloaterSLappTest::postBuild()
{
getChild<LLLineEditor>("remove_folder_id")->setKeystrokeCallback([this](LLLineEditor* editor, void*)
{
std::string slapp(getString("remove_folder_slapp"));
getChild<LLTextBox>("remove_folder_txt")->setValue(slapp + editor->getValue().asString());
}, NULL);
return true;
}

View File

@ -0,0 +1,42 @@
/**
* @file llfloaterslapptest.h
*
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2025, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLFLOATERSLAPPTEST_H
#define LL_LLFLOATERSLAPPTEST_H
#include "llfloater.h"
class LLFloaterSLappTest:
public LLFloater
{
friend class LLFloaterReg;
virtual bool postBuild() override;
private:
LLFloaterSLappTest(const LLSD& key);
~LLFloaterSLappTest();
};
#endif

View File

@ -353,6 +353,18 @@ void LLGLTFMaterialList::queueApply(const LLViewerObject* obj, S32 side, const L
}
}
void LLGLTFMaterialList::queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id, const std::string &override_json)
{
if (asset_id.isNull() || override_json.empty())
{
queueApply(obj, side, asset_id);
}
else
{
sApplyQueue.push_back({ obj->getID(), side, asset_id, nullptr, override_json });
}
}
void LLGLTFMaterialList::queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id, const LLGLTFMaterial* material_override)
{
if (asset_id.isNull() || material_override == nullptr)
@ -456,6 +468,10 @@ void LLGLTFMaterialList::flushUpdatesOnce(std::shared_ptr<CallbackHolder> callba
{
data[i]["gltf_json"] = e.override_data->asJSON();
}
if (!e.override_json.empty())
{
data[i]["gltf_json"] = e.override_json;
}
else
{
// Clear all overrides

View File

@ -67,6 +67,7 @@ public:
//
// NOTE: Implicitly clears most override data if present
static void queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id);
static void queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id, const std::string& override_json);
// Queue an application of a material asset we want to send to the simulator.
// Call "flushUpdates" to flush pending updates immediately.
@ -160,6 +161,7 @@ protected:
S32 side = -1;
LLUUID asset_id;
LLPointer<LLGLTFMaterial> override_data;
std::string override_json;
};
typedef std::list<ApplyMaterialAssetData> apply_queue_t;

View File

@ -3920,6 +3920,13 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action)));
}
else if ("copy_folder_uuid" == action)
{
LLInventoryCategory* cat = gInventory.getCategory(mUUID);
if (!cat) return;
gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(mUUID.asString()));
return;
}
// <FS:Ansariel> FIRE-29342: Protect folder option
else if ("protect_folder" == action)
{
@ -4925,6 +4932,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
{
disabled_items.push_back(std::string("Delete System Folder"));
}
else
{
static LLCachedControl<bool> show_copy_id(gSavedSettings, "InventoryExposeFolderID", false);
if (show_copy_id())
{
items.push_back(std::string("Copy UUID"));
}
}
// <FS:AH/SJ> Don't offer sharing of trash folder (FIRE-1642, FIRE-6547)
//if (isAgentInventory() && !isMarketplaceListingsFolder())

View File

@ -4572,21 +4572,14 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
tep->setGLTFRenderMaterial(nullptr);
tep->setGLTFMaterialOverride(nullptr);
LLSD override_data;
override_data["object_id"] = objectp->getID();
override_data["side"] = te;
if (te_data["te"].has("pbr_override"))
{
override_data["gltf_json"] = te_data["te"]["pbr_override"];
LLGLTFMaterialList::queueApply(objectp, te, te_data["te"]["pbr"].asUUID(), te_data["te"]["pbr_override"]);
}
else
{
override_data["gltf_json"] = "";
LLGLTFMaterialList::queueApply(objectp, te, te_data["te"]["pbr"].asUUID());
}
override_data["asset_id"] = te_data["te"]["pbr"].asUUID();
LLGLTFMaterialList::queueUpdate(override_data);
}
else
{

View File

@ -2150,7 +2150,7 @@ void LLPanelMainInventory::initInventoryViews()
void LLPanelMainInventory::toggleViewMode()
{
if(mSingleFolderMode && isCombinationViewMode())
if(mSingleFolderMode && isCombinationViewMode() && mCombinationGalleryPanel->getRootFolder().notNull())
{
mCombinationInventoryPanel->getRootFolder()->setForceArrange(false);
}
@ -2633,7 +2633,8 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)
}
else
{
LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
LLFolderView* root_folder = getActivePanel() ? getActivePanel()->getRootFolder() : nullptr;
LLFolderViewItem* current_item = root_folder ? root_folder->getCurSelectedItem() : nullptr;
if (current_item)
{
inv_item = dynamic_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryObject());
@ -3243,8 +3244,6 @@ void LLPanelMainInventory::updateCombinationVisibility()
mCombinationGalleryPanel->handleModifiedFilter();
}
getActivePanel()->getRootFolder();
if (mReshapeInvLayout
&& show_inv_pane
&& (mCombinationGalleryPanel->hasVisibleItems() || mCombinationGalleryPanel->areViewsInitialized())
@ -3301,8 +3300,12 @@ void LLPanelMainInventory::updateCombinationVisibility()
&& mCombinationInventoryPanel->areViewsInitialized())
{
mCombinationInventoryPanel->setSelectionByID(mCombInvUUIDNeedsRename, true);
mCombinationInventoryPanel->getRootFolder()->scrollToShowSelection();
mCombinationInventoryPanel->getRootFolder()->setNeedsAutoRename(true);
LLFolderView* root = mCombinationInventoryPanel->getRootFolder();
if (root)
{
root->scrollToShowSelection();
root->setNeedsAutoRename(true);
}
mCombInvUUIDNeedsRename.setNull();
}
}

View File

@ -80,13 +80,6 @@ class LLClassifiedHandler : public LLCommandHandler, public LLAvatarPropertiesOb
public:
// throttle calls from untrusted browsers
LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {}
virtual ~LLClassifiedHandler()
{
if (LLAvatarPropertiesProcessor::instanceExists())
{
LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this);
}
}
std::set<LLUUID> mClassifiedIds;
std::string mRequestVerb;

View File

@ -57,7 +57,7 @@
static LLPanelInjector<LLPanelProfilePicks> t_panel_profile_picks("panel_profile_picks");
static LLPanelInjector<LLPanelProfilePick> t_panel_profile_pick("panel_profile_pick");
constexpr F32 REQUEST_TIMOUT = 60;
constexpr F32 REQUEST_TIMEOUT = 60;
constexpr F32 LOCATION_CACHE_TIMOUT = 900;
class LLPickHandler : public LLCommandHandler
@ -981,7 +981,7 @@ std::string LLPanelProfilePick::getLocationNotice()
void LLPanelProfilePick::sendParcelInfoRequest()
{
if (mParcelId != mRequestedId || mLastRequestTimer.getElapsedTimeF32() > REQUEST_TIMOUT)
if (mParcelId != mRequestedId || mLastRequestTimer.getElapsedTimeF32() > REQUEST_TIMEOUT)
{
if (mRequestedId.notNull())
{

View File

@ -102,7 +102,15 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v
msg->getS32 ("Data", "SalePrice", parcel_data.sale_price);
msg->getS32 ("Data", "AuctionID", parcel_data.auction_id);
LLRemoteParcelInfoProcessor::observer_multimap_t & observers = LLRemoteParcelInfoProcessor::getInstance()->mObservers;
LLRemoteParcelInfoProcessor* inst = LLRemoteParcelInfoProcessor::getInstance();
requests_map_t::const_iterator found = inst->mPendingParcelRequests.find(parcel_data.parcel_id);
if (found != inst->mPendingParcelRequests.end())
{
inst->mPendingParcelRequests.erase(found);
}
LLRemoteParcelInfoProcessor::observer_multimap_t & observers = inst->mObservers;
typedef std::vector<observer_multimap_t::iterator> deadlist_t;
deadlist_t dead_iters;
@ -151,6 +159,15 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v
void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id)
{
constexpr F32 DUPPLICATE_TIMEOUT = 0.5f;
requests_map_t::const_iterator found = mPendingParcelRequests.find(parcel_id);
if (found != mPendingParcelRequests.end() && found->second.getElapsedTimeF32() < DUPPLICATE_TIMEOUT)
{
// recently requested
return;
}
mPendingParcelRequests[parcel_id].reset();
LLMessageSystem *msg = gMessageSystem;
msg->newMessage("ParcelInfoRequest");

View File

@ -91,6 +91,8 @@ public:
private:
typedef std::multimap<LLUUID, LLHandle<LLRemoteParcelInfoObserver> > observer_multimap_t;
observer_multimap_t mObservers;
typedef std::map<LLUUID, LLTimer> requests_map_t;
requests_map_t mPendingParcelRequests; // Dupplicate request avoidance
void regionParcelInfoCoro(std::string url, LLUUID regionId, LLVector3 posRegion, LLVector3d posGlobal, LLHandle<LLRemoteParcelInfoObserver> observerHandle);
};

View File

@ -2467,6 +2467,15 @@ bool idle_startup()
#endif
// </FS:Ansariel>
}
// It is entirely possible that we may get the friends list _before_ we have the callbacks registered to process that.
// This will lead to the friends list not being processed properly and online statuses not being updated appropriately at login.
// So, we need to make sure that we have the callbacks registered before we get the friends list.
// This appears to crop up on some systems somewhere between STATE_AGENT_SEND and STATE_INVENTORY_SEND. It's happened to me a few times now.
// -Geenz 2025-03-12
LL_INFOS() << " AvatarTracker" << LL_ENDL;
LLAvatarTracker::instance().registerCallbacks(gMessageSystem);
do_startup_frame();
// Create login effect
@ -2786,8 +2795,6 @@ bool idle_startup()
LLMessageSystem* msg = gMessageSystem;
LL_INFOS() << " Inventory" << LL_ENDL;
LLInventoryModel::registerCallbacks(msg);
LL_INFOS() << " AvatarTracker" << LL_ENDL;
LLAvatarTracker::instance().registerCallbacks(msg);
LL_INFOS() << " Landmark" << LL_ENDL;
LLLandmark::registerCallbacks(msg);
do_startup_frame();

View File

@ -139,6 +139,7 @@
#include "llfloatersettingscolor.h"
#include "llfloatersettingsdebug.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterslapptest.h"
#include "llfloatersnapshot.h"
#include "llfloatersounddevices.h"
#include "llfloaterspellchecksettings.h"
@ -336,7 +337,8 @@ public:
"upload_model",
"upload_script",
"upload_sound",
"bulk_upload"
"bulk_upload",
"slapp_test"
};
return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end();
}
@ -601,6 +603,7 @@ void LLViewerFloaterReg::registerFloaters()
//LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>);
LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
LLFloaterReg::add("slapp_test", "floater_test_slapp.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSLappTest>);
LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);

View File

@ -48,6 +48,8 @@ const F32 MIN_FRACTIONAL = 0.2f;
const F32 MIN_BANDWIDTH = 50.f;
const F32 MAX_BANDWIDTH = 6000.f;
const F32 STEP_FRACTIONAL = 0.1f;
const F32 HIGH_BUFFER_LOAD_TRESHOLD = 1.f;
const F32 LOW_BUFFER_LOAD_TRESHOLD = 0.8f;
const LLUnit<F32, LLUnits::Percent> TIGHTEN_THROTTLE_THRESHOLD(3.0f); // packet loss % per s
const LLUnit<F32, LLUnits::Percent> EASE_THROTTLE_THRESHOLD(0.5f); // packet loss % per s
const F32 DYNAMIC_UPDATE_DURATION = 5.0f; // seconds
@ -146,7 +148,7 @@ LLViewerThrottleGroup LLViewerThrottleGroup::operator-(const LLViewerThrottleGro
void LLViewerThrottleGroup::sendToSim() const
{
LL_INFOS() << "Sending throttle settings, total BW " << mThrottleTotal << LL_ENDL;
LL_DEBUGS("Throttle") << "Sending throttle settings, total BW " << mThrottleTotal << LL_ENDL;
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_AgentThrottle);
@ -305,7 +307,10 @@ void LLViewerThrottle::updateDynamicThrottle()
mUpdateTimer.reset();
LLUnit<F32, LLUnits::Percent> mean_packets_lost = LLViewerStats::instance().getRecording().getMean(LLStatViewer::PACKETS_LOST_PERCENT);
if (mean_packets_lost > TIGHTEN_THROTTLE_THRESHOLD)
if (
mean_packets_lost > TIGHTEN_THROTTLE_THRESHOLD // already losing packets
|| mBufferLoadRate >= HIGH_BUFFER_LOAD_TRESHOLD // let viewer sort through the backlog before it starts dropping packets
)
{
if (mThrottleFrac <= MIN_FRACTIONAL || mCurrentBandwidth / 1024.0f <= MIN_BANDWIDTH)
{
@ -318,7 +323,8 @@ void LLViewerThrottle::updateDynamicThrottle()
mCurrent.sendToSim();
LL_INFOS() << "Tightening network throttle to " << mCurrentBandwidth << LL_ENDL;
}
else if (mean_packets_lost <= EASE_THROTTLE_THRESHOLD)
else if (mean_packets_lost <= EASE_THROTTLE_THRESHOLD
&& mBufferLoadRate < LOW_BUFFER_LOAD_TRESHOLD)
{
if (mThrottleFrac >= MAX_FRACTIONAL || mCurrentBandwidth / 1024.0f >= MAX_BANDWIDTH)
{
@ -331,4 +337,6 @@ void LLViewerThrottle::updateDynamicThrottle()
mCurrent.sendToSim();
LL_INFOS() << "Easing network throttle to " << mCurrentBandwidth << LL_ENDL;
}
mBufferLoadRate = 0;
}

View File

@ -70,12 +70,15 @@ public:
void updateDynamicThrottle();
void resetDynamicThrottle();
void setBufferLoadRate(F32 rate) { mBufferLoadRate = llmax(mBufferLoadRate, rate); }
LLViewerThrottleGroup getThrottleGroup(const F32 bandwidth_kbps);
static const std::string sNames[TC_EOF];
protected:
F32 mMaxBandwidth;
F32 mCurrentBandwidth;
F32 mBufferLoadRate = 0;
LLViewerThrottleGroup mCurrent;

View File

@ -91,6 +91,7 @@
<menu_item_call label="Schutz aufheben" name="UnprotectFolder"/>
<menu_item_call label="Ordner neu laden" name="ReloadFolder"/>
<menu_item_call label="Asset-UUID kopieren" name="Copy Asset UUID"/>
<menu_item_call label="UUID kopieren" name="Copy UUID"/>
<menu_item_call label="Wiederherstellen an letzter Position" name="Restore to Last Position"/>
<menu_item_call label="Ausschneiden" name="Cut"/>
<menu_item_call label="Kopieren" name="Copy"/>

View File

@ -620,6 +620,7 @@
<menu_item_call label="Farbeinstellungen anzeigen" name="Color Settings"/>
<menu_item_call label="Farbeinstellungen neu laden" name="Reload Color Settings"/>
<menu_item_call label="Schriftarttest anzeigen" name="Show Font Test"/>
<menu_item_call label="SLapps-Test anzeigen" name="Show SLapps Test"/>
<menu_item_call label="Aus XML-Datei laden" name="Load from XML"/>
<menu_item_call label="In XML-Datei speichern" name="Save to XML"/>
<menu_item_check label="XUI-Namen anzeigen" name="Show XUI Names"/>

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater
legacy_header_height="18"
height="300"
layout="topleft"
name="slapp_test"
title="SLAPP TEST"
width="500">
<floater.string
name="remove_folder_slapp">
secondlife://app/remove_folder/?folder_id=
</floater.string>
<text
type="string"
length="1"
top="20"
follows="left|top|right"
height="16"
name="trusted_txt"
font="SansSerifMedium"
text_color="white"
layout="topleft"
left="16">
Trusted source
</text>
<text
type="string"
length="1"
top_pad="8"
follows="left|top|right"
height="16"
layout="topleft"
left="16">
/wear_folder
</text>
<text
type="string"
length="1"
top_pad="5"
follows="left|top|right"
height="16"
width="450"
layout="topleft"
left="16">
secondlife://app/wear_folder/?folder_name=Daisy
</text>
<text
type="string"
length="1"
top_pad="8 "
follows="left|top|right"
height="16"
layout="topleft"
left="16">
/add_folder
</text>
<text
type="string"
length="1"
top_pad="5"
follows="left|top|right"
height="16"
width="450"
layout="topleft"
left="16">
secondlife://app/add_folder/?folder_name=Cardboard%20Boxbot
</text>
<text
type="string"
length="1"
top_pad="5"
follows="left|top|right"
height="16"
width="450"
layout="topleft">
secondlife://app/add_folder/?folder_id=59219db2-c260-87d3-213d-bb3bc298a3d8
</text>
<text
type="string"
length="1"
top_pad="8 "
follows="left|top|right"
height="16"
layout="topleft"
left="16">
/remove_folder
</text>
<text
type="string"
length="1"
top_pad="5"
follows="left|top|right"
height="16"
layout="topleft"
left="16">
Folder ID:
</text>
<line_editor
border_style="line"
border_thickness="1"
follows="left|top"
font="SansSerif"
height="18"
layout="topleft"
left="75"
max_length_bytes="50"
prevalidate_callback="ascii"
name="remove_folder_id"
top_delta="-2"
width="270" />
<text
type="string"
length="1"
top_pad="5"
follows="left|top|right"
height="16"
width="450"
name="remove_folder_txt"
layout="topleft"
left="16">
secondlife://app/remove_folder/?folder_id=
</text>
</floater>

View File

@ -678,6 +678,14 @@
function="Inventory.DoToSelected"
parameter="copy_uuid" />
</menu_item_call>
<menu_item_call
label="Copy UUID"
layout="topleft"
name="Copy UUID">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="copy_folder_uuid" />
</menu_item_call>
<menu_item_call
label="Restore to Last Position"
layout="topleft"

View File

@ -5272,6 +5272,13 @@
function="Floater.Show"
parameter="font_test" />
</menu_item_call>
<menu_item_call
label="Show SLapps Test"
name="Show SLapps Test">
<menu_item_call.on_click
function="Floater.Show"
parameter="slapp_test" />
</menu_item_call>
<menu_item_call
label="Load from XML"
name="Load from XML">