From 452ebe4c4a0199fd07848a27f176723d3acf5704 Mon Sep 17 00:00:00 2001 From: David Athay Date: Tue, 25 Jun 2024 23:05:31 +0000 Subject: Added online player list to Social window The online list refreshes every 18 seconds, which matches ManaVerse behavior. It's not ideal, but to improve this would mean diving into TMWA. The client version was bumped to 8 to get a SMSG_ONLINE_LIST reply. Further changes needed related to the client version are tracked by #71. This also changes the TabbedArea to take into account the frame size for its tab widgets, to make sure those frames are not clipped by the TabbedArea widget (as happened in the Social window). The horizontal scroll bar is now disabled in all social tabs, with the vertical one appearing only when necessary. Closes #61 --- src/gui/socialwindow.cpp | 91 +++++++++++++++++++++++++++++++++++++-- src/gui/socialwindow.h | 10 +++++ src/gui/widgets/avatarlistbox.cpp | 16 +------ src/gui/widgets/tabbedarea.cpp | 11 +++-- src/net/chathandler.h | 2 + src/net/manaserv/chathandler.h | 2 + src/net/tmwa/chathandler.cpp | 34 +++++++++++++++ src/net/tmwa/chathandler.h | 2 + src/net/tmwa/loginhandler.cpp | 2 +- 9 files changed, 146 insertions(+), 24 deletions(-) diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp index 9ba64e9f..76235306 100644 --- a/src/gui/socialwindow.cpp +++ b/src/gui/socialwindow.cpp @@ -20,6 +20,7 @@ #include "gui/socialwindow.h" +#include "client.h" #include "event.h" #include "guild.h" #include "localplayer.h" @@ -40,6 +41,7 @@ #include "gui/widgets/tabbedarea.h" #include "net/net.h" +#include "net/chathandler.h" #include "net/guildhandler.h" #include "net/partyhandler.h" @@ -98,8 +100,8 @@ public: mList = std::make_unique(guild); mScroll = std::make_unique(mList.get()); - mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_AUTO); - mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS); + mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); + mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_AUTO); } void action(const gcn::ActionEvent &event) override @@ -173,7 +175,7 @@ public: mList = std::make_unique(party); mScroll = std::make_unique(mList.get()); - mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_AUTO); + mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_AUTO); } @@ -231,6 +233,64 @@ private: Party *mParty; }; +class PlayerList : public AvatarListModel +{ +public: + void setPlayers(const std::vector &players) + { + delete_all(mPlayers); + mPlayers = players; + } + + /** + * Returns the number of players in the list. + */ + int getNumberOfElements() override + { + return mPlayers.size(); + } + + Avatar *getAvatarAt(int index) override + { + return mPlayers[index]; + } + +private: + std::vector mPlayers; +}; + +class PlayerListTab : public SocialTab +{ +public: + PlayerListTab() + { + mPlayerList = new PlayerList; + + mList = std::make_unique(mPlayerList); + mScroll = std::make_unique(mList.get()); + + mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); + mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_AUTO); + } + + ~PlayerListTab() + { + delete mPlayerList; + } + + void setPlayers(const std::vector &players) + { + mPlayerList->setPlayers(players); + } + +protected: + void invite() override {} + void leave() override {} + +private: + PlayerList *mPlayerList; +}; + /*class BuddyTab : public SocialTab { // TODO? @@ -314,7 +374,12 @@ SocialWindow::SocialWindow() : widgetResized(nullptr); - mCreatePopup = new CreatePopup(); + mCreatePopup = new CreatePopup; + + mPlayerListTab = new PlayerListTab; + mPlayerListTab->setCaption(strprintf(_("Online (%zu)"), 0ul)); + + mTabs->addTab(mPlayerListTab, mPlayerListTab->mScroll.get()); if (local_player->getParty()) { @@ -345,6 +410,7 @@ SocialWindow::~SocialWindow() mPartyInviter.clear(); } delete mCreatePopup; + delete mPlayerListTab; } bool SocialWindow::addTab(Guild *guild) @@ -605,6 +671,23 @@ void SocialWindow::showPartyCreate() mPartyCreateDialog->addActionListener(this); } +void SocialWindow::setPlayersOnline(const std::vector &players) +{ + mPlayerListTab->setPlayers(players); + mPlayerListTab->setCaption(strprintf(_("Online (%zu)"), players.size())); +} + +void SocialWindow::logic() +{ + if (mLastOnlineListUpdate == 0 || get_elapsed_time(mLastOnlineListUpdate) >= 18000) + { + Net::getChatHandler()->requestOnlineList(); + mLastOnlineListUpdate = tick_time; + } + + Window::logic(); +} + void SocialWindow::updateButtons() { bool hasTabs = mTabs->getNumberOfTabs() > 0; diff --git a/src/gui/socialwindow.h b/src/gui/socialwindow.h index 8575f3b2..b6865fb2 100644 --- a/src/gui/socialwindow.h +++ b/src/gui/socialwindow.h @@ -28,12 +28,15 @@ #include #include +#include +class Avatar; class Button; class ConfirmDialog; class CreatePopup; class Guild; class Party; +class PlayerListTab; class SocialTab; class Tab; class TabbedArea; @@ -74,12 +77,17 @@ public: void showPartyCreate(); + void setPlayersOnline(const std::vector &players); + + void logic() override; + protected: friend class SocialTab; void updateButtons(); int mGuildInvited = 0; + int mLastOnlineListUpdate = 0; ConfirmDialog *mGuildAcceptDialog = nullptr; TextDialog *mGuildCreateDialog = nullptr; @@ -92,6 +100,8 @@ protected: CreatePopup *mCreatePopup; + PlayerListTab *mPlayerListTab; + Button *mCreateButton; Button *mInviteButton; Button *mLeaveButton; diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp index 6fd0fcfb..ec3327b2 100644 --- a/src/gui/widgets/avatarlistbox.cpp +++ b/src/gui/widgets/avatarlistbox.cpp @@ -83,9 +83,6 @@ void AvatarListBox::draw(gcn::Graphics *gcnGraphics) graphics->fillRectangle(gcn::Rectangle(0, fontHeight * mSelected, getWidth(), fontHeight)); - int newWidth = 0; - int width = 0; - // Draw the list elements graphics->setColor(Theme::getThemeColor(Theme::TEXT)); for (int i = 0, y = 0; @@ -116,27 +113,16 @@ void AvatarListBox::draw(gcn::Graphics *gcnGraphics) // Draw Name graphics->drawText(text, 15, y); - width = graphics->getFont()->getWidth(text) + 17; // Extra right padding - - if (width > newWidth) - { - newWidth = width; - } - if (a->getDisplayBold()) graphics->setFont(getFont()); } - - setWidth(newWidth); } void AvatarListBox::mousePressed(gcn::MouseEvent &event) { if (event.getButton() == gcn::MouseEvent::LEFT) { - int y = event.getY(); - setSelected(y / getFont()->getHeight()); - distributeActionEvent(); + ListBox::mousePressed(event); } // TODO: Add support for context menu else if (event.getButton() == gcn::MouseEvent::RIGHT) diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp index 772a8e22..af0c11cb 100644 --- a/src/gui/widgets/tabbedarea.cpp +++ b/src/gui/widgets/tabbedarea.cpp @@ -87,8 +87,10 @@ void TabbedArea::addTab(gcn::Tab* tab, gcn::Widget* widget) { gcn::TabbedArea::addTab(tab, widget); - widget->setSize(mWidgetContainer->getWidth(), - mWidgetContainer->getHeight()); + int frameSize = widget->getFrameSize(); + widget->setPosition(frameSize, frameSize); + widget->setSize(mWidgetContainer->getWidth() - frameSize * 2, + mWidgetContainer->getHeight() - frameSize * 2); updateTabsWidth(); updateArrowEnableState(); @@ -177,8 +179,9 @@ void TabbedArea::widgetResized(const gcn::Event &event) if (gcn::Widget *w = getCurrentWidget()) { - w->setSize(mWidgetContainer->getWidth(), - mWidgetContainer->getHeight()); + int frameSize = w->getFrameSize(); + w->setSize(mWidgetContainer->getWidth() - frameSize * 2, + mWidgetContainer->getHeight() - frameSize * 2); } // Check whether there is room to show more tabs now. diff --git a/src/net/chathandler.h b/src/net/chathandler.h index c324c2d8..382ac39a 100644 --- a/src/net/chathandler.h +++ b/src/net/chathandler.h @@ -58,6 +58,8 @@ class ChatHandler virtual void who() = 0; virtual bool whoSupported() const = 0; + + virtual void requestOnlineList() = 0; }; } diff --git a/src/net/manaserv/chathandler.h b/src/net/manaserv/chathandler.h index c4dc6861..f17883ae 100644 --- a/src/net/manaserv/chathandler.h +++ b/src/net/manaserv/chathandler.h @@ -72,6 +72,8 @@ class ChatHandler final : public MessageHandler, public Net::ChatHandler bool whoSupported() const override { return true; } + void requestOnlineList() override {} + private: /** * Handle chat messages sent from the game server. diff --git a/src/net/tmwa/chathandler.cpp b/src/net/tmwa/chathandler.cpp index a1e2d375..5d9a0e21 100644 --- a/src/net/tmwa/chathandler.cpp +++ b/src/net/tmwa/chathandler.cpp @@ -22,11 +22,14 @@ #include "net/tmwa/chathandler.h" #include "actorspritemanager.h" +#include "avatar.h" #include "being.h" #include "event.h" #include "localplayer.h" #include "playerrelations.h" +#include "gui/socialwindow.h" + #include "net/tmwa/loginhandler.h" #include "net/tmwa/messagein.h" #include "net/tmwa/messageout.h" @@ -50,6 +53,7 @@ ChatHandler::ChatHandler() SMSG_WHISPER_RESPONSE, SMSG_GM_CHAT, SMSG_SCRIPT_MESSAGE, + SMSG_ONLINE_LIST, 0 }; handledMessages = _messages; @@ -252,6 +256,31 @@ void ChatHandler::handleMessage(MessageIn &msg) SERVER_NOTICE(msg.readString(chatMsgLength)) break; } + + case SMSG_ONLINE_LIST: + { + int length = msg.readInt16(); + int count = (length - 4) / 31; + std::vector players; + + for (int i = 0; i < count; i++) + { + msg.readInt32(); // account id + std::string nick = msg.readString(24); + msg.readInt8(); // level + msg.readInt8(); // gm level + msg.readInt8(); // gender + + Avatar *avatar = new Avatar(nick); + avatar->setOnline(true); + players.push_back(avatar); + } + + socialWindow->setPlayersOnline(players); + + break; + } + } } @@ -332,4 +361,9 @@ void ChatHandler::kickUser(int channelId, const std::string &name) SERVER_NOTICE(_("Channels are not supported!")) } +void ChatHandler::requestOnlineList() +{ + MessageOut outMsg(CMSG_ONLINE_LIST); +} + } // namespace TmwAthena diff --git a/src/net/tmwa/chathandler.h b/src/net/tmwa/chathandler.h index 9f838b2c..d545b221 100644 --- a/src/net/tmwa/chathandler.h +++ b/src/net/tmwa/chathandler.h @@ -66,6 +66,8 @@ class ChatHandler final : public MessageHandler, public Net::ChatHandler bool whoSupported() const override { return false; } + void requestOnlineList() override; + private: std::queue mSentWhispers; }; diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp index 8ee5e102..24bc9ab2 100644 --- a/src/net/tmwa/loginhandler.cpp +++ b/src/net/tmwa/loginhandler.cpp @@ -321,7 +321,7 @@ void LoginHandler::sendLoginRegister(const std::string &username, const std::string &password) { MessageOut outMsg(CMSG_LOGIN_REGISTER); - outMsg.writeInt32(6); // client version + outMsg.writeInt32(8); // client version outMsg.writeString(username, 24); outMsg.writeString(password, 24); -- cgit v1.2.3-70-g09d2