From 10e874cefd887807a3553d7db6d67482689c83d8 Mon Sep 17 00:00:00 2001 From: Ade Novan Date: Fri, 21 Oct 2016 18:35:54 +0800 Subject: [PATCH] PPSSPP early chat feature rebranched --- Core/HLE/proAdhoc.cpp | 66 +++++++++++++++++++--- Core/HLE/proAdhoc.h | 9 +++ UI/ChatScreen.cpp | 124 ++++++++++++++++++++++++++++++++++++++++++ UI/ChatScreen.h | 21 +++++++ UI/EmuScreen.cpp | 13 +++++ UI/EmuScreen.h | 1 + UI/UI.vcxproj | 2 + UI/UI.vcxproj.filters | 6 ++ 8 files changed, 233 insertions(+), 9 deletions(-) create mode 100644 UI/ChatScreen.cpp create mode 100644 UI/ChatScreen.h diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index a7e154348..6288189eb 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -55,6 +55,11 @@ std::recursive_mutex peerlock; SceNetAdhocPdpStat * pdp[255]; SceNetAdhocPtpStat * ptp[255]; uint32_t localip; +std::vector chatLog; +ChatMenu* ch; +std::string name = ""; +std::string incoming = ""; +std::string message = ""; int isLocalMAC(const SceNetEtherAddr * addr) { SceNetEtherAddr saddr; @@ -981,6 +986,35 @@ void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) { free(node); } +void setChatPointer(ChatMenu* chatmenu) { + //set chatscreen instance + ch = chatmenu; +} + +void sendChat(std::string chatString) { + SceNetAdhocctlChatPacketC2S chat; + chat.base.opcode = OPCODE_CHAT; + //Send Chat Messages need to check network inited and already connected to server or not + //if (friendFinderRunning) + //{ + // Send Chat to Server + //maximum char allowed is 64 character for compability with original server (pro.coldbird.net) + message = chatString.substr(0, 57); // 64 return chat variable corrupted is it out of memory? + strcpy(chat.message, message.c_str()); + NOTICE_LOG(SCENET, "Send %s to Adhoc Server", chat.message); + int chatResult = send(metasocket, (const char *)&chat, sizeof(chat), 0); + //need to check if send success or not before appending to chat screen + name = g_Config.sNickName.c_str(); + chatLog.push_back(name.substr(0, 8) + ": " + chat.message); + //} +} + + +std::vector getChatLog() { + // this log used by chat screen + return chatLog; +} + int friendFinder(){ // Receive Buffer int rxpos = 0; @@ -1024,13 +1058,6 @@ int friendFinder(){ }*/ } - // Send Chat Messages - //while(popFromOutbox(chat.message)) - //{ - // // Send Chat to Server - // sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0); - //} - // Wait for Incoming Data int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos, 0); @@ -1084,7 +1111,19 @@ int friendFinder(){ // Add Incoming Chat to HUD //printf("Receive chat message %s", packet->base.message); - DEBUG_LOG(SCENET, "Received chat message %s", packet->base.message); + NOTICE_LOG(SCENET, "Received chat message %s", packet->base.message); + incoming = ""; + name = (char *)packet->name.data; + incoming.append(name.substr(0, 8)); + incoming.append(": "); + incoming.append((char *)packet->base.message); + 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 (ch) { + ch->UpdateChat(); + } + // Move RX Buffer + memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C)); // Move RX Buffer memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C)); @@ -1107,7 +1146,16 @@ int friendFinder(){ // Add User addFriend(packet); - + incoming = ""; + incoming.append((char *)packet->name.data); + incoming.append(" Joined "); + //do we need ip? + //joined.append((char *)packet->ip); + 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 (ch) { + ch->UpdateChat(); + } // Update HUD User Count #ifdef LOCALHOST_AS_PEER setUserCount(getActivePeerCount()); diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index 6573dd892..2ec786120 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -33,6 +33,7 @@ #include "Core/HLE/sceKernel.h" #include "Core/HLE/sceKernelMutex.h" #include "Core/HLE/sceUtility.h" +#include "UI/ChatScreen.h" class PointerWrap; @@ -842,6 +843,14 @@ SceNetAdhocMatchingMemberInternal* addMember(SceNetAdhocMatchingContext * contex */ void addFriend(SceNetAdhocctlConnectPacketS2C * packet); +/** +* Send chat or get that +* @param std::string ChatString +*/ +void setChatPointer(ChatMenu* chatmenu); +void sendChat(std::string chatString); +std::vector getChatLog(); + /* * Find a Peer/Friend by MAC address */ diff --git a/UI/ChatScreen.cpp b/UI/ChatScreen.cpp new file mode 100644 index 000000000..b34c705c4 --- /dev/null +++ b/UI/ChatScreen.cpp @@ -0,0 +1,124 @@ +#include "ui/ui_context.h" +#include "ui/view.h" +#include "ui/viewgroup.h" +#include "ui/ui.h" +#include "ChatScreen.h" +#include "Core/Config.h" +#include "Core/System.h" +#include "Common/LogManager.h" +#include "Core/HLE/proAdhoc.h" + +void ChatMenu::CreatePopupContents(UI::ViewGroup *parent) { + using namespace UI; + //tried to give instance to proAdhoc not working + //setChatPointer(this); + LinearLayout *outer = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, 400)); + scroll_ = outer->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(PopupWidth(), FILL_PARENT, 1.0f))); + chatVert_ = scroll_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(PopupWidth(), WRAP_CONTENT))); + chatVert_->SetSpacing(0); + LinearLayout *bottom = outer->Add(new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); + chatEdit_ = bottom->Add(new TextEdit("", "Chat Here", new LinearLayoutParams(1.0))); + chatEdit_->OnEnter.Handle(this, &ChatMenu::OnSubmit); + bottom->Add(new Button("Send"))->OnClick.Handle(this, &ChatMenu::OnSubmit); + parent->Add(outer); + UpdateChat(); +} + +void ChatMenu::CreateViews() { + using namespace UI; + + UIContext &dc = *screenManager()->getUIContext(); + + AnchorLayout *anchor = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); + anchor->Overflow(false); + root_ = anchor; + + float yres = screenManager()->getUIContext()->GetBounds().h; + + box_ = new LinearLayout(ORIENT_VERTICAL, + new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, 280, NONE, NONE, 250, true)); + + root_->Add(box_); + box_->SetBG(UI::Drawable(0x66303030)); + box_->SetHasDropShadow(false); + + View *title = new PopupHeader("Chat"); + box_->Add(title); + + CreatePopupContents(box_); + root_->SetDefaultFocusView(box_); +} + +void ChatMenu::dialogFinished(const Screen *dialog, DialogResult result) { + UpdateUIState(UISTATE_INGAME); + // Close when a subscreen got closed. + // TODO: a bug in screenmanager causes this not to work here. + // screenManager()->finishDialog(this, DR_OK); +} + +UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) { + std::string chat = chatEdit_->GetText(); + NOTICE_LOG(HLE, "Chat Send to socket: %s", chat.c_str()); + chatEdit_->SetText(""); + chatEdit_->SetFocus(); + sendChat(chat); + UpdateChat(); + return UI::EVENT_DONE; +} + +std::vector Split(const std::string& str, int splitLength) +{ + int NumSubstrings = str.length() / splitLength; + std::vector ret; + + // TODO sub string in white space + for (auto i = 0; i < NumSubstrings; i++) + { + ret.push_back(str.substr(i * splitLength, splitLength)); + } + + // If there are leftover characters, create a shorter item at the end. + if (str.length() % splitLength != 0) + { + ret.push_back(str.substr(splitLength * NumSubstrings)); + } + + + return ret; +} + +void ChatMenu::UpdateChat() { + using namespace UI; + if (chatVert_ != NULL) { + chatVert_->Clear(); + std::vector chatLog = getChatLog(); + for (auto i : chatLog) { + if (i.length() > 30) { + //split long text + std::vector splitted = Split(i, 32); + for (auto j : splitted) { + TextView *v = chatVert_->Add(new TextView(j, FLAG_DYNAMIC_ASCII, false, new LayoutParams(PopupWidth(), WRAP_CONTENT))); + uint32_t color = 0xFFFFFF; + v->SetTextColor(0xFF000000 | color); + } + } + else { + TextView *v = chatVert_->Add(new TextView(i, FLAG_DYNAMIC_ASCII, false, new LayoutParams(PopupWidth(), WRAP_CONTENT))); + uint32_t color = 0xFFFFFF; + v->SetTextColor(0xFF000000 | color); + } + } + scroll_->ScrollToBottom(); + } +} + +bool ChatMenu::touch(const TouchInput &touch) { + if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) { + return UIDialogScreen::touch(touch); + } + + if (!box_->GetBounds().Contains(touch.x, touch.y)) + screenManager()->finishDialog(this, DR_BACK); + + return UIDialogScreen::touch(touch); +} \ No newline at end of file diff --git a/UI/ChatScreen.h b/UI/ChatScreen.h new file mode 100644 index 000000000..c9c72c47a --- /dev/null +++ b/UI/ChatScreen.h @@ -0,0 +1,21 @@ +#pragma once +#include "file/file_util.h" +#include "ui/ui_screen.h" + +class ChatMenu : public PopupScreen { +public: + ChatMenu() : PopupScreen("Chat") {} + void CreatePopupContents(UI::ViewGroup *parent) override; + void CreateViews() override; + void dialogFinished(const Screen *dialog, DialogResult result) override; + bool touch(const TouchInput &touch) override; + void UpdateChat(); +private: + UI::EventReturn OnSubmit(UI::EventParams &e); + UI::TextEdit *chatEdit_; + UI::ScrollView *scroll_; + UI::LinearLayout *chatVert_; + UI::ViewGroup *box_; + UI::Button *defaultButton_; + bool toBottom_; +}; \ No newline at end of file diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 0e496cf64..f7b65203e 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -54,6 +54,7 @@ #include "Core/SaveState.h" #include "Core/MIPS/MIPS.h" #include "Core/HLE/__sceAudio.h" +#include "Core/HLE/proAdhoc.h" #include "UI/ui_atlas.h" #include "UI/BackgroundAudio.h" @@ -70,6 +71,7 @@ #include "UI/GameSettingsScreen.h" #include "UI/InstallZipScreen.h" #include "UI/ProfilerDraw.h" +#include "UI/ChatScreen.h" #if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) #include "Windows/MainWindow.h" @@ -776,6 +778,8 @@ void EmuScreen::CreateViews() { if (g_Config.bShowDeveloperMenu) { root_->Add(new Button("DevMenu"))->OnClick.Handle(this, &EmuScreen::OnDevTools); } + // TODO add options in networking menu checkbox enable chat + root_->Add(new Button("Chat", new AnchorLayoutParams(50, NONE, NONE, 50, true)))->OnClick.Handle(this, &EmuScreen::OnChat); saveStatePreview_ = new AsyncImageFileView("", IS_FIXED, nullptr, new AnchorLayoutParams(bounds.centerX(), 100, NONE, NONE, true)); saveStatePreview_->SetFixedSize(160, 90); saveStatePreview_->SetColor(0x90FFFFFF); @@ -794,7 +798,16 @@ UI::EventReturn EmuScreen::OnDevTools(UI::EventParams ¶ms) { return UI::EVENT_DONE; } +UI::EventReturn EmuScreen::OnChat(UI::EventParams ¶ms) { + releaseButtons(); + ChatMenu* ch = new ChatMenu(); + setChatPointer(ch); + screenManager()->push(ch); + return UI::EVENT_DONE; +} + void EmuScreen::update() { + if (bootPending_) bootGame(gamePath_); diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 3f103513b..2057f6835 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -52,6 +52,7 @@ public: protected: void CreateViews() override; UI::EventReturn OnDevTools(UI::EventParams ¶ms); + UI::EventReturn OnChat(UI::EventParams ¶ms); private: void bootGame(const std::string &filename); diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index 06f979c86..2438e316f 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -20,6 +20,7 @@ + @@ -51,6 +52,7 @@ + diff --git a/UI/UI.vcxproj.filters b/UI/UI.vcxproj.filters index 8332d1176..ed59a4c61 100644 --- a/UI/UI.vcxproj.filters +++ b/UI/UI.vcxproj.filters @@ -70,6 +70,9 @@ Screens + + Screens + @@ -141,6 +144,9 @@ Screens + + Screens +