diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 7a7033b91d..f751037dd9 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -51,6 +51,7 @@ #define TCP_MAXSEG 2 #endif // defined(HAVE_LIBNX) || PPSSPP_PLATFORM(SWITCH) +#include #include #include "Common/Data/Text/I18n.h" @@ -111,13 +112,6 @@ SceNetAdhocctlAdhocId product_code; std::thread friendFinderThread; std::recursive_mutex peerlock; AdhocSocket* adhocSockets[MAX_SOCKET]; -std::vector chatLog; -std::string name = ""; -std::string incoming = ""; -std::string message = ""; -bool chatScreenVisible = false; -bool updateChatScreen = false; -int newChat = 0; bool isOriPort = false; bool isLocalServer = false; SockAddrIN4 g_adhocServerIP; @@ -125,6 +119,11 @@ SockAddrIN4 g_localhostIP; sockaddr LocalIP; int defaultWlanChannel = PSP_SYSTEMPARAM_ADHOC_CHANNEL_11; // Don't put 0(Auto) here, it needed to be a valid/actual channel number +static std::mutex chatLogLock; +static std::vector chatLog; +static int chatMessageGeneration = 0; +static int chatMessageCount = 0; + bool isMacMatch(const SceNetEtherAddr* addr1, const SceNetEtherAddr* addr2) { // Ignoring the 1st byte since there are games (ie. Gran Turismo) who tamper with the 1st byte of OUI to change the unicast/multicast bit return (memcmp(((const char*)addr1)+1, ((const char*)addr2)+1, ETHER_ADDR_LEN-1) == 0); @@ -1290,42 +1289,47 @@ void sendChat(std::string chatString) { auto n = GetI18NCategory("Networking"); chat.base.opcode = OPCODE_CHAT; //TODO check network inited, check send success or not, chatlog.pushback error on failed send, pushback error on not connected - if (friendFinderRunning) - { + if (friendFinderRunning) { // Send Chat to Server if (!chatString.empty()) { //maximum char allowed is 64 character for compability with original server (pro.coldbird.net) - message = chatString.substr(0, 60); // 64 return chat variable corrupted is it out of memory? + std::string message = chatString.substr(0, 60); // 64 return chat variable corrupted is it out of memory? strcpy(chat.message, message.c_str()); //Send Chat Messages if (IsSocketReady(metasocket, false, true) > 0) { int chatResult = send(metasocket, (const char*)&chat, sizeof(chat), MSG_NOSIGNAL); NOTICE_LOG(SCENET, "Send Chat %s to Adhoc Server", chat.message); - name = g_Config.sNickName.c_str(); + std::string name = g_Config.sNickName.c_str(); + + std::lock_guard guard(chatLogLock); chatLog.push_back(name.substr(0, 8) + ": " + chat.message); - if (chatScreenVisible) { - updateChatScreen = true; - } + chatMessageGeneration++; } } - } - else { + } else { + std::lock_guard guard(chatLogLock); chatLog.push_back(n->T("You're in Offline Mode, go to lobby or online hall")); - if (chatScreenVisible) { - updateChatScreen = true; - } + chatMessageGeneration++; } } std::vector getChatLog() { - // this log used by chat screen + std::lock_guard guard(chatLogLock); + // If the log gets large, trim it down. if (chatLog.size() > 50) { - //erase the first 40 element limit the chatlog size - chatLog.erase(chatLog.begin(), chatLog.begin() + 40); + chatLog.erase(chatLog.begin(), chatLog.begin() + (chatLog.size() - 50)); } return chatLog; } +int GetChatChangeID() { + return chatMessageGeneration; +} + +int GetChatMessageCount() { + return chatMessageCount; +} + int friendFinder(){ SetCurrentThreadName("FriendFinder"); auto n = GetI18NCategory("Networking"); @@ -1516,21 +1520,16 @@ int friendFinder(){ // Add Incoming Chat to HUD NOTICE_LOG(SCENET, "Received chat message %s", packet->base.message); - incoming = ""; - name = (char*)packet->name.data; + std::string incoming = ""; + std::string name = (char*)packet->name.data; incoming.append(name.substr(0, 8)); incoming.append(": "); incoming.append((char*)packet->base.message); + + std::lock_guard guard(chatLogLock); chatLog.push_back(incoming); - //im new to pointer btw :( doesn't know its safe or not this should update the chat screen when data coming - if (chatScreenVisible) { - updateChatScreen = true; - } - else { - if (newChat < 50) { - newChat += 1; - } - } + chatMessageGeneration++; + chatMessageCount++; // Move RX Buffer memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C)); @@ -1591,17 +1590,16 @@ int friendFinder(){ } // Update HUD User Count - name = (char*)packet->name.data; - incoming = ""; + std::string name = (char*)packet->name.data; + std::string incoming = ""; incoming.append(name.substr(0, 8)); incoming.append(" Joined "); //do we need ip? //joined.append((char *)packet->ip); + + std::lock_guard guard(chatLogLock); chatLog.push_back(incoming); - //im new to pointer btw :( doesn't know its safe or not this should update the chat screen when data coming - if (chatScreenVisible) { - updateChatScreen = true; - } + chatMessageGeneration++; #ifdef LOCALHOST_AS_PEER setUserCount(getActivePeerCount()); @@ -1609,7 +1607,7 @@ int friendFinder(){ // setUserCount(getActivePeerCount()+1); #endif - // Move RX Buffer + // Move RX Buffer memmove(rx, rx + sizeof(SceNetAdhocctlConnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectPacketS2C)); // Fix RX Buffer Length diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index 22b88059bd..a1343d25dd 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -1015,9 +1015,8 @@ void addFriend(SceNetAdhocctlConnectPacketS2C * packet); */ void sendChat(std::string chatString); std::vector getChatLog(); -extern bool chatScreenVisible; -extern bool updateChatScreen; -extern int newChat; +int GetChatChangeID(); +int GetChatMessageCount(); /* * Find a Peer/Friend by MAC address diff --git a/UI/ChatScreen.cpp b/UI/ChatScreen.cpp index dfb1acb14d..41eef866ae 100644 --- a/UI/ChatScreen.cpp +++ b/UI/ChatScreen.cpp @@ -172,14 +172,11 @@ void ChatMenu::Update() { scroll_->ScrollToBottom(); } - if (updateChatScreen) { + if (chatChangeID_ != GetChatChangeID()) { + chatChangeID_ = GetChatChangeID(); UpdateChat(); - updateChatScreen = false; } - chatScreenVisible = true; - newChat = 0; - #if defined(USING_WIN_UI) // Could remove the fullscreen check here, it works now. if (promptInput_ && g_Config.bBypassOSKWithKeyboard && !g_Config.bFullScreen) { @@ -203,5 +200,4 @@ bool ChatMenu::SubviewFocused(UI::View *view) { void ChatMenu::Close() { SetVisibility(UI::V_GONE); - chatScreenVisible = false; } diff --git a/UI/ChatScreen.h b/UI/ChatScreen.h index 83ca61b7b4..b068ddb1f0 100644 --- a/UI/ChatScreen.h +++ b/UI/ChatScreen.h @@ -38,6 +38,7 @@ private: UI::LinearLayout *chatVert_ = nullptr; UI::ViewGroup *box_ = nullptr; + int chatChangeID_ = 0; bool toBottom_ = true; bool promptInput_ = false; }; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 1b499a4708..f85f65243a 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -862,7 +862,7 @@ void EmuScreen::CreateViews() { break; } - ChoiceWithValueDisplay *btn = new ChoiceWithValueDisplay(&newChat, n->T("Chat"), layoutParams); + ChoiceWithValueDisplay *btn = new ChoiceWithValueDisplay(&newChatMessages_, n->T("Chat"), layoutParams); root_->Add(btn)->OnClick.Handle(this, &EmuScreen::OnChat); chatButton_ = btn; chatMenu_ = root_->Add(new ChatMenu(screenManager()->getUIContext()->GetBounds(), new LayoutParams(FILL_PARENT, FILL_PARENT))); @@ -987,6 +987,18 @@ void EmuScreen::update() { resumeButton_->SetVisibility(coreState == CoreState::CORE_RUNTIME_ERROR && Memory::MemFault_MayBeResumable() ? V_VISIBLE : V_GONE); resetButton_->SetVisibility(coreState == CoreState::CORE_RUNTIME_ERROR ? V_VISIBLE : V_GONE); + if (chatButton_ && chatMenu_) { + if (chatMenu_->GetVisibility() != V_GONE) { + chatMessages_ = GetChatMessageCount(); + newChatMessages_ = 0; + } else { + int diff = GetChatMessageCount() - chatMessages_; + chatMessages_ += diff; + // Cap the count at 50. + newChatMessages_ = diff > 50 ? 50 : diff; + } + } + if (bootPending_) { bootGame(gamePath_); } diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 79f47982d6..ff41bd81a4 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -86,6 +86,10 @@ private: // If set, pauses at the end of the frame. bool pauseTrigger_ = false; + // The last read chat message count, and how many new ones there are. + int chatMessages_ = 0; + int newChatMessages_ = 0; + // In-memory save state used for freezeFrame, which is useful for debugging. std::vector freezeState_;