Compare commits
19 Commits
sv-1.8.9.8
...
sv-1.8.9.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32dbd40e64 | ||
|
|
a69e04a817 | ||
|
|
159de683e8 | ||
|
|
a9dbaf5e0a | ||
|
|
3c3d8c2400 | ||
|
|
b4080f8e2d | ||
|
|
5de94d6610 | ||
|
|
829045c262 | ||
|
|
b02d70fba0 | ||
|
|
64ed6e99f0 | ||
|
|
33d3bb2870 | ||
|
|
4df2193a4c | ||
|
|
343be08467 | ||
|
|
788b83bff3 | ||
|
|
c201ac90ba | ||
|
|
af3c66ad08 | ||
|
|
9bffc4bb82 | ||
|
|
132db6225e | ||
|
|
257086cbfc |
@@ -85,6 +85,7 @@ if (WINDOWS)
|
||||
/TP
|
||||
/W3
|
||||
/c
|
||||
/Zc:__cplusplus
|
||||
/Zc:forScope
|
||||
/Zc:rvalueCast
|
||||
/Zc:wchar_t
|
||||
|
||||
@@ -50,12 +50,10 @@ if (LINUX)
|
||||
set(DL_LIBRARY dl)
|
||||
set(RT_LIBRARY rt)
|
||||
set(PTHREAD_LIBRARY pthread)
|
||||
set(FMT_LIBRARY "")
|
||||
else (LINUX)
|
||||
set(DL_LIBRARY "")
|
||||
set(RT_LIBRARY "")
|
||||
set(PTHREAD_LIBRARY "")
|
||||
set(FMT_LIBRARY fmt::fmt)
|
||||
endif (LINUX)
|
||||
|
||||
if (WINDOWS)
|
||||
@@ -77,6 +75,6 @@ else (WINDOWS)
|
||||
set(WINDOWS_LIBRARIES "")
|
||||
endif (WINDOWS)
|
||||
|
||||
mark_as_advanced(DL_LIBRARY RT_LIBRARY PTHREAD_LIBRARY FMT_LIBRARY WINDOWS_LIBRARIES)
|
||||
mark_as_advanced(DL_LIBRARY RT_LIBRARY PTHREAD_LIBRARY WINDOWS_LIBRARIES)
|
||||
|
||||
endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
|
||||
|
||||
@@ -9,16 +9,18 @@ FetchContent_Declare(
|
||||
Catch2
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG v2.11.0
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
FetchContent_Declare(
|
||||
fmt
|
||||
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
|
||||
GIT_TAG 6.1.2
|
||||
GIT_TAG 0463665ef136d685fe07a564d93c782456456d3d
|
||||
)
|
||||
FetchContent_Declare(
|
||||
nlohmann_json
|
||||
GIT_REPOSITORY https://github.com/nlohmann/json.git
|
||||
GIT_TAG v3.7.3
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
FetchContent_Declare(
|
||||
absl
|
||||
@@ -45,9 +47,7 @@ if (BUILD_TESTING)
|
||||
endif()
|
||||
|
||||
#Download the rest of the libraries
|
||||
if(WINDOWS)
|
||||
FetchContent_MakeAvailable(fmt)
|
||||
endif()
|
||||
|
||||
# Typically you don't care so much for a third party library's tests to be
|
||||
# run from your own project's code.
|
||||
|
||||
@@ -300,6 +300,7 @@ target_link_libraries(
|
||||
${CORESERVICES_LIBRARY}
|
||||
${URIPARSER_LIBRARY}
|
||||
nlohmann_json::nlohmann_json
|
||||
absl::strings
|
||||
${RT_LIBRARY}
|
||||
)
|
||||
|
||||
|
||||
@@ -1072,8 +1072,8 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
|
||||
// the size, and read it.
|
||||
U32 size_nbo = 0;
|
||||
read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/
|
||||
S32 size = (S32)ntohl(size_nbo);
|
||||
if(mCheckLimits && (size > mMaxBytesLeft))
|
||||
S32 size = (S32)ntohl(size_nbo); // Can return negative size if > 2^31.
|
||||
if(size < 0 || mCheckLimits && (size > mMaxBytesLeft))
|
||||
{
|
||||
parse_count = PARSE_FAILURE;
|
||||
}
|
||||
@@ -1113,7 +1113,11 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
|
||||
map = LLSD::emptyMap();
|
||||
U32 value_nbo = 0;
|
||||
read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
|
||||
S32 size = (S32)ntohl(value_nbo);
|
||||
S32 size = (S32)ntohl(value_nbo); // Can return negative size if > 2^31.
|
||||
if (size < 0)
|
||||
{
|
||||
return PARSE_FAILURE;
|
||||
}
|
||||
S32 parse_count = 0;
|
||||
S32 count = 0;
|
||||
char c = get(istr);
|
||||
@@ -1167,7 +1171,11 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
|
||||
array = LLSD::emptyArray();
|
||||
U32 value_nbo = 0;
|
||||
read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
|
||||
S32 size = (S32)ntohl(value_nbo);
|
||||
S32 size = (S32)ntohl(value_nbo); // Can return negative size if > 2^31.
|
||||
if (size < 0)
|
||||
{
|
||||
return PARSE_FAILURE;
|
||||
}
|
||||
|
||||
// *FIX: This would be a good place to reserve some space in the
|
||||
// array...
|
||||
@@ -1208,8 +1216,8 @@ bool LLSDBinaryParser::parseString(
|
||||
// *FIX: This is memory inefficient.
|
||||
U32 value_nbo = 0;
|
||||
read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
|
||||
S32 size = (S32)ntohl(value_nbo);
|
||||
if(mCheckLimits && (size > mMaxBytesLeft)) return false;
|
||||
S32 size = (S32)ntohl(value_nbo); // Can return negative size if > 2^31.
|
||||
if(size < 0 || mCheckLimits && (size > mMaxBytesLeft)) return false;
|
||||
std::vector<char> buf;
|
||||
if(size)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,16 @@
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <string>
|
||||
|
||||
#if __cplusplus < 201606
|
||||
#include <absl/strings/string_view.h>
|
||||
namespace std {
|
||||
typedef absl::string_view string_view;
|
||||
}
|
||||
#else
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
//#include <locale>
|
||||
#include <iomanip>
|
||||
|
||||
@@ -126,9 +126,12 @@ public:
|
||||
// Returns true if this rotation is orthonormal with det ~= 1
|
||||
inline bool isOkRotation() const;
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
#if !defined(LL_DEBUG)
|
||||
static_assert(std::is_trivial<LLMatrix3a>::value, "LLMatrix3a must be a trivial type");
|
||||
static_assert(std::is_standard_layout<LLMatrix3a>::value, "LLMatrix3a must be a standard layout type");
|
||||
|
||||
static_assert(std::is_trivial<LLRotation>::value, "LLRotation must be a trivial type");
|
||||
static_assert(std::is_standard_layout<LLRotation>::value, "LLRotation must be a standard layout type");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -718,6 +718,8 @@ inline std::ostream& operator<<(std::ostream& s, const LLMatrix4a& m)
|
||||
|
||||
void matMulBoundBox(const LLMatrix4a &a, const LLVector4a *in_extents, LLVector4a *out_extents);
|
||||
|
||||
#if !defined(LL_DEBUG)
|
||||
static_assert(std::is_trivial<LLMatrix4a>::value, "LLMatrix4a must be a trivial type");
|
||||
static_assert(std::is_standard_layout<LLMatrix4a>::value, "LLMatrix4a must be a standard layout type");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -104,7 +104,8 @@ private:
|
||||
LL_ALIGN_16(LLVector4a mV);
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
#if !defined(LL_DEBUG)
|
||||
static_assert(std::is_trivial<LLPlane>::value, "LLPlane must be a trivial type");
|
||||
static_assert(std::is_standard_layout<LLPlane>::value, "LLPlane must be a standard layout type");
|
||||
|
||||
#endif
|
||||
#endif // LL_LLPLANE_H
|
||||
|
||||
@@ -105,7 +105,9 @@ protected:
|
||||
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
#if !defined(LL_DEBUG)
|
||||
static_assert(std::is_trivial<LLQuaternion2>::value, "LLQuaternion2 must be a trivial type");
|
||||
static_assert(std::is_standard_layout<LLQuaternion2>::value, "LLQuaternion2 must be a standard layout type");
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -350,6 +350,8 @@ inline std::ostream& operator<<(std::ostream& s, const LLVector4a& v)
|
||||
return s;
|
||||
}
|
||||
|
||||
#if !defined(LL_DEBUG)
|
||||
static_assert(std::is_trivial<LLVector4a>::value, "LLVector4a must be a be a trivial type");
|
||||
static_assert(std::is_standard_layout<LLVector4a>::value, "LLVector4a must be a standard layout type");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -262,6 +262,8 @@ LLCacheName::~LLCacheName()
|
||||
delete &impl;
|
||||
}
|
||||
|
||||
const ReverseCache& LLCacheName::getReverseMap() const { return impl.mReverseCache; }
|
||||
|
||||
LLCacheName::Impl::Impl(LLMessageSystem* msg)
|
||||
: mMsg(msg), mUpstreamHost(LLHost::invalid)
|
||||
{
|
||||
|
||||
@@ -57,6 +57,8 @@ public:
|
||||
LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host);
|
||||
~LLCacheName();
|
||||
|
||||
const std::map<std::string, LLUUID>& getReverseMap() const;
|
||||
|
||||
// registers the upstream host
|
||||
// for viewers, this is the currently connected simulator
|
||||
// for simulators, this is the data server
|
||||
|
||||
@@ -2146,7 +2146,7 @@ void LLRender::setLineWidth(F32 line_width)
|
||||
}
|
||||
if (mNewContext.lineWidth != line_width || mDirty)
|
||||
{
|
||||
if (mMode == LLRender::LINES || LLRender::LINE_STRIP)
|
||||
if (mMode == LLRender::LINES || mMode == LLRender::LINE_STRIP)
|
||||
{
|
||||
flush();
|
||||
}
|
||||
@@ -2492,7 +2492,8 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count)
|
||||
mColorsp[mCount] = mColorsp[mCount-1];
|
||||
}
|
||||
|
||||
mVerticesp[mCount] = mVerticesp[mCount-1];
|
||||
if (mCount > 0) // ND: Guard against crashes if mCount is zero, yes it can happen
|
||||
mVerticesp[mCount] = mVerticesp[mCount-1];
|
||||
|
||||
mPrimitiveReset = false;
|
||||
}
|
||||
@@ -2528,9 +2529,12 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32
|
||||
mCount++;
|
||||
mColorsp[mCount] = mColorsp[mCount-1];
|
||||
}
|
||||
|
||||
mVerticesp[mCount] = mVerticesp[mCount-1];
|
||||
mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
|
||||
|
||||
if (mCount > 0)
|
||||
{
|
||||
mVerticesp[mCount] = mVerticesp[mCount - 1];
|
||||
mTexcoordsp[mCount] = mTexcoordsp[mCount - 1];
|
||||
}
|
||||
|
||||
mPrimitiveReset = false;
|
||||
}
|
||||
@@ -2564,9 +2568,12 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLCo
|
||||
mColorsp.copyArray(mCount, colors, vert_count);
|
||||
mCount += vert_count;
|
||||
|
||||
mVerticesp[mCount] = mVerticesp[mCount-1];
|
||||
mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
|
||||
mColorsp[mCount] = mColorsp[mCount-1];
|
||||
if (mCount > 0)
|
||||
{
|
||||
mVerticesp[mCount] = mVerticesp[mCount - 1];
|
||||
mTexcoordsp[mCount] = mTexcoordsp[mCount - 1];
|
||||
mColorsp[mCount] = mColorsp[mCount - 1];
|
||||
}
|
||||
|
||||
mPrimitiveReset = false;
|
||||
}
|
||||
|
||||
@@ -1197,6 +1197,10 @@ void LLVertexBuffer::genBuffer(U32 size)
|
||||
{
|
||||
mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
|
||||
}
|
||||
if ((sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) && !mMappedData)
|
||||
{
|
||||
LL_ERRS() << "mMappedData allocation failedd" << LL_ENDL;
|
||||
}
|
||||
|
||||
sGLCount++;
|
||||
}
|
||||
@@ -1213,6 +1217,10 @@ void LLVertexBuffer::genIndices(U32 size)
|
||||
{
|
||||
mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize);
|
||||
}
|
||||
if ((sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) && !mMappedIndexData)
|
||||
{
|
||||
LL_ERRS() << "mMappedIndexData allocation failedd" << LL_ENDL;
|
||||
}
|
||||
|
||||
sGLCount++;
|
||||
}
|
||||
@@ -1848,6 +1856,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
|
||||
LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL;
|
||||
}
|
||||
|
||||
bool was_locked = mIndexLocked;
|
||||
if (!mIndexLocked)
|
||||
{
|
||||
mIndexLocked = true;
|
||||
@@ -1942,6 +1951,10 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
|
||||
|
||||
LL_ERRS() << "glMapBuffer returned NULL (no index data)" << LL_ENDL;
|
||||
}
|
||||
else if (was_locked)
|
||||
{
|
||||
LL_ERRS() << "mIndexLocked was true but no Index data allocated" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS() << "memory allocation for Index data failed. " << LL_ENDL;
|
||||
|
||||
@@ -1709,7 +1709,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
||||
absl::flat_hash_map
|
||||
absl::node_hash_map
|
||||
nlohmann_json::nlohmann_json
|
||||
${FMT_LIBRARY}
|
||||
fmt::fmt
|
||||
)
|
||||
|
||||
if (LINUX)
|
||||
|
||||
@@ -349,7 +349,10 @@ bool LLAttachmentsMgr::getPendingAttachments(uuid_set_t& ids) const
|
||||
ids.clear();
|
||||
|
||||
// Returns the union of the LL maintained list of attachments that are waiting for link creation and our maintained list of attachments that are pending link creation
|
||||
set_union(mRecentlyArrivedAttachments.begin(), mRecentlyArrivedAttachments.end(), mPendingAttachLinks.begin(), mPendingAttachLinks.end(), std::inserter(ids, ids.begin()));
|
||||
ids.insert(mRecentlyArrivedAttachments.begin(), mRecentlyArrivedAttachments.end());
|
||||
ids.insert(mPendingAttachLinks.begin(), mPendingAttachLinks.end());
|
||||
// Singu Note: "Expression: Sequence not ordered" using std::set_union
|
||||
//set_union(mRecentlyArrivedAttachments.begin(), mRecentlyArrivedAttachments.end(), mPendingAttachLinks.begin(), mPendingAttachLinks.end(), std::inserter(ids, ids.begin()));
|
||||
|
||||
return !ids.empty();
|
||||
}
|
||||
|
||||
@@ -531,17 +531,24 @@ void LLChatBar::sendChat( EChatType type )
|
||||
// static
|
||||
void LLChatBar::startChat(const char* line)
|
||||
{
|
||||
if (!gChatBar || !gChatBar->getParent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
gChatBar->getParent()->setVisible(TRUE);
|
||||
gChatBar->setKeyboardFocus(TRUE);
|
||||
gSavedSettings.setBOOL("ChatVisible", TRUE);
|
||||
|
||||
if (line && gChatBar->mInputEditor)
|
||||
if (gChatBar->mInputEditor)
|
||||
{
|
||||
std::string line_string(line);
|
||||
gChatBar->mInputEditor->setText(line_string);
|
||||
if (line)
|
||||
{
|
||||
std::string line_string(line);
|
||||
gChatBar->mInputEditor->setText(line_string);
|
||||
}
|
||||
// always move cursor to end so users don't obliterate chat when accidentally hitting WASD
|
||||
gChatBar->mInputEditor->setCursorToEnd();
|
||||
}
|
||||
// always move cursor to end so users don't obliterate chat when accidentally hitting WASD
|
||||
gChatBar->mInputEditor->setCursorToEnd();
|
||||
}
|
||||
|
||||
|
||||
@@ -550,7 +557,8 @@ void LLChatBar::startChat(const char* line)
|
||||
void LLChatBar::stopChat()
|
||||
{
|
||||
// In simple UI mode, we never release focus from the chat bar
|
||||
gChatBar->setKeyboardFocus(FALSE);
|
||||
if (gChatBar)
|
||||
gChatBar->setKeyboardFocus(FALSE);
|
||||
|
||||
// If we typed a movement key and pressed return during the
|
||||
// same frame, the keyboard handlers will see the key as having
|
||||
@@ -562,7 +570,8 @@ void LLChatBar::stopChat()
|
||||
gAgent.stopTyping();
|
||||
|
||||
// hide chat bar so it doesn't grab focus back
|
||||
gChatBar->getParent()->setVisible(FALSE);
|
||||
if (gChatBar && gChatBar->getParent())
|
||||
gChatBar->getParent()->setVisible(FALSE);
|
||||
gSavedSettings.setBOOL("ChatVisible", FALSE);
|
||||
}
|
||||
|
||||
|
||||
@@ -515,6 +515,10 @@ void LLCloudLayer::connectNeighbor(LLCloudLayer *cloudp, U32 direction)
|
||||
return;
|
||||
}
|
||||
|
||||
if (mNeighbors[direction])
|
||||
{
|
||||
mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = NULL;
|
||||
}
|
||||
mNeighbors[direction] = cloudp;
|
||||
if (cloudp)
|
||||
mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = this;
|
||||
|
||||
@@ -1596,11 +1596,7 @@ void LLSpatialBridge::cleanupReferences()
|
||||
LLDrawable::cleanupReferences();
|
||||
if (mDrawable)
|
||||
{
|
||||
/*
|
||||
|
||||
DON'T DO THIS -- this should happen through octree destruction
|
||||
|
||||
mDrawable->setSpatialGroup(NULL);
|
||||
mDrawable->setGroup(NULL);
|
||||
if (mDrawable->getVObj())
|
||||
{
|
||||
LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren();
|
||||
@@ -1608,17 +1604,18 @@ void LLSpatialBridge::cleanupReferences()
|
||||
iter != child_list.end(); iter++)
|
||||
{
|
||||
LLViewerObject* child = *iter;
|
||||
LLDrawable* drawable = child->mDrawable;
|
||||
LLDrawable* drawable = child->mDrawable;
|
||||
if (drawable)
|
||||
{
|
||||
drawable->setSpatialGroup(NULL);
|
||||
drawable->setGroup(NULL);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
LLPointer<LLDrawable> drawablep = mDrawable;
|
||||
LLPointer<LLSpatialBridge> bridgep = mDrawable->getSpatialBridge();
|
||||
mDrawable->setSpatialBridge(nullptr);
|
||||
mDrawable = nullptr;
|
||||
drawablep->setSpatialBridge(nullptr);
|
||||
bridgep = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
//
|
||||
LLColor4 agent_chat_color(const LLUUID& id, const std::string&, bool local_chat = true);
|
||||
LLColor4 get_text_color(const LLChat& chat, bool from_im = false);
|
||||
void show_log_browser(const std::string&, const std::string&);
|
||||
void show_log_browser(const std::string&, const LLUUID&);
|
||||
|
||||
//
|
||||
// Member Functions
|
||||
@@ -96,7 +96,7 @@ LLFloaterChat::LLFloaterChat(const LLSD& seed)
|
||||
|
||||
LLTextEditor* history_editor_with_mute = getChild<LLTextEditor>("Chat History Editor with mute");
|
||||
getChild<LLUICtrl>("show mutes")->setCommitCallback(boost::bind(&LLFloaterChat::onClickToggleShowMute, this, _2, getChild<LLTextEditor>("Chat History Editor"), history_editor_with_mute));
|
||||
getChild<LLUICtrl>("chat_history_open")->setCommitCallback(boost::bind(show_log_browser, "chat", "chat"));
|
||||
getChild<LLUICtrl>("chat_history_open")->setCommitCallback(boost::bind(show_log_browser, "chat", LLUUID::null));
|
||||
}
|
||||
|
||||
LLFloaterChat::~LLFloaterChat()
|
||||
@@ -243,7 +243,7 @@ void log_chat_text(const LLChat& chat)
|
||||
else
|
||||
histstr = chat.mText;
|
||||
|
||||
LLLogChat::saveHistory(std::string("chat"), histstr);
|
||||
LLLogChat::saveHistory("chat", LLUUID::null, histstr);
|
||||
}
|
||||
// static
|
||||
void LLFloaterChat::addChatHistory(LLChat& chat, bool log_to_file)
|
||||
@@ -535,28 +535,19 @@ LLColor4 get_text_color(const LLChat& chat, bool from_im)
|
||||
//static
|
||||
void LLFloaterChat::loadHistory()
|
||||
{
|
||||
LLLogChat::loadHistory("chat", &chatFromLogFile, (void*)LLFloaterChat::getInstance());
|
||||
LLLogChat::loadHistory("chat", LLUUID::null, boost::bind(&LLFloaterChat::chatFromLogFile, getInstance(), _1, _2));
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
|
||||
|
||||
void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type, const std::string& line)
|
||||
{
|
||||
switch (type)
|
||||
bool log_line = type == LLLogChat::LOG_LINE;
|
||||
if (log_line || gSavedPerAccountSettings.getBOOL("LogChat"))
|
||||
{
|
||||
case LLLogChat::LOG_EMPTY:
|
||||
if (gSavedPerAccountSettings.getBOOL("LogChat"))
|
||||
addChatHistory(static_cast<LLFloaterChat*>(userdata)->getString("IM_logging_string"), false);
|
||||
break;
|
||||
case LLLogChat::LOG_END:
|
||||
if (gSavedPerAccountSettings.getBOOL("LogChat"))
|
||||
addChatHistory(static_cast<LLFloaterChat*>(userdata)->getString("IM_end_log_string"), false);
|
||||
break;
|
||||
case LLLogChat::LOG_LINE:
|
||||
addChatHistory(line, FALSE);
|
||||
break;
|
||||
default:
|
||||
// nothing
|
||||
break;
|
||||
LLStyleSP style(new LLStyle(true, gSavedSettings.getColor4("LogChatColor"), LLStringUtil::null));
|
||||
const auto text = log_line ? line : getString(type == LLLogChat::LOG_END ? "IM_end_log_string" : "IM_logging_string");
|
||||
for (const auto& ed_name : { "Chat History Editor", "Chat History Editor with mute" })
|
||||
getChild<LLTextEditor>(ed_name)->appendText(text, false, true, style, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
static void triggerAlerts(const std::string& text);
|
||||
|
||||
void onClickToggleShowMute(bool show_mute, class LLTextEditor* history_editor, LLTextEditor* history_editor_with_mute);
|
||||
static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
|
||||
void chatFromLogFile(LLLogChat::ELogLineType type, const std::string& line);
|
||||
static void loadHistory();
|
||||
static void* createSpeakersPanel(void* data);
|
||||
static void* createChatPanel(void* data);
|
||||
|
||||
@@ -94,7 +94,7 @@ void LLHUDIcon::renderIcon(BOOL for_select)
|
||||
if (mHidden)
|
||||
return;
|
||||
|
||||
if (mSourceObject.isNull() || mImagep.isNull())
|
||||
if (mSourceObject.isNull() || mImagep.isNull() || mSourceObject->mDrawable.isNull())
|
||||
{
|
||||
markDead();
|
||||
return;
|
||||
|
||||
@@ -375,9 +375,7 @@ LLFloaterIMPanel::LLFloaterIMPanel(
|
||||
|
||||
if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
|
||||
{
|
||||
LLLogChat::loadHistory(mLogLabel,
|
||||
&chatFromLogFile,
|
||||
(void *)this);
|
||||
LLLogChat::loadHistory(mLogLabel, mSessionType == P2P_SESSION ? mOtherParticipantUUID : mSessionUUID, boost::bind(&LLFloaterIMPanel::chatFromLogFile, this, _1, _2));
|
||||
}
|
||||
|
||||
if ( !mSessionInitialized )
|
||||
@@ -861,7 +859,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, LLColor4 incol
|
||||
// Floater title contains display name -> bad idea to use that as filename
|
||||
// mLogLabel, however, is the old legacy name
|
||||
//LLLogChat::saveHistory(getTitle(),histstr);
|
||||
LLLogChat::saveHistory(mLogLabel, histstr);
|
||||
LLLogChat::saveHistory(mLogLabel, mSessionType == P2P_SESSION ? mOtherParticipantUUID : mSessionUUID, histstr);
|
||||
// [/Ansariel: Display name support]
|
||||
}
|
||||
|
||||
@@ -1179,9 +1177,9 @@ void LLFloaterIMPanel::onFlyoutCommit(LLComboBox* flyout, const LLSD& value)
|
||||
}
|
||||
}
|
||||
|
||||
void show_log_browser(const std::string& name, const std::string& id)
|
||||
void show_log_browser(const std::string& name, const LLUUID& id)
|
||||
{
|
||||
const std::string file(LLLogChat::makeLogFileName(name));
|
||||
const std::string file(LLLogChat::makeLogFileName(name, id));
|
||||
if (!LLFile::isfile(file))
|
||||
{
|
||||
make_ui_sound("UISndBadKeystroke");
|
||||
@@ -1195,7 +1193,7 @@ void show_log_browser(const std::string& name, const std::string& id)
|
||||
}
|
||||
LLFloaterWebContent::Params p;
|
||||
p.url("file:///" + file);
|
||||
p.id(id);
|
||||
p.id(id.asString());
|
||||
p.show_chrome(false);
|
||||
p.trusted_content(true);
|
||||
LLFloaterWebContent::showInstance("log", p); // If we passed id instead of "log", there would be no control over how many log browsers opened at once.
|
||||
@@ -1206,8 +1204,8 @@ void LLFloaterIMPanel::onClickHistory()
|
||||
if (mOtherParticipantUUID.notNull())
|
||||
{
|
||||
// [Ansariel: Display name support]
|
||||
//show_log_browser(getTitle(), mOtherParticipantUUID.asString());
|
||||
show_log_browser(mLogLabel, mOtherParticipantUUID.asString());
|
||||
//show_log_browser(getTitle(), mSessionType == P2P_SESSION ? mOtherParticipantUUID : mSessionUUID);
|
||||
show_log_browser(mLogLabel, mSessionType == P2P_SESSION ? mOtherParticipantUUID : mSessionUUID);
|
||||
// [/Ansariel: Display name support]
|
||||
}
|
||||
}
|
||||
@@ -1671,39 +1669,16 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLUUID& from_id)
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
|
||||
void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, const std::string& line)
|
||||
{
|
||||
LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata;
|
||||
std::string message = line;
|
||||
|
||||
switch (type)
|
||||
bool log_line = type == LLLogChat::LOG_LINE;
|
||||
if (log_line || gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
|
||||
{
|
||||
case LLLogChat::LOG_EMPTY:
|
||||
// add warning log enabled message
|
||||
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
|
||||
{
|
||||
message = LLFloaterChat::getInstance()->getString("IM_logging_string");
|
||||
}
|
||||
break;
|
||||
case LLLogChat::LOG_END:
|
||||
// add log end message
|
||||
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
|
||||
{
|
||||
message = LLFloaterChat::getInstance()->getString("IM_end_log_string");
|
||||
}
|
||||
break;
|
||||
case LLLogChat::LOG_LINE:
|
||||
// just add normal lines from file
|
||||
break;
|
||||
default:
|
||||
// nothing
|
||||
break;
|
||||
LLStyleSP style(new LLStyle(true, gSavedSettings.getColor4("LogChatColor"), LLStringUtil::null));
|
||||
mHistoryEditor->appendText(log_line ? line :
|
||||
getString(type == LLLogChat::LOG_END ? "IM_end_log_string" : "IM_logging_string"),
|
||||
false, true, style, false);
|
||||
}
|
||||
|
||||
//self->addHistoryLine(line, LLColor4::grey, FALSE);
|
||||
LLStyleSP style(new LLStyle(true, gSavedSettings.getColor4("LogChatColor"), LLStringUtil::null));
|
||||
self->mHistoryEditor->appendText(message, false, true, style, false);
|
||||
}
|
||||
|
||||
void LLFloaterIMPanel::showSessionStartError(
|
||||
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
|
||||
// Handle other participant in the session typing.
|
||||
void processIMTyping(const LLUUID& from_id, BOOL typing);
|
||||
static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
|
||||
void chatFromLogFile(LLLogChat::ELogLineType type, const std::string& line);
|
||||
|
||||
//show error statuses to the user
|
||||
void showSessionStartError(const std::string& error_string);
|
||||
|
||||
@@ -560,7 +560,7 @@ void LLIMProcessing::processNewMessage(const LLUUID& from_id,
|
||||
chat.mFromID = from_id;
|
||||
chat.mFromName = name;
|
||||
chat.mSourceType = (from_id.isNull() || (name == SYSTEM_FROM)) ? CHAT_SOURCE_SYSTEM :
|
||||
(dialog == IM_FROM_TASK && dialog == IM_FROM_TASK_AS_ALERT) ? CHAT_SOURCE_OBJECT : CHAT_SOURCE_AGENT;
|
||||
(dialog == IM_FROM_TASK || dialog == IM_FROM_TASK_AS_ALERT) ? CHAT_SOURCE_OBJECT : CHAT_SOURCE_AGENT;
|
||||
|
||||
bool is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat)
|
||||
// object IMs contain sender object id in session_id (STORM-1209)
|
||||
@@ -1895,6 +1895,11 @@ void LLIMProcessing::requestOfflineMessages()
|
||||
|
||||
void LLIMProcessing::requestOfflineMessagesCoro(const LLCoroResponder& responder)
|
||||
{
|
||||
if (LLApp::isQuitting() || !gAgent.getRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto status = responder.getStatus();
|
||||
|
||||
if (!responder.isGoodStatus(status)) // success = httpResults["success"].asBoolean();
|
||||
|
||||
@@ -36,35 +36,132 @@
|
||||
#include "lllogchat.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llfloaterchat.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
static std::string get_log_dir_file(const std::string& filename)
|
||||
{
|
||||
return gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename);
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLLogChat::makeLogFileName(std::string filename)
|
||||
std::string LLLogChat::makeLogFileNameInternal(std::string filename)
|
||||
{
|
||||
if (gSavedPerAccountSettings.getBOOL("LogFileNamewithDate"))
|
||||
static const LLCachedControl<bool> with_date(gSavedPerAccountSettings, "LogFileNamewithDate");
|
||||
if (with_date)
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
char dbuffer[100]; /* Flawfinder: ignore */
|
||||
if (filename == "chat")
|
||||
{
|
||||
static const LLCachedControl<std::string> local_chat_date_format(gSavedPerAccountSettings, "LogFileLocalChatDateFormat", "-%Y-%m-%d");
|
||||
strftime(dbuffer, 100, local_chat_date_format().c_str(), localtime(&now));
|
||||
}
|
||||
else
|
||||
{
|
||||
static const LLCachedControl<std::string> ims_date_format(gSavedPerAccountSettings, "LogFileIMsDateFormat", "-%Y-%m");
|
||||
strftime(dbuffer, 100, ims_date_format().c_str(), localtime(&now));
|
||||
}
|
||||
filename += dbuffer;
|
||||
std::array<char, 100> dbuffer;
|
||||
static const LLCachedControl<std::string> local_chat_date_format(gSavedPerAccountSettings, "LogFileLocalChatDateFormat", "-%Y-%m-%d");
|
||||
static const LLCachedControl<std::string> ims_date_format(gSavedPerAccountSettings, "LogFileIMsDateFormat", "-%Y-%m");
|
||||
strftime(dbuffer.data(), dbuffer.size(), (filename == "chat" ? local_chat_date_format : ims_date_format)().c_str(), localtime(&now));
|
||||
filename += dbuffer.data();
|
||||
}
|
||||
cleanFileName(filename);
|
||||
return get_log_dir_file(filename + ".txt");
|
||||
}
|
||||
|
||||
bool LLLogChat::migrateFile(const std::string& old_name, const std::string& filename)
|
||||
{
|
||||
std::string oldfile = makeLogFileNameInternal(old_name);
|
||||
if (!LLFile::isfile(oldfile)) return false; // An old file by this name doesn't exist
|
||||
|
||||
if (LLFile::isfile(filename)) // A file by the new name also exists, but wasn't being tracked yet
|
||||
{
|
||||
auto&& new_untracked_log = llifstream(filename);
|
||||
auto&& tracked_log = llofstream(oldfile, llofstream::out|llofstream::app);
|
||||
// Append new to old and find out if it failed
|
||||
bool failed = !(tracked_log << new_untracked_log.rdbuf());
|
||||
// Close streams
|
||||
new_untracked_log.close();
|
||||
tracked_log.close();
|
||||
if (failed || LLFile::remove(filename)) // Delete the untracked new file so that reclaiming its name won't fail
|
||||
return true; // We failed to remove it or update the old file, let's just use the new file and leave the old one alone
|
||||
}
|
||||
|
||||
LLFile::rename(oldfile, filename); // Move the existing file to the new name
|
||||
return true; // Report success
|
||||
}
|
||||
|
||||
static LLSD sIDMap;
|
||||
|
||||
static std::string get_ids_map_file() { return get_log_dir_file("ids_to_names.json"); }
|
||||
void LLLogChat::initializeIDMap()
|
||||
{
|
||||
const auto map_file = get_ids_map_file();
|
||||
bool write = true; // Do we want to write back to map_file?
|
||||
if (LLFile::isfile(map_file)) // If we've already made this file, load our map from it
|
||||
{
|
||||
if (auto&& fstr = llifstream(map_file))
|
||||
{
|
||||
LLSDSerialize::fromNotation(sIDMap, fstr, LLSDSerialize::SIZE_UNLIMITED);
|
||||
fstr.close();
|
||||
}
|
||||
write = false; // Don't write what we just read
|
||||
}
|
||||
|
||||
if (gCacheName) // Load what we can from name cache to initialize or update the map and its file
|
||||
{
|
||||
bool empty = sIDMap.size() == 0; // Opt out of searching the map for IDs we added if we started with none
|
||||
for (const auto& r : gCacheName->getReverseMap()) // For every name id pair
|
||||
{
|
||||
const auto id = r.second.asString();
|
||||
const auto& name = r.first;
|
||||
const auto filename = makeLogFileNameInternal(name);
|
||||
bool id_known = !empty && sIDMap.has(id); // Is this ID known?
|
||||
if (id_known ? name != sIDMap[id].asStringRef() // If names don't match
|
||||
&& migrateFile(sIDMap[id].asStringRef(), filename) // Do we need to migrate an existing log?
|
||||
: LLFile::isfile(filename)) // Otherwise if there's a log file for them but they're not in the map yet
|
||||
{
|
||||
if (id_known) write = true; // We updated, write
|
||||
sIDMap[id] = name; // Add them to the map
|
||||
}
|
||||
}
|
||||
|
||||
if (write)
|
||||
if (auto&& fstr = llofstream(map_file))
|
||||
{
|
||||
LLSDSerialize::toPrettyNotation(sIDMap, fstr);
|
||||
fstr.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLLogChat::makeLogFileName(const std::string& username, const LLUUID& id)
|
||||
{
|
||||
const auto name = username.empty() ? id.asString() : username; // Fall back on ID if the grid sucks and we have no name
|
||||
std::string filename = makeLogFileNameInternal(name);
|
||||
if (id.notNull() && !LLFile::isfile(filename)) // No existing file by this user's current name, check for possible file rename
|
||||
{
|
||||
auto& entry = sIDMap[id.asString()];
|
||||
const bool empty = !entry.size();
|
||||
if (empty || entry != name) // If we haven't seen this entry yet, or the name is different than we remember
|
||||
{
|
||||
if (empty) // We didn't see this entry on load
|
||||
{
|
||||
// Ideally, we would look up the old names here via server request
|
||||
// In lieu of that, our reverse cache has old names and new names that we've gained since our initialization of the ID map
|
||||
for (const auto& r : gCacheName->getReverseMap())
|
||||
if (r.second == id && migrateFile(r.first, filename))
|
||||
break;
|
||||
}
|
||||
else migrateFile(entry.asStringRef(), filename); // We've seen this entry before, migrate old file if it exists
|
||||
|
||||
entry = name; // Update the entry to point to the new name
|
||||
|
||||
if (auto&& fstr = llofstream(get_ids_map_file())) // Write back to our map file
|
||||
{
|
||||
LLSDSerialize::toPrettyNotation(sIDMap, fstr);
|
||||
fstr.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
filename = cleanFileName(filename);
|
||||
filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename);
|
||||
filename += ".txt";
|
||||
return filename;
|
||||
}
|
||||
|
||||
std::string LLLogChat::cleanFileName(std::string filename)
|
||||
void LLLogChat::cleanFileName(std::string& filename)
|
||||
{
|
||||
std::string invalidChars = "\"\'\\/?*:<>|[]{}~"; // Cannot match glob or illegal filename chars
|
||||
S32 position = filename.find_first_of(invalidChars);
|
||||
@@ -73,7 +170,6 @@ std::string LLLogChat::cleanFileName(std::string filename)
|
||||
filename[position] = '_';
|
||||
position = filename.find_first_of(invalidChars, position);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
static void time_format(std::string& out, const char* fmt, const std::tm* time)
|
||||
@@ -92,6 +188,7 @@ static void time_format(std::string& out, const char* fmt, const std::tm* time)
|
||||
charvector.resize(1+size); // Use the String Stone
|
||||
format_the_time();
|
||||
}
|
||||
#undef format_the_time
|
||||
out.assign(charvector.data());
|
||||
}
|
||||
|
||||
@@ -117,15 +214,15 @@ std::string LLLogChat::timestamp(bool withdate)
|
||||
|
||||
|
||||
//static
|
||||
void LLLogChat::saveHistory(std::string const& filename, std::string line)
|
||||
void LLLogChat::saveHistory(const std::string& name, const LLUUID& id, const std::string& line)
|
||||
{
|
||||
if(!filename.size())
|
||||
if(name.empty() && id.isNull())
|
||||
{
|
||||
LL_INFOS() << "Filename is Empty!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLFILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(filename), "a"); /*Flawfinder: ignore*/
|
||||
LLFILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(name, id), "a"); /*Flawfinder: ignore*/
|
||||
if (!fp)
|
||||
{
|
||||
LL_INFOS() << "Couldn't open chat history log!" << LL_ENDL;
|
||||
@@ -140,10 +237,9 @@ void LLLogChat::saveHistory(std::string const& filename, std::string line)
|
||||
|
||||
static long const LOG_RECALL_BUFSIZ = 2048;
|
||||
|
||||
void LLLogChat::loadHistory(std::string const& filename , void (*callback)(ELogLineType, std::string, void*), void* userdata)
|
||||
void LLLogChat::loadHistory(const std::string& name, const LLUUID& id, std::function<void (ELogLineType, const std::string&)> callback)
|
||||
{
|
||||
bool filename_empty = filename.empty();
|
||||
if (filename_empty)
|
||||
if (name.empty() && id.isNull())
|
||||
{
|
||||
LL_WARNS() << "filename is empty!" << LL_ENDL;
|
||||
}
|
||||
@@ -154,7 +250,7 @@ void LLLogChat::loadHistory(std::string const& filename , void (*callback)(ELogL
|
||||
if (lines == 0) break;
|
||||
|
||||
// Open the log file.
|
||||
LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "rb");
|
||||
LLFILE* fptr = LLFile::fopen(makeLogFileName(name, id), "rb");
|
||||
if (!fptr) break;
|
||||
|
||||
// Set pos to point to the last character of the file, if any.
|
||||
@@ -199,20 +295,15 @@ void LLLogChat::loadHistory(std::string const& filename , void (*callback)(ELogL
|
||||
// Read lines from the file one by one until we reach the end of the file.
|
||||
while (fgets(buffer, LOG_RECALL_BUFSIZ, fptr))
|
||||
{
|
||||
size_t len = strlen(buffer);
|
||||
int i = len - 1;
|
||||
while (i >= 0 && (buffer[i] == '\r' || buffer[i] == '\n')) // strip newline chars from the end of the string
|
||||
{
|
||||
buffer[i] = '\0';
|
||||
i--;
|
||||
}
|
||||
callback(LOG_LINE, buffer, userdata);
|
||||
// strip newline chars from the end of the string
|
||||
for (S32 i = strlen(buffer) - 1; i >= 0 && (buffer[i] == '\r' || buffer[i] == '\n'); --i)
|
||||
buffer[i] = '\0';
|
||||
callback(LOG_LINE, buffer);
|
||||
}
|
||||
|
||||
fclose(fptr);
|
||||
callback(LOG_END, LLStringUtil::null, userdata);
|
||||
callback(LOG_END, LLStringUtil::null);
|
||||
return;
|
||||
}
|
||||
callback(LOG_EMPTY, LLStringUtil::null, userdata);
|
||||
callback(LOG_EMPTY, LLStringUtil::null);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,14 +45,16 @@ public:
|
||||
LOG_LINE,
|
||||
LOG_END
|
||||
};
|
||||
static void initializeIDMap();
|
||||
static std::string timestamp(bool withdate = false);
|
||||
static std::string makeLogFileName(std::string filename);
|
||||
static void saveHistory(std::string const& filename, std::string line);
|
||||
static void loadHistory(std::string const& filename,
|
||||
void (*callback)(ELogLineType,std::string,void*),
|
||||
void* userdata);
|
||||
static std::string makeLogFileName(const std::string& name, const LLUUID& id);
|
||||
static void saveHistory(const std::string& name, const LLUUID& id, const std::string& line);
|
||||
static void loadHistory(const std::string& name, const LLUUID& id,
|
||||
std::function<void (ELogLineType, const std::string&)> callback);
|
||||
private:
|
||||
static std::string cleanFileName(std::string filename);
|
||||
static std::string makeLogFileNameInternal(std::string filename);
|
||||
static bool migrateFile(const std::string& old_name, const std::string& filename);
|
||||
static void cleanFileName(std::string& filename);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -340,7 +340,7 @@ static std::string profile_picture_title(const std::string& str) { return "Profi
|
||||
static void show_partner_help() { LLNotificationsUtil::add("ClickPartnerHelpAvatar", LLSD(), LLSD(), boost::bind(LLPanelAvatarSecondLife::onClickPartnerHelpLoadURL, _1, _2)); }
|
||||
void show_log_browser(const LLUUID& id, const LFIDBearer::Type& type)
|
||||
{
|
||||
void show_log_browser(const std::string& name, const std::string& id);
|
||||
void show_log_browser(const std::string& name, const LLUUID& id);
|
||||
std::string name;
|
||||
if (type == LFIDBearer::AVATAR)
|
||||
{
|
||||
@@ -352,7 +352,7 @@ void show_log_browser(const LLUUID& id, const LFIDBearer::Type& type)
|
||||
{
|
||||
gCacheName->getGroupName(id, name);
|
||||
}
|
||||
show_log_browser(name, id.asString());
|
||||
show_log_browser(name, id);
|
||||
}
|
||||
BOOL LLPanelAvatarSecondLife::postBuild()
|
||||
{
|
||||
|
||||
@@ -1609,22 +1609,8 @@ std::string LLPreviewGesture::getLabel(const std::vector<std::string>& v_labels)
|
||||
for(const auto& pair : LLPreview::sInstances)
|
||||
{
|
||||
const auto& pPreview(pair.second);
|
||||
#ifndef LL_WINDOWS
|
||||
#if __cplusplus >= 201606
|
||||
constexpr std::string_view gesture("Gesture");
|
||||
if (pPreview && pPreview->getTitleName().compare(gesture) == 0)
|
||||
LL_COMPILE_TIME_MESSAGE("String view support detected, remove this macro check, this line and the old check below");
|
||||
#endif
|
||||
#endif
|
||||
if (pPreview && pPreview->getTitleName() ==
|
||||
#ifndef LL_WINDOWS
|
||||
static_cast<const std::string>(
|
||||
#endif
|
||||
"Gesture"
|
||||
#ifndef LL_WINDOWS
|
||||
)
|
||||
#endif
|
||||
)
|
||||
if (pPreview && std::string_view(pPreview->getTitleName()) == gesture)
|
||||
{
|
||||
wait_anim = pPreview->getChild<LLCheckBoxCtrl>("wait_anim_check")->getLabel();
|
||||
break;
|
||||
|
||||
@@ -316,7 +316,7 @@ public:
|
||||
|
||||
void drawObjectBox(LLColor4 col);
|
||||
|
||||
LLSpatialPartition* getSpatialPartition() const {return (LLSpatialPartition*)mSpatialPartition;}
|
||||
LLSpatialPartition* getSpatialPartition() const {return mSpatialPartition;}
|
||||
|
||||
//LISTENER FUNCTIONS
|
||||
void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* face) final override;
|
||||
|
||||
@@ -1837,6 +1837,7 @@ bool idle_startup()
|
||||
display_startup();
|
||||
|
||||
LLStartUp::initNameCache();
|
||||
LLLogChat::initializeIDMap(); // Name cache loaded, create a happy mappy
|
||||
display_startup();
|
||||
|
||||
// update the voice settings *after* gCacheName initialization
|
||||
|
||||
@@ -872,7 +872,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
|
||||
mCacheReadCount(0U),
|
||||
mCacheWriteCount(0U)
|
||||
{
|
||||
mCanUseNET = mUrl.empty() && !gHippoGridManager->getConnectedGrid()->isSecondLife();
|
||||
mCanUseNET = mUrl.empty(); // Necessary for precached UUID textures, regardless of grid.
|
||||
|
||||
if (!mCanUseNET)
|
||||
{
|
||||
|
||||
@@ -548,24 +548,29 @@ void start_chat( EKeystate s )
|
||||
}
|
||||
|
||||
// start chat
|
||||
gChatBar->startChat(NULL);
|
||||
LLChatBar::startChat(NULL);
|
||||
}
|
||||
|
||||
void start_gesture( EKeystate s )
|
||||
{
|
||||
if (LLAppViewer::instance()->quitRequested())
|
||||
{
|
||||
return; // can't talk, gotta go, kthxbye!
|
||||
}
|
||||
|
||||
LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
|
||||
if (KEYSTATE_UP == s &&
|
||||
! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
|
||||
{
|
||||
if (gChatBar->getCurrentChat().empty())
|
||||
if (gChatBar && gChatBar->getCurrentChat().empty())
|
||||
{
|
||||
// No existing chat in chat editor, insert '/'
|
||||
gChatBar->startChat("/");
|
||||
LLChatBar::startChat("/");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't overwrite existing text in chat editor
|
||||
gChatBar->startChat(NULL);
|
||||
LLChatBar::startChat(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,10 +152,6 @@ bool can_block(const LLUUID& id);
|
||||
static const boost::regex NEWLINES("\\n{1}");
|
||||
// NaCl End
|
||||
|
||||
|
||||
|
||||
extern AIHTTPTimeoutPolicy authHandler_timeout;
|
||||
|
||||
//
|
||||
// Constants
|
||||
//
|
||||
@@ -3877,17 +3873,18 @@ void process_sound_trigger(LLMessageSystem* msg, void**)
|
||||
msg->getUUIDFast(_PREHASH_SoundData, _PREHASH_ObjectID, object_id);
|
||||
|
||||
// NaCl - Antispam Registry
|
||||
if (auto antispam = NACLAntiSpamRegistry::getIfExists())
|
||||
if (NACLAntiSpamRegistry::instanceExists())
|
||||
{
|
||||
auto& antispam = NACLAntiSpamRegistry::instance();
|
||||
static const LLCachedControl<U32> _NACL_AntiSpamSoundMulti("_NACL_AntiSpamSoundMulti");
|
||||
if (owner_id.isNull())
|
||||
{
|
||||
bool is_collision_sound(const std::string & sound);
|
||||
if (!is_collision_sound(sound_id.asString())
|
||||
&& antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, object_id, LFIDBearer::OBJECT, _NACL_AntiSpamSoundMulti))
|
||||
&& antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, object_id, LFIDBearer::OBJECT, _NACL_AntiSpamSoundMulti))
|
||||
return;
|
||||
}
|
||||
else if (antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, owner_id, LFIDBearer::AVATAR, _NACL_AntiSpamSoundMulti)) return;
|
||||
else if (antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, owner_id, LFIDBearer::AVATAR, _NACL_AntiSpamSoundMulti)) return;
|
||||
}
|
||||
// NaCl End
|
||||
|
||||
@@ -3967,12 +3964,13 @@ void process_preload_sound(LLMessageSystem* msg, void** user_data)
|
||||
msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id);
|
||||
|
||||
// NaCl - Antispam Registry
|
||||
if (auto antispam = NACLAntiSpamRegistry::getIfExists())
|
||||
if (NACLAntiSpamRegistry::instanceExists())
|
||||
{
|
||||
auto& antispam = NACLAntiSpamRegistry::instance();
|
||||
static const LLCachedControl<U32> _NACL_AntiSpamSoundPreloadMulti("_NACL_AntiSpamSoundPreloadMulti");
|
||||
if ((owner_id.isNull()
|
||||
&& antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND_PRELOAD, object_id, LFIDBearer::OBJECT, _NACL_AntiSpamSoundPreloadMulti))
|
||||
|| antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND_PRELOAD, owner_id, LFIDBearer::AVATAR, _NACL_AntiSpamSoundPreloadMulti))
|
||||
&& antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND_PRELOAD, object_id, LFIDBearer::OBJECT, _NACL_AntiSpamSoundPreloadMulti))
|
||||
|| antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND_PRELOAD, owner_id, LFIDBearer::AVATAR, _NACL_AntiSpamSoundPreloadMulti))
|
||||
return;
|
||||
}
|
||||
// NaCl End
|
||||
@@ -4012,11 +4010,12 @@ void process_attached_sound(LLMessageSystem* msg, void** user_data)
|
||||
msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_OwnerID, owner_id);
|
||||
|
||||
// NaCl - Antispam Registry
|
||||
if (auto antispam = NACLAntiSpamRegistry::getIfExists())
|
||||
if (NACLAntiSpamRegistry::instanceExists())
|
||||
{
|
||||
auto& antispam = NACLAntiSpamRegistry::instance();
|
||||
if ((owner_id.isNull()
|
||||
&& antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, object_id, LFIDBearer::OBJECT))
|
||||
|| antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, owner_id))
|
||||
&& antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, object_id, LFIDBearer::OBJECT))
|
||||
|| antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SOUND, owner_id))
|
||||
return;
|
||||
}
|
||||
// NaCl End
|
||||
@@ -5775,9 +5774,11 @@ void process_economy_data(LLMessageSystem* msg, void** /*user_data*/)
|
||||
void notify_cautioned_script_question(const LLSD& notification, const LLSD& response, S32 orig_questions, BOOL granted)
|
||||
{
|
||||
// NaCl - Antispam Registry
|
||||
if (auto antispam = NACLAntiSpamRegistry::getIfExists())
|
||||
if (antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, notification["payload"]["task_id"].asUUID(), LFIDBearer::OBJECT))
|
||||
if (NACLAntiSpamRegistry::instanceExists())
|
||||
{
|
||||
if (NACLAntiSpamRegistry::instance().checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, notification["payload"]["task_id"].asUUID(), LFIDBearer::OBJECT))
|
||||
return;
|
||||
}
|
||||
// NaCl End
|
||||
// only continue if at least some permissions were requested
|
||||
if (orig_questions)
|
||||
@@ -6052,11 +6053,12 @@ void process_script_question(LLMessageSystem* msg, void** user_data)
|
||||
msg->getUUIDFast(_PREHASH_Data, _PREHASH_ItemID, itemid);
|
||||
|
||||
// NaCl - Antispam Registry
|
||||
if (auto antispam = NACLAntiSpamRegistry::getIfExists())
|
||||
if (NACLAntiSpamRegistry::instanceExists())
|
||||
{
|
||||
auto& antispam = NACLAntiSpamRegistry::instance();
|
||||
if ((taskid.isNull()
|
||||
&& antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, itemid, LFIDBearer::NONE))
|
||||
|| antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, taskid, LFIDBearer::OBJECT))
|
||||
&& antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, itemid, LFIDBearer::NONE))
|
||||
|| antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, taskid, LFIDBearer::OBJECT))
|
||||
return;
|
||||
}
|
||||
// NaCl End
|
||||
@@ -7104,6 +7106,12 @@ void callback_load_url_name(const LLUUID& id, const std::string& full_name, bool
|
||||
}
|
||||
}
|
||||
|
||||
// We've got the name of the person who owns the object hurling the url.
|
||||
void callback_load_url_avatar_name(const LLUUID& id, const LLAvatarName& av_name)
|
||||
{
|
||||
callback_load_url_name(id, av_name.getUserName(), false);
|
||||
}
|
||||
|
||||
void process_load_url(LLMessageSystem* msg, void**)
|
||||
{
|
||||
LLUUID object_id;
|
||||
@@ -7124,11 +7132,12 @@ void process_load_url(LLMessageSystem* msg, void**)
|
||||
|
||||
msg->getBOOL("Data", "OwnerIsGroup", owner_is_group);
|
||||
// NaCl - Antispam Registry
|
||||
if (auto antispam = NACLAntiSpamRegistry::getIfExists())
|
||||
if (NACLAntiSpamRegistry::instanceExists())
|
||||
{
|
||||
auto& antispam = NACLAntiSpamRegistry::instance();
|
||||
if ((owner_id.isNull()
|
||||
&& antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, object_id, LFIDBearer::OBJECT))
|
||||
|| antispam->checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, owner_id, owner_is_group ? LFIDBearer::GROUP : LFIDBearer::AVATAR))
|
||||
&& antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, object_id, LFIDBearer::OBJECT))
|
||||
|| antispam.checkQueue(NACLAntiSpamRegistry::QUEUE_SCRIPT_DIALOG, owner_id, owner_is_group ? LFIDBearer::GROUP : LFIDBearer::AVATAR))
|
||||
return;
|
||||
}
|
||||
// NaCl End
|
||||
@@ -7157,8 +7166,14 @@ void process_load_url(LLMessageSystem* msg, void**)
|
||||
// Add to list of pending name lookups
|
||||
gLoadUrlList.push_back(payload);
|
||||
|
||||
gCacheName->get(owner_id, owner_is_group,
|
||||
boost::bind(&callback_load_url_name, _1, _2, _3));
|
||||
if (owner_is_group)
|
||||
{
|
||||
gCacheName->getGroup(owner_id, boost::bind(&callback_load_url_name, _1, _2, _3));
|
||||
}
|
||||
else
|
||||
{
|
||||
LLAvatarNameCache::get(owner_id, boost::bind(&callback_load_url_avatar_name, _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7308,21 +7323,15 @@ void onCovenantLoadComplete(LLVFS* vfs,
|
||||
|
||||
S32 file_length = file.getSize();
|
||||
|
||||
char* buffer = new char[file_length+1];
|
||||
if (buffer == NULL)
|
||||
{
|
||||
LL_ERRS("Messaging") << "Memory Allocation failed" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
file.read((U8*)buffer, file_length); /* Flawfinder: ignore */
|
||||
std::vector<char> buffer(file_length + 1);
|
||||
file.read((U8*)&buffer[0], file_length);
|
||||
// put a EOS at the end
|
||||
buffer[file_length] = 0;
|
||||
|
||||
if( (file_length > 19) && !strncmp( buffer, "Linden text version", 19 ) )
|
||||
buffer[file_length] = '\0';
|
||||
|
||||
if ((file_length > 19) && !strncmp(&buffer[0], "Linden text version", 19))
|
||||
{
|
||||
LLViewerTextEditor * editor = new LLViewerTextEditor(std::string("temp"), LLRect(0,0,0,0), file_length+1);
|
||||
if( !editor->importBuffer( buffer, file_length+1 ) )
|
||||
if( !editor->importBuffer( &buffer[0], file_length+1 ) )
|
||||
{
|
||||
LL_WARNS("Messaging") << "Problem importing estate covenant." << LL_ENDL;
|
||||
covenant_text = "Problem importing estate covenant.";
|
||||
@@ -7339,7 +7348,6 @@ void onCovenantLoadComplete(LLVFS* vfs,
|
||||
LL_WARNS("Messaging") << "Problem importing estate covenant: Covenant file format error." << LL_ENDL;
|
||||
covenant_text = "Problem importing estate covenant: Covenant file format error.";
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -846,10 +846,12 @@ public:
|
||||
};
|
||||
|
||||
|
||||
LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part) :
|
||||
LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLSpatialPartition* part) :
|
||||
LLViewerOctreeGroup(node),
|
||||
mSpatialPartition(part)
|
||||
{
|
||||
llassert(part);
|
||||
mSpatialPartition->mGroups.push_back(this);
|
||||
part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
|
||||
mLODHash = part->mLODSeed;
|
||||
|
||||
@@ -867,12 +869,21 @@ LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctre
|
||||
|
||||
LLOcclusionCullingGroup::~LLOcclusionCullingGroup()
|
||||
{
|
||||
if (mSpatialPartition)
|
||||
{
|
||||
auto it = std::find_if(mSpatialPartition->mGroups.begin(), mSpatialPartition->mGroups.end(), [this](LLOcclusionCullingGroup* rhs) {return rhs == this; });
|
||||
llassert(it != mSpatialPartition->mGroups.end());
|
||||
if (it != mSpatialPartition->mGroups.end())
|
||||
{
|
||||
mSpatialPartition->mGroups.erase(it);
|
||||
}
|
||||
}
|
||||
releaseOcclusionQueryObjectNames();
|
||||
}
|
||||
|
||||
BOOL LLOcclusionCullingGroup::needsUpdate()
|
||||
{
|
||||
return (LLDrawable::getCurrentFrame() % mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
|
||||
return mSpatialPartition && (LLDrawable::getCurrentFrame() % mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOL LLOcclusionCullingGroup::isRecentlyVisible() const
|
||||
@@ -1070,6 +1081,10 @@ U32 LLOcclusionCullingGroup::getLastOcclusionIssuedTime()
|
||||
|
||||
void LLOcclusionCullingGroup::checkOcclusion()
|
||||
{
|
||||
if (mSpatialPartition == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (LLPipeline::sUseOcclusion > 1)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_READBACK);
|
||||
@@ -1170,6 +1185,10 @@ static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_DRAW("Draw");
|
||||
|
||||
void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* shift)
|
||||
{
|
||||
if (mSpatialPartition == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLGLDisable<GL_STENCIL_TEST> stencil;
|
||||
if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)
|
||||
{
|
||||
@@ -1319,6 +1338,11 @@ LLViewerOctreePartition::LLViewerOctreePartition() :
|
||||
|
||||
LLViewerOctreePartition::~LLViewerOctreePartition()
|
||||
{
|
||||
llassert(mGroups.empty());
|
||||
for (auto& entry : mGroups)
|
||||
{
|
||||
entry->mSpatialPartition = nullptr;
|
||||
}
|
||||
delete mOctree;
|
||||
mOctree = NULL;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ class LLViewerOctreeEntryData;
|
||||
class LLViewerOctreeGroup;
|
||||
class LLViewerOctreeEntry;
|
||||
class LLViewerOctreePartition;
|
||||
class LLSpatialPartition;
|
||||
|
||||
typedef LLOctreeListener<LLViewerOctreeEntry> OctreeListener;
|
||||
typedef LLTreeNode<LLViewerOctreeEntry> TreeNode;
|
||||
@@ -288,7 +289,7 @@ protected:
|
||||
virtual ~LLOcclusionCullingGroup();
|
||||
|
||||
public:
|
||||
LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part);
|
||||
LLOcclusionCullingGroup(OctreeNode* node, LLSpatialPartition* part);
|
||||
LLOcclusionCullingGroup(const LLOcclusionCullingGroup& rhs) : LLViewerOctreeGroup(rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
@@ -330,7 +331,8 @@ protected:
|
||||
|
||||
S32 mLODHash;
|
||||
|
||||
LLViewerOctreePartition* mSpatialPartition;
|
||||
friend class LLViewerOctreePartition;
|
||||
LLSpatialPartition* mSpatialPartition;
|
||||
U32 mOcclusionQuery[LLViewerCamera::NUM_CAMERAS];
|
||||
|
||||
public:
|
||||
@@ -355,6 +357,7 @@ public:
|
||||
BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed
|
||||
U32 mLODSeed;
|
||||
U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed)
|
||||
std::vector<LLOcclusionCullingGroup*> mGroups;
|
||||
};
|
||||
|
||||
class LLViewerOctreeCull : public OctreeTraveler
|
||||
|
||||
@@ -2946,7 +2946,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
|
||||
{
|
||||
{
|
||||
// passing NULL here, character will be added later when it is handled by character handler.
|
||||
gChatBar->startChat(NULL);
|
||||
LLChatBar::startChat(NULL);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -3548,7 +3548,7 @@ void LLViewerWindow::updateLayout()
|
||||
&& gFocusMgr.getKeyboardFocus() == NULL
|
||||
&& gChatBar->isInVisibleChain())
|
||||
{
|
||||
gChatBar->startChat(NULL);
|
||||
LLChatBar::startChat(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1153,7 +1153,7 @@ void LLPipeline::createGLBuffers()
|
||||
{
|
||||
if (!mNoiseMap)
|
||||
{
|
||||
LLVector3 noise[NOISE_MAP_RES*NOISE_MAP_RES];
|
||||
std::array<LLVector3, NOISE_MAP_RES * NOISE_MAP_RES> noise;
|
||||
|
||||
F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f;
|
||||
for (auto& val : noise)
|
||||
@@ -1166,7 +1166,7 @@ void LLPipeline::createGLBuffers()
|
||||
mNoiseMap = LLImageGL::createTextureName();
|
||||
|
||||
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap->getTexName());
|
||||
LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, NOISE_MAP_RES, NOISE_MAP_RES, GL_RGB, GL_FLOAT, noise);
|
||||
LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, NOISE_MAP_RES, NOISE_MAP_RES, GL_RGB, GL_FLOAT, noise.data());
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||
}
|
||||
|
||||
|
||||
@@ -2156,7 +2156,7 @@ Offer a teleport?<tag>Bestätigen</tag><form name="form">
|
||||
<button name="GoNow..." text="Jetzt gehen..."/>
|
||||
</form></notification>
|
||||
|
||||
<notification name="OfferFriendship">[NAME] bietet Ihnen die Freundschaft an.
|
||||
<notification name="OfferFriendship">[NAME_SLURL] bietet Ihnen die Freundschaft an.
|
||||
|
||||
[MESSAGE]
|
||||
|
||||
@@ -2169,7 +2169,7 @@ Offer a teleport?<tag>Bestätigen</tag><form name="form">
|
||||
|
||||
<notification name="FriendshipOffered">Sie haben [TO_NAME] die Freundschaft angeboten.</notification>
|
||||
|
||||
<notification name="OfferFriendshipNoMessage">[NAME] bietet Ihnen die Freundschaft an.
|
||||
<notification name="OfferFriendshipNoMessage">[NAME_SLURL] bietet Ihnen die Freundschaft an.
|
||||
|
||||
(Sie werden dadurch den gegenseitigen Online-Status sehen können.)<form name="form">
|
||||
<button name="Accept" text="Akzeptieren"/>
|
||||
@@ -2178,9 +2178,9 @@ Offer a teleport?<tag>Bestätigen</tag><form name="form">
|
||||
<button name="Profile" text="Profil"/>
|
||||
</form></notification>
|
||||
|
||||
<notification name="FriendshipAccepted">[NAME] hat Ihr Freundschaftsangebot akzeptiert.</notification>
|
||||
<notification name="FriendshipAccepted">[NAME_SLURL] hat Ihr Freundschaftsangebot akzeptiert.</notification>
|
||||
|
||||
<notification name="FriendshipDeclined">[NAME] hat Ihr Freundschaftsangebot abgelehnt.</notification>
|
||||
<notification name="FriendshipDeclined">[NAME_SLURL] hat Ihr Freundschaftsangebot abgelehnt.</notification>
|
||||
|
||||
<notification name="FriendshipDissolved">[NAME] hat Ihr Freundschaftsangebot abgelehnt.</notification>
|
||||
|
||||
|
||||
@@ -2788,7 +2788,7 @@ Riprova tra qualche istante.
|
||||
</form>
|
||||
</notification>
|
||||
<notification name="OfferFriendship">
|
||||
[NAME] ti ha offerto la sua amicizia.
|
||||
[NAME_SLURL] ti ha offerto la sua amicizia.
|
||||
|
||||
[MESSAGE]
|
||||
|
||||
@@ -2799,7 +2799,7 @@ Riprova tra qualche istante.
|
||||
</form>
|
||||
</notification>
|
||||
<notification name="OfferFriendshipNoMessage">
|
||||
[NAME] ti ha offerto la sua amicizia.
|
||||
[NAME_SLURL] ti ha offerto la sua amicizia.
|
||||
|
||||
(Di default, potrete vedervi reciprocamente online.)
|
||||
<form name="form">
|
||||
@@ -2808,10 +2808,10 @@ Riprova tra qualche istante.
|
||||
</form>
|
||||
</notification>
|
||||
<notification name="FriendshipAccepted">
|
||||
[NAME] ha accettato la tua offerta di amicizia.
|
||||
[NAME_SLURL] ha accettato la tua offerta di amicizia.
|
||||
</notification>
|
||||
<notification name="FriendshipDeclined">
|
||||
[NAME] ha rifiutato la tua offerta di amicizia.
|
||||
[NAME_SLURL] ha rifiutato la tua offerta di amicizia.
|
||||
</notification>
|
||||
<notification name="OfferCallingCard">
|
||||
[NAME] ti ha offerto il suo biglietto da visita.
|
||||
|
||||
@@ -3556,7 +3556,7 @@ No entanto, esta região tem conteúdo acessível apenas para adultos.
|
||||
</notification>
|
||||
|
||||
<notification name="OfferFriendship">
|
||||
[NAME] está lhe oferecendo sua amizade
|
||||
[NAME_SLURL] está lhe oferecendo sua amizade
|
||||
|
||||
[MESSAGE]
|
||||
|
||||
@@ -3572,7 +3572,7 @@ No entanto, esta região tem conteúdo acessível apenas para adultos.
|
||||
</notification>
|
||||
|
||||
<notification name="OfferFriendshipNoMessage">
|
||||
[NAME] está lhe oferecendo sua amizade.
|
||||
[NAME_SLURL] está lhe oferecendo sua amizade.
|
||||
|
||||
(Por definição vocês serão capazes de ver um ao outro online)
|
||||
<form name="form">
|
||||
@@ -3582,11 +3582,11 @@ No entanto, esta região tem conteúdo acessível apenas para adultos.
|
||||
</notification>
|
||||
|
||||
<notification name="FriendshipAccepted">
|
||||
[NAME] aceitou seu convite de amizade.
|
||||
[NAME_SLURL] aceitou seu convite de amizade.
|
||||
</notification>
|
||||
|
||||
<notification name="FriendshipDeclined">
|
||||
[NAME] recusou seu convite de amizade
|
||||
[NAME_SLURL] recusou seu convite de amizade
|
||||
</notification>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user