diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index f2f1b1157c..11b33e573c 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -348,7 +348,7 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
try
{
// Disable for more meaningful callstacks
-//#if LL_WINDOWS
+//#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD
// winlevel(callable);
//#else
//
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 4d73533797..ba5b36a47f 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -2203,19 +2203,27 @@ bool LLImageFormatted::load(const std::string &filename, int load_size)
}
bool res;
U8 *data = allocateData(load_size);
- apr_size_t bytes_read = load_size;
- apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
- if (s != APR_SUCCESS || (S32) bytes_read != load_size)
+ if (data)
{
- deleteData();
- setLastError("Unable to read file",filename);
- res = false;
+ apr_size_t bytes_read = load_size;
+ apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
+ if (s != APR_SUCCESS || (S32) bytes_read != load_size)
+ {
+ deleteData();
+ setLastError("Unable to read file",filename);
+ res = false;
+ }
+ else
+ {
+ res = updateData();
+ }
}
else
{
- res = updateData();
+ setLastError("Allocation failure", filename);
+ res = false;
}
-
+
return res;
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index b61fd2ebc3..eeef62603c 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2349,7 +2349,14 @@ bool idle_startup()
if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT)
{
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
- LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ if (gRememberPassword)
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
+ }
reset_login();
}
return FALSE;
@@ -3252,7 +3259,14 @@ void use_circuit_callback(void**, S32 result)
{
// Make sure user knows something bad happened. JC
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
- LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ if (gRememberPassword)
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
+ }
reset_login();
}
else
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index d8aa49ab07..933ded9aaa 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -748,9 +748,14 @@ void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask)
!objectp->isHUDAttachment() &&
objectp->getRoot() == gAgentAvatarp->getRoot())
{
- // force focus to point in space where we were looking previously
- gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ // we are essentially editing object position
+ if (!gSavedSettings.getBOOL("EditCameraMovement"))
+ {
+ // force focus to point in space where we were looking previously
+ // Example of use: follow cam scripts shouldn't affect you when movng objects arouns
+ gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ }
}
else
{
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 633029dee8..2520348ea3 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -287,6 +287,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mPixelArea(1024.f),
mInventory(NULL),
mInventorySerialNum(0),
+ mExpectedInventorySerialNum(0),
mInvRequestState(INVENTORY_REQUEST_STOPPED),
mInvRequestXFerId(0),
mInventoryDirty(FALSE),
@@ -2899,13 +2900,13 @@ void LLViewerObject::doUpdateInventory(
{
// best guess.
perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
- --mInventorySerialNum;
+ --mExpectedInventorySerialNum;
}
else
{
// dummy it up.
perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
- --mInventorySerialNum;
+ --mExpectedInventorySerialNum;
}
}
LLViewerInventoryItem* oldItem = item;
@@ -2913,7 +2914,11 @@ void LLViewerObject::doUpdateInventory(
new_item->setPermissions(perm);
mInventory->push_front(new_item);
doInventoryCallback();
- ++mInventorySerialNum;
+ ++mExpectedInventorySerialNum;
+ }
+ else if (is_new)
+ {
+ ++mExpectedInventorySerialNum;
}
}
@@ -2980,7 +2985,7 @@ void LLViewerObject::moveInventory(const LLUUID& folder_id,
if(!item->getPermissions().allowCopyBy(gAgent.getID()))
{
deleteInventoryItem(item_id);
- ++mInventorySerialNum;
+ ++mExpectedInventorySerialNum;
}
}
}
@@ -3256,74 +3261,95 @@ S32 LLFilenameAndTask::sCount = 0;
// static
void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
{
- LLUUID task_id;
- msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
- LLViewerObject* object = gObjectList.findObject(task_id);
- if(!object)
- {
- LL_WARNS() << "LLViewerObject::processTaskInv object "
- << task_id << " does not exist." << LL_ENDL;
- return;
- }
+ LLUUID task_id;
+ msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
+ LLViewerObject* object = gObjectList.findObject(task_id);
+ if (!object)
+ {
+ LL_WARNS() << "LLViewerObject::processTaskInv object "
+ << task_id << " does not exist." << LL_ENDL;
+ return;
+ }
- LLFilenameAndTask* ft = new LLFilenameAndTask;
- ft->mTaskID = task_id;
- // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
- msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
+ LLFilenameAndTask* ft = new LLFilenameAndTask;
+ ft->mTaskID = task_id;
+ // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
+ msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
- if (ft->mSerial < object->mInventorySerialNum)
- {
- // viewer did some changes to inventory that were not saved yet.
- LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL;
- object->mInventorySerialNum = ft->mSerial;
- }
+ if (ft->mSerial == object->mInventorySerialNum)
+ {
+ // Loop Protection.
+ // We received same serial twice.
+ // Viewer did some changes to inventory that couldn't be saved server side
+ // or something went wrong to cause serial to be out of sync
+ LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
+ object->mExpectedInventorySerialNum = ft->mSerial;
+ }
- std::string unclean_filename;
- msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
- ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
+ if (ft->mSerial < object->mExpectedInventorySerialNum)
+ {
+ // out of date message, record to current serial for loop protection, but do not load it
+ // just drop xfer to restart on idle
+ if (ft->mSerial < object->mInventorySerialNum)
+ {
+ LL_WARNS() << "Somehow task serial decreased, out of order packet?" << LL_ENDL;
+ }
+ object->mInventorySerialNum = ft->mSerial;
+ object->mInvRequestXFerId = 0;
+ object->mInvRequestState = INVENTORY_REQUEST_STOPPED;
+ }
+ else if (ft->mSerial >= object->mExpectedInventorySerialNum)
+ {
+ object->mInventorySerialNum = ft->mSerial;
+ object->mExpectedInventorySerialNum = ft->mSerial;
- if(ft->mFilename.empty())
- {
- LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
- // mock up some inventory to make a drop target.
- if(object->mInventory)
- {
- object->mInventory->clear(); // will deref and delete it
- }
- else
- {
- object->mInventory = new LLInventoryObject::object_list_t();
- }
- LLPointer obj;
- obj = new LLInventoryObject(object->mID, LLUUID::null,
- LLAssetType::AT_CATEGORY,
- "Contents");
- object->mInventory->push_front(obj);
- object->doInventoryCallback();
- delete ft;
- return;
- }
- U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
- ft->mFilename, LL_PATH_CACHE,
- object->mRegionp->getHost(),
- TRUE,
- &LLViewerObject::processTaskInvFile,
- (void**)ft,
- LLXferManager::HIGH_PRIORITY);
- if (object->mInvRequestState == INVENTORY_XFER)
- {
- if (new_id > 0 && new_id != object->mInvRequestXFerId)
- {
- // we started new download.
- gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
- object->mInvRequestXFerId = new_id;
- }
- }
- else
- {
- object->mInvRequestState = INVENTORY_XFER;
- object->mInvRequestXFerId = new_id;
- }
+ std::string unclean_filename;
+ msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
+ ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
+
+ if (ft->mFilename.empty())
+ {
+ LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
+ // mock up some inventory to make a drop target.
+ if (object->mInventory)
+ {
+ object->mInventory->clear(); // will deref and delete it
+ }
+ else
+ {
+ object->mInventory = new LLInventoryObject::object_list_t();
+ }
+ LLPointer obj;
+ obj = new LLInventoryObject(object->mID, LLUUID::null,
+ LLAssetType::AT_CATEGORY,
+ "Contents");
+ object->mInventory->push_front(obj);
+ object->doInventoryCallback();
+ delete ft;
+ return;
+ }
+ U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
+ ft->mFilename, LL_PATH_CACHE,
+ object->mRegionp->getHost(),
+ TRUE,
+ &LLViewerObject::processTaskInvFile,
+ (void**)ft,
+ LLXferManager::HIGH_PRIORITY);
+ if (object->mInvRequestState == INVENTORY_XFER)
+ {
+ if (new_id > 0 && new_id != object->mInvRequestXFerId)
+ {
+ // we started new download.
+ gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
+ object->mInvRequestXFerId = new_id;
+ }
+ }
+ else
+ {
+ object->mInvRequestState = INVENTORY_XFER;
+ object->mInvRequestXFerId = new_id;
+ }
+ }
}
void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
@@ -3337,6 +3363,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS
&& ft->mSerial >= object->mInventorySerialNum)
{
object->mInventorySerialNum = ft->mSerial;
+ LL_DEBUGS() << "Receiving inventory task file for serial " << object->mInventorySerialNum << " taskid: " << ft->mTaskID << LL_ENDL;
+ if (ft->mSerial < object->mExpectedInventorySerialNum)
+ {
+ // User managed to change something while inventory was loading
+ LL_DEBUGS() << "Processing file that is potentially out of date for task: " << ft->mTaskID << LL_ENDL;
+ }
+
if (object->loadTaskInvFile(ft->mFilename))
{
@@ -3498,7 +3531,7 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
msg->addUUIDFast(_PREHASH_ItemID, item_id);
msg->sendReliable(mRegionp->getHost());
deleteInventoryItem(item_id);
- ++mInventorySerialNum;
+ ++mExpectedInventorySerialNum;
}
bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 0384b3e4fb..5fee3dcdf5 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -819,6 +819,7 @@ protected:
typedef std::list callback_list_t;
callback_list_t mInventoryCallbacks;
S16 mInventorySerialNum;
+ S16 mExpectedInventorySerialNum;
enum EInventoryRequestState
{
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 41ec0de381..ff5d0c4a17 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -79,6 +79,7 @@
#include "llselectmgr.h"
#include "llsprite.h"
#include "lltargetingmotion.h"
+#include "lltoolmgr.h"
#include "lltoolmorph.h"
#include "llviewercamera.h"
#include "llviewertexlayer.h"
@@ -8076,12 +8077,33 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
gAgentCamera.changeCameraToMouselook();
}
- //KC: revoke perms on sit
+ if (gAgentCamera.getFocusOnAvatar() && LLToolMgr::getInstance()->inEdit())
+ {
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if (node && node->mValid)
+ {
+ LLViewerObject* root_object = node->getObject();
+ if (root_object == sit_object)
+ {
+ LLFloaterTools::sPreviousFocusOnAvatar = true;
+ if (!gSavedSettings.getBOOL("EditCameraMovement"))
+ {
+ // always freeze camera in space, even if camera doesn't move
+ // so, for example, follow cam scripts can't affect you when in build mode
+ gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ }
+ }
+ }
+ }
+
+ // revoke perms on sit
U32 revoke_on = gSavedSettings.getU32("FSRevokePerms");
if ((revoke_on == 1 || revoke_on == 3) && !sit_object->permYouOwner())
{
revokePermissionsOnObject(sit_object);
}
+ //
}
if (mDrawable.isNull())
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 4f8c541419..d689034f09 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3684,6 +3684,30 @@ You can either check your Internet connection and try again in a few minutes, cl
+
+ fail
+We're having trouble connecting. There may be a problem with your Internet connection or the [SECOND_LIFE_GRID].
+
+You can either check your Internet connection and try again in a few minutes or click Help to view the [SUPPORT_SITE].
+
+ http://secondlife.com/support/
+
+
+
+