/* =========================================================================== Copyright (C) 2023-2024 the OpenMoHAA team This file is part of OpenMoHAA source code. OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenMoHAA source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "cl_ui.h" #include "../qcommon/localization.h" class LANGameItem : public UIListCtrlItem { str strings[6]; public: LANGameItem(); LANGameItem( const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping, const str& ipAddress ); int getListItemValue(int which) const override; griditemtype_t getListItemType(int which) const override; str getListItemString(int which) const override; void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override; qboolean IsHeaderEntry() const override; }; Event EV_LANGame_JoinGame ( "joingame", EV_DEFAULT, NULL, NULL, "Join the currently selected server" ); CLASS_DECLARATION(UIListCtrl, UILANGameClass, NULL) { {&EV_UIListBase_ItemSelected, &UILANGameClass::SelectServer}, {&EV_UIListBase_ItemDoubleClicked, &UILANGameClass::JoinServer }, {&EV_LANGame_JoinGame, &UILANGameClass::JoinServer }, {NULL, NULL } }; UILANGameClass::UILANGameClass() { Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked); Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected); AllowActivate(true); setHeaderFont("facfont-20"); m_iLastUpdateTime = 0; m_noservers_mat = uWinMan.RegisterShader("textures/menu/noservers"); // // Added in OPM // m_bVirtual = false; } void UILANGameClass::Draw(void) { if (cls.bNewLocalServerInfo) { SetupServers(); } UIListCtrl::Draw(); if (!getNumItems() && m_noservers_mat) { float x, y, w, h; w = re.GetShaderWidth(m_noservers_mat->GetMaterial()) * m_vVirtualScale[0]; h = re.GetShaderHeight(m_noservers_mat->GetMaterial()) * m_vVirtualScale[1]; UIRect2D frame = getClientFrame(); x = (frame.size.width - w) * 0.5f; y = (frame.size.height - h) * 0.5f; re.DrawStretchPic(x, y, w, h, 0, 0, 1, 1, m_noservers_mat->GetMaterial()); } if (m_iLastUpdateTime && m_iLastUpdateTime < cls.realtime) { Cvar_Set("cl_langamerefreshstatus", "Ready"); m_iLastUpdateTime = 0; } } void UILANGameClass::UpdateUIElement(void) { float width; RemoveAllColumns(); width = getClientFrame().size.width - 16.f; AddColumn(Sys_LV_CL_ConvertString("Server Name"), 0, width * 0.27f, false, false); // was 0.4 AddColumn(Sys_LV_CL_ConvertString("Map"), 1, width * 0.12f, false, false); // was 0.15 AddColumn(Sys_LV_CL_ConvertString("Players"), 2, width * 0.08f, true, true); // was 0.165 AddColumn(Sys_LV_CL_ConvertString("GameType"), 3, width * 0.118f, false, false); // was 0.22 AddColumn(Sys_LV_CL_ConvertString("Ping"), 4, width * 0.052f, true, false); // was 0.065 AddColumn(Sys_LV_CL_ConvertString("IP"), 5, width * 0.36f, false, false); // Added in OPM uWinMan.ActivateControl(this); SetupServers(); } void UILANGameClass::SetupServers(void) { int i; LANGameItem *pItem; const serverInfo_t *pServerInfo; for (i = 1; i <= cls.numlocalservers; i++) { pServerInfo = &cls.localServers[i - 1]; if (i > getNumItems()) { pItem = new LANGameItem(); AddItem(pItem); } else { pItem = static_cast(GetItem(i)); } *pItem = LANGameItem( pServerInfo->hostName, pServerInfo->mapName, va("%02i/%02i", pServerInfo->clients, pServerInfo->maxClients), pServerInfo->gameTypeString, str(pServerInfo->ping), // Added in OPM NET_AdrToStringwPort(pServerInfo->adr) ); } while (cls.numlocalservers < getNumItems()) { DeleteItem(getNumItems()); } cls.bNewLocalServerInfo = false; m_iLastUpdateTime = 0; } void UILANGameClass::SelectServer(Event *ev) { const serverInfo_t& serverInfo = cls.localServers[getCurrentItem() - 1]; static const char info[] = "\xFF\xFF\xFF\xFF\x02getinfo xxx"; Com_Printf("Requesting updated info from server...\n"); Cvar_Set("cl_langamerefreshstatus", "Requesting updated info from server..."); NET_SendPacket(NS_CLIENT, sizeof(info), info, serverInfo.adr); m_iLastUpdateTime = cls.realtime + 3000; } void UILANGameClass::JoinServer(Event *ev) { if (!getCurrentItem()) { return; } const serverInfo_t& serverInfo = cls.localServers[getCurrentItem() - 1]; UI_SetReturnMenuToCurrent(); CL_Connect(NET_AdrToStringwPort(serverInfo.adr), netadrtype_t::NA_UNSPEC); } qboolean UILANGameClass::KeyEvent(int key, unsigned int time) { switch (key) { case K_ENTER: case K_KP_ENTER: JoinServer(NULL); return true; case K_UPARROW: if (getCurrentItem() > 1) { TrySelectItem(getCurrentItem() - 1); SelectServer(NULL); } return false; case K_DOWNARROW: if (getCurrentItem() < getNumItems()) { TrySelectItem(getCurrentItem() + 1); SelectServer(NULL); } return false; } return UIListBase::KeyEvent(key, time); } LANGameItem::LANGameItem() {} LANGameItem::LANGameItem( const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping, const str& ipAddress ) { strings[0] = hostName; strings[1] = mapName; strings[2] = players; strings[3] = gameTypeString; strings[4] = ping; // // Added in OPM // strings[5] = ipAddress; } int LANGameItem::getListItemValue(int which) const { return atoi(strings[which]); } griditemtype_t LANGameItem::getListItemType(int which) const { return griditemtype_t::TYPE_STRING; } str LANGameItem::getListItemString(int which) const { return strings[which]; } void LANGameItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {} qboolean LANGameItem::IsHeaderEntry() const { return qfalse; }