From 4a5b6d43d0d931c27903dae552fde46b766ec336 Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Mon, 10 Apr 2023 15:15:12 +0200 Subject: [PATCH 1/4] feat: added bots column on server browser --- data/ui_scripts/server_browser/__init__.lua | 371 ++++++++++++++++++ .../server_browser_button/__init__.lua | 3 - src/client/component/server_list.cpp | 18 +- src/client/game/symbols.hpp | 8 +- .../steam/interfaces/matchmaking_servers.cpp | 5 +- 5 files changed, 397 insertions(+), 8 deletions(-) create mode 100644 data/ui_scripts/server_browser/__init__.lua delete mode 100644 data/ui_scripts/server_browser_button/__init__.lua diff --git a/data/ui_scripts/server_browser/__init__.lua b/data/ui_scripts/server_browser/__init__.lua new file mode 100644 index 00000000..d53055de --- /dev/null +++ b/data/ui_scripts/server_browser/__init__.lua @@ -0,0 +1,371 @@ +if Engine.GetCurrentMap() ~= "core_frontend" then + return +end + +function IsServerBrowserEnabled() + return true +end + +DataSources.LobbyServer = { + prepare = function ( controller, list, filter ) + list.numElementsInList = list.vCount + list.controller = controller + list.serverBrowserRootModel = Engine.CreateModel( Engine.GetGlobalModel(), "serverBrowser" ) + local serverListCountModel = Engine.GetModel( list.serverBrowserRootModel, "serverListCount" ) + if serverListCountModel then + list.serverCount = Engine.GetModelValue( serverListCountModel ) + else + list.serverCount = 0 + end + list.servers = {} + local serversModel = Engine.CreateModel( list.serverBrowserRootModel, "servers" ) + for i = 1, list.numElementsInList, 1 do + list.servers[i] = {} + list.servers[i].root = Engine.CreateModel( serversModel, "server_" .. i ) + list.servers[i].model = Engine.CreateModel( list.servers[i].root, "model" ) + end + list.updateModels = function ( controller, list, offset ) + local serverInfo = Engine.SteamServerBrowser_GetServerInfo( offset ) + if serverInfo then + local SetModelValue = function ( model, key, value ) + local model = Engine.CreateModel( model, key ) + if model then + Engine.SetModelValue( model, value ) + end + end + + local elementIndex = offset % list.numElementsInList + 1 + local serverModel = list.servers[elementIndex].model + SetModelValue( serverModel, "serverIndex", serverInfo.serverIndex ) + SetModelValue( serverModel, "connectAddr", serverInfo.connectAddr ) + SetModelValue( serverModel, "ping", serverInfo.ping ) + SetModelValue( serverModel, "modName", serverInfo.modName ) + SetModelValue( serverModel, "mapName", serverInfo.map ) + SetModelValue( serverModel, "desc", serverInfo.desc ) + -- Changed the client count to be the actual player count + local clientCount = serverInfo.playerCount - serverInfo.botCount + SetModelValue( serverModel, "clientCount", clientCount ) + SetModelValue( serverModel, "maxClients", serverInfo.maxPlayers ) + SetModelValue( serverModel, "passwordProtected", serverInfo.password ) + SetModelValue( serverModel, "secure", serverInfo.secure ) + SetModelValue( serverModel, "name", serverInfo.name ) + SetModelValue( serverModel, "gameType", serverInfo.gametype ) + SetModelValue( serverModel, "dedicated", serverInfo.dedicated ) + SetModelValue( serverModel, "ranked", serverInfo.ranked ) + SetModelValue( serverModel, "hardcore", serverInfo.hardcore ) + -- Added the bot count + SetModelValue( serverModel, "botCount", serverInfo.botCount ) + return serverModel + else + return nil + end + end + + if list.serverListUpdateSubscription then + list:removeSubscription( list.serverListUpdateSubscription ) + end + local serverListUpdateModel = Engine.CreateModel( list.serverBrowserRootModel, "serverListCount" ) + list.serverListUpdateSubscription = list:subscribeToModel( serverListUpdateModel, function ( model ) + list:updateDataSource( false, false ) + end, false ) + if list.serverListSortTypeSubscription then + list:removeSubscription( list.serverListSortTypeSubscription ) + end + local serverListSortTypeModel = Engine.CreateModel( list.serverBrowserRootModel, "serverListSortType" ) + list.serverListSortTypeSubscription = list:subscribeToModel( serverListSortTypeModel, function ( model ) + list:updateDataSource( false, false ) + end, false ) + end, + getCount = function ( list ) + return list.serverCount + end, + getItem = function ( controller, list, index ) + local offset = index - 1 + return list.updateModels( controller, list, offset ) + end, + cleanup = function ( list ) + if list.serverBrowserRootModel then + Engine.UnsubscribeAndFreeModel( list.serverBrowserRootModel ) + list.serverBrowserRootModel = nil + end + end +} + +CoD.ServerBrowserRowInternal.new = function ( menu, controller ) + local self = LUI.UIHorizontalList.new( { + left = 0, + top = 0, + right = 0, + bottom = 0, + leftAnchor = true, + topAnchor = true, + rightAnchor = true, + bottomAnchor = true, + spacing = 2 + } ) + self:setAlignment( LUI.Alignment.Left ) + if PreLoadFunc then + PreLoadFunc( self, controller ) + end + self:setUseStencil( false ) + self:setClass( CoD.ServerBrowserRowInternal ) + self.id = "ServerBrowserRowInternal" + self.soundSet = "default" + self:setLeftRight( true, false, 0, 700 ) + self:setTopBottom( true, false, 0, 22 ) + self:makeFocusable() + self.onlyChildrenFocusable = true + self.anyChildUsesUpdateState = true + + local passwordFlag = CoD.ServerBrowserFlag.new( menu, controller ) + passwordFlag:setLeftRight( true, false, 0, 28 ) + passwordFlag:setTopBottom( true, true, 0, 0 ) + passwordFlag.icon:setImage( RegisterImage( "uie_t7_icon_serverbrowser_protected" ) ) + passwordFlag:linkToElementModel( self, nil, false, function ( model ) + passwordFlag:setModel( model, controller ) + end ) + passwordFlag:mergeStateConditions( { + { + stateName = "FlagOn", + condition = function ( menu, element, event ) + return IsSelfModelValueTrue( element, controller, "passwordProtected" ) + end + } + } ) + passwordFlag:linkToElementModel( passwordFlag, "passwordProtected", true, function ( model ) + menu:updateElementState( passwordFlag, { + name = "model_validation", + menu = menu, + modelValue = Engine.GetModelValue( model ), + modelName = "passwordProtected" + } ) + end ) + self:addElement( passwordFlag ) + self.passwordFlag = passwordFlag + + local dedicatedFlag = CoD.ServerBrowserFlag.new( menu, controller ) + dedicatedFlag:setLeftRight( true, false, 30, 58 ) + dedicatedFlag:setTopBottom( true, true, 0, 0 ) + dedicatedFlag.icon:setImage( RegisterImage( "uie_t7_icon_serverbrowser_dedicated" ) ) + dedicatedFlag:linkToElementModel( self, nil, false, function ( model ) + dedicatedFlag:setModel( model, controller ) + end ) + dedicatedFlag:mergeStateConditions( { + { + stateName = "FlagOn", + condition = function ( menu, element, event ) + return IsSelfModelValueTrue( element, controller, "dedicated" ) + end + } + } ) + dedicatedFlag:linkToElementModel( dedicatedFlag, "dedicated", true, function ( model ) + menu:updateElementState( dedicatedFlag, { + name = "model_validation", + menu = menu, + modelValue = Engine.GetModelValue( model ), + modelName = "dedicated" + } ) + end ) + self:addElement( dedicatedFlag ) + self.dedicatedFlag = dedicatedFlag + + local rankedFlag = CoD.ServerBrowserFlag.new( menu, controller ) + rankedFlag:setLeftRight( true, false, 60, 88 ) + rankedFlag:setTopBottom( true, true, 0, 0 ) + rankedFlag.icon:setImage( RegisterImage( "uie_t7_icon_serverbrowser_ranked" ) ) + rankedFlag:linkToElementModel( self, nil, false, function ( model ) + rankedFlag:setModel( model, controller ) + end ) + rankedFlag:mergeStateConditions( { + { + stateName = "FlagOn", + condition = function ( menu, element, event ) + return IsSelfModelValueTrue( element, controller, "ranked" ) + end + } + } ) + rankedFlag:linkToElementModel( rankedFlag, "ranked", true, function ( model ) + menu:updateElementState( rankedFlag, { + name = "model_validation", + menu = menu, + modelValue = Engine.GetModelValue( model ), + modelName = "ranked" + } ) + end ) + self:addElement( rankedFlag ) + self.rankedFlag = rankedFlag + + local name = CoD.horizontalScrollingTextBox_18pt.new( menu, controller ) + name:setLeftRight( true, false, 90, 330 ) + name:setTopBottom( true, false, 2, 20 ) + name.textBox:setTTF( "fonts/default.ttf" ) + name.textBox:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) + name:linkToElementModel( self, "name", true, function ( model ) + local _name = Engine.GetModelValue( model ) + if _name then + name.textBox:setText( Engine.Localize( _name ) ) + end + end ) + self:addElement( name ) + self.name = name + + local spacer = LUI.UIFrame.new( menu, controller, 0, 0, false ) + spacer:setLeftRight( true, false, 332, 339 ) + spacer:setTopBottom( true, false, 0, 22 ) + spacer:setAlpha( 0 ) + self:addElement( spacer ) + self.spacer = spacer + + local map = CoD.horizontalScrollingTextBox_18pt.new( menu, controller ) + map:setLeftRight( true, false, 341, 446 ) + map:setTopBottom( true, false, 2, 20 ) + map.textBox:setTTF( "fonts/default.ttf" ) + map.textBox:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) + map:linkToElementModel( self, "mapName", true, function ( model ) + local mapName = Engine.GetModelValue( model ) + if mapName then + map.textBox:setText( MapNameToLocalizedMapName( mapName ) ) + end + end ) + self:addElement( map ) + self.map = map + + local hardcoreFlag = CoD.ServerBrowserFlag.new( menu, controller ) + hardcoreFlag:setLeftRight( true, false, 448, 470 ) + hardcoreFlag:setTopBottom( true, true, 0, 0 ) + hardcoreFlag.icon:setImage( RegisterImage( "uie_t7_icon_serverbrowser_skull" ) ) + hardcoreFlag:linkToElementModel( self, nil, false, function ( model ) + hardcoreFlag:setModel( model, controller ) + end ) + hardcoreFlag:mergeStateConditions( { + { + stateName = "FlagOn", + condition = function ( menu, element, event ) + return IsSelfModelValueTrue( element, controller, "hardcore" ) + end + } + } ) + hardcoreFlag:linkToElementModel( hardcoreFlag, "hardcore", true, function ( model ) + menu:updateElementState( hardcoreFlag, { + name = "model_validation", + menu = menu, + modelValue = Engine.GetModelValue( model ), + modelName = "hardcore" + } ) + end ) + self:addElement( hardcoreFlag ) + self.hardcoreFlag = hardcoreFlag + + local gametype = LUI.UIText.new() + gametype:setLeftRight( true, false, 472, 576 ) + gametype:setTopBottom( true, false, 2, 20 ) + gametype:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) + gametype:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) + gametype:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) + gametype:linkToElementModel( self, "gameType", true, function ( model ) + local gameType = Engine.GetModelValue( model ) + if gameType then + gametype:setText( Engine.Localize( GetGameTypeDisplayString( gameType ) ) ) + end + end ) + self:addElement( gametype ) + self.gametype = gametype + + local playerCount = LUI.UIText.new() + playerCount:setLeftRight( true, false, 593, 613 ) + playerCount:setTopBottom( true, false, 2, 20 ) + playerCount:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) + playerCount:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_RIGHT ) + playerCount:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) + playerCount:linkToElementModel( self, "clientCount", true, function ( model ) + local clientCount = Engine.GetModelValue( model ) + if clientCount then + playerCount:setText( Engine.Localize( clientCount ) ) + end + end ) + self:addElement( playerCount ) + self.playerCount = playerCount + + local slash = LUI.UIText.new() + slash:setLeftRight( true, false, 615, 624 ) + slash:setTopBottom( true, false, 2, 20 ) + slash:setText( Engine.Localize( "/" ) ) + slash:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) + slash:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) + slash:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) + self:addElement( slash ) + self.slash = slash + + local maxPlayers = LUI.UIText.new() + maxPlayers:setLeftRight( true, false, 626, 645 ) + maxPlayers:setTopBottom( true, false, 2, 20 ) + maxPlayers:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) + maxPlayers:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) + maxPlayers:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) + maxPlayers:linkToElementModel( self, "maxClients", true, function ( model ) + local maxClients = Engine.GetModelValue( model ) + if maxClients then + maxPlayers:setText( Engine.Localize( maxClients ) ) + end + end ) + self:addElement( maxPlayers ) + self.maxPlayers = maxPlayers + + local botCount = LUI.UIText.new() + botCount:setLeftRight( true, false, 637, 659 ) + botCount:setTopBottom( true, false, 2, 20 ) + botCount:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) + botCount:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) + botCount:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) + botCount:linkToElementModel( self, "botCount", true, function ( model ) + local _botCount = Engine.GetModelValue( model ) + if _botCount then + botCount:setText( "[".. Engine.Localize( _botCount ) .."]" ) + end + end ) + self:addElement( botCount ) + self.botCount = botCount + + local ping = LUI.UIText.new() + ping:setLeftRight( true, false, 661, 699.37 ) + ping:setTopBottom( true, false, 2, 20 ) + ping:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) + ping:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_CENTER ) + ping:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) + ping:linkToElementModel( self, "ping", true, function ( model ) + local _ping = Engine.GetModelValue( model ) + if _ping then + ping:setText( Engine.Localize( _ping ) ) + end + end ) + self:addElement( ping ) + self.ping = ping + + spacer.id = "spacer" + self:registerEventHandler( "gain_focus", function ( self, event ) + if self.m_focusable and self.spacer:processEvent( event ) then + return true + else + return LUI.UIElement.gainFocus( self, event ) + end + end ) + LUI.OverrideFunction_CallOriginalSecond( self, "close", function ( element ) + element.passwordFlag:close() + element.dedicatedFlag:close() + element.rankedFlag:close() + element.name:close() + element.map:close() + element.hardcoreFlag:close() + element.gametype:close() + element.playerCount:close() + element.maxPlayers:close() + element.ping:close() + end ) + + if PostLoadFunc then + PostLoadFunc( self, controller, menu ) + end + + return self +end + diff --git a/data/ui_scripts/server_browser_button/__init__.lua b/data/ui_scripts/server_browser_button/__init__.lua deleted file mode 100644 index affb1588..00000000 --- a/data/ui_scripts/server_browser_button/__init__.lua +++ /dev/null @@ -1,3 +0,0 @@ -function IsServerBrowserEnabled() - return true -end \ No newline at end of file diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index 7bcff98e..ab0d291f 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "network.hpp" #include "scheduler.hpp" @@ -14,6 +15,8 @@ namespace server_list { namespace { + utils::hook::detour lua_gameitem_to_table_hook; + struct state { game::netadr_t address{}; @@ -72,6 +75,17 @@ namespace server_list } callback(true, result); + } + + void lua_gameitem_to_table_stub(game::hks::lua_State* state, __int64 gameItem, int index) + { + lua_gameitem_to_table_hook.invoke(state, gameItem, index); + + if (state) + { + auto botCount = atoi(game::Info_ValueForKey(gameItem + 276, "bots")); + game::Lua_SetTableInt("botCount", botCount, state); + } } } @@ -131,7 +145,9 @@ namespace server_list s.callback(false, {}); s.callback = {}; }); - }, scheduler::async, 200ms); + }, scheduler::async, 200ms); + + lua_gameitem_to_table_hook.create(0x141F1FD10_g, lua_gameitem_to_table_stub); } void pre_destroy() override diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index f754090f..0fe15b80 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -72,7 +72,10 @@ namespace game WEAK symbol DB_ReleaseXAssets{0x1414247C0}; // Live - WEAK symbol Live_GetConnectivityInformation{0x141E0C380}; + WEAK symbol Live_GetConnectivityInformation{0x141E0C380}; + + // Info + WEAK symbol Info_ValueForKey{ 0x1422E87B0 }; // MSG WEAK symbol MSG_ReadByte{0x142155450, 0x14050D1B0}; @@ -141,7 +144,8 @@ namespace game WEAK symbol UI_CoD_GetRootNameForController{0x141F28940, 0x0}; WEAK symbol Lua_CoD_LoadLuaFile{0x141F11A20, 0x0}; WEAK symbol CG_LUIHUDRestart{0x140F7E970}; - WEAK symbol CL_CheckKeepDrawingConnectScreen{0x1413CCAE0}; + WEAK symbol CL_CheckKeepDrawingConnectScreen{0x1413CCAE0}; + WEAK symbol Lua_SetTableInt{ 0x141F066E0 }; // Scr WEAK symbol Scr_AddInt{0x1412E9870, 0x14016F160}; diff --git a/src/client/steam/interfaces/matchmaking_servers.cpp b/src/client/steam/interfaces/matchmaking_servers.cpp index 8f772b65..13d25e84 100644 --- a/src/client/steam/interfaces/matchmaking_servers.cpp +++ b/src/client/steam/interfaces/matchmaking_servers.cpp @@ -55,10 +55,11 @@ namespace steam const auto mode = game::eModes(std::atoi(playmode.data())); const auto* tags = ::utils::string::va( - R"(\gametype\%s\dedicated\%s\ranked\false\hardcore\false\zombies\%s\modName\\playerCount\%d)", + R"(\gametype\%s\dedicated\%s\ranked\false\hardcore\false\zombies\%s\modName\\playerCount\%d\bots\%d\)", info.get("gametype").data(), info.get("dedicated") == "1" ? "true" : "false", - mode == game::MODE_ZOMBIES ? "true" : "false", server.m_nPlayers); + mode == game::MODE_ZOMBIES ? "true" : "false", + server.m_nPlayers, atoi(info.get("bots").data())); ::utils::string::copy(server.m_szGameTags, tags); server.m_steamID.bits = strtoull(info.get("xuid").data(), nullptr, 16); From d31fe6e8557967de1d95d3feee54af00bd228779 Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Mon, 10 Apr 2023 15:57:46 +0200 Subject: [PATCH 2/4] fix: improved lua formatting --- data/ui_scripts/server_browser/__init__.lua | 455 ++++++++++---------- 1 file changed, 227 insertions(+), 228 deletions(-) diff --git a/data/ui_scripts/server_browser/__init__.lua b/data/ui_scripts/server_browser/__init__.lua index d53055de..c29af165 100644 --- a/data/ui_scripts/server_browser/__init__.lua +++ b/data/ui_scripts/server_browser/__init__.lua @@ -7,92 +7,92 @@ function IsServerBrowserEnabled() end DataSources.LobbyServer = { - prepare = function ( controller, list, filter ) + prepare = function(controller, list, filter) list.numElementsInList = list.vCount list.controller = controller - list.serverBrowserRootModel = Engine.CreateModel( Engine.GetGlobalModel(), "serverBrowser" ) - local serverListCountModel = Engine.GetModel( list.serverBrowserRootModel, "serverListCount" ) + list.serverBrowserRootModel = Engine.CreateModel(Engine.GetGlobalModel(), "serverBrowser") + local serverListCountModel = Engine.GetModel(list.serverBrowserRootModel, "serverListCount") if serverListCountModel then - list.serverCount = Engine.GetModelValue( serverListCountModel ) + list.serverCount = Engine.GetModelValue(serverListCountModel) else list.serverCount = 0 end list.servers = {} - local serversModel = Engine.CreateModel( list.serverBrowserRootModel, "servers" ) + local serversModel = Engine.CreateModel(list.serverBrowserRootModel, "servers") for i = 1, list.numElementsInList, 1 do list.servers[i] = {} - list.servers[i].root = Engine.CreateModel( serversModel, "server_" .. i ) - list.servers[i].model = Engine.CreateModel( list.servers[i].root, "model" ) + list.servers[i].root = Engine.CreateModel(serversModel, "server_" .. i) + list.servers[i].model = Engine.CreateModel(list.servers[i].root, "model") end - list.updateModels = function ( controller, list, offset ) - local serverInfo = Engine.SteamServerBrowser_GetServerInfo( offset ) + list.updateModels = function(controller, list, offset) + local serverInfo = Engine.SteamServerBrowser_GetServerInfo(offset) if serverInfo then - local SetModelValue = function ( model, key, value ) - local model = Engine.CreateModel( model, key ) + local SetModelValue = function(model, key, value) + local model = Engine.CreateModel(model, key) if model then - Engine.SetModelValue( model, value ) + Engine.SetModelValue(model, value) end end - + local elementIndex = offset % list.numElementsInList + 1 local serverModel = list.servers[elementIndex].model - SetModelValue( serverModel, "serverIndex", serverInfo.serverIndex ) - SetModelValue( serverModel, "connectAddr", serverInfo.connectAddr ) - SetModelValue( serverModel, "ping", serverInfo.ping ) - SetModelValue( serverModel, "modName", serverInfo.modName ) - SetModelValue( serverModel, "mapName", serverInfo.map ) - SetModelValue( serverModel, "desc", serverInfo.desc ) + SetModelValue(serverModel, "serverIndex", serverInfo.serverIndex) + SetModelValue(serverModel, "connectAddr", serverInfo.connectAddr) + SetModelValue(serverModel, "ping", serverInfo.ping) + SetModelValue(serverModel, "modName", serverInfo.modName) + SetModelValue(serverModel, "mapName", serverInfo.map) + SetModelValue(serverModel, "desc", serverInfo.desc) -- Changed the client count to be the actual player count local clientCount = serverInfo.playerCount - serverInfo.botCount - SetModelValue( serverModel, "clientCount", clientCount ) - SetModelValue( serverModel, "maxClients", serverInfo.maxPlayers ) - SetModelValue( serverModel, "passwordProtected", serverInfo.password ) - SetModelValue( serverModel, "secure", serverInfo.secure ) - SetModelValue( serverModel, "name", serverInfo.name ) - SetModelValue( serverModel, "gameType", serverInfo.gametype ) - SetModelValue( serverModel, "dedicated", serverInfo.dedicated ) - SetModelValue( serverModel, "ranked", serverInfo.ranked ) - SetModelValue( serverModel, "hardcore", serverInfo.hardcore ) + SetModelValue(serverModel, "clientCount", clientCount) + SetModelValue(serverModel, "maxClients", serverInfo.maxPlayers) + SetModelValue(serverModel, "passwordProtected", serverInfo.password) + SetModelValue(serverModel, "secure", serverInfo.secure) + SetModelValue(serverModel, "name", serverInfo.name) + SetModelValue(serverModel, "gameType", serverInfo.gametype) + SetModelValue(serverModel, "dedicated", serverInfo.dedicated) + SetModelValue(serverModel, "ranked", serverInfo.ranked) + SetModelValue(serverModel, "hardcore", serverInfo.hardcore) -- Added the bot count - SetModelValue( serverModel, "botCount", serverInfo.botCount ) + SetModelValue(serverModel, "botCount", serverInfo.botCount) return serverModel else return nil end end - + if list.serverListUpdateSubscription then - list:removeSubscription( list.serverListUpdateSubscription ) + list:removeSubscription(list.serverListUpdateSubscription) end - local serverListUpdateModel = Engine.CreateModel( list.serverBrowserRootModel, "serverListCount" ) - list.serverListUpdateSubscription = list:subscribeToModel( serverListUpdateModel, function ( model ) - list:updateDataSource( false, false ) - end, false ) + local serverListUpdateModel = Engine.CreateModel(list.serverBrowserRootModel, "serverListCount") + list.serverListUpdateSubscription = list:subscribeToModel(serverListUpdateModel, function(model) + list:updateDataSource(false, false) + end, false) if list.serverListSortTypeSubscription then - list:removeSubscription( list.serverListSortTypeSubscription ) + list:removeSubscription(list.serverListSortTypeSubscription) end - local serverListSortTypeModel = Engine.CreateModel( list.serverBrowserRootModel, "serverListSortType" ) - list.serverListSortTypeSubscription = list:subscribeToModel( serverListSortTypeModel, function ( model ) - list:updateDataSource( false, false ) - end, false ) + local serverListSortTypeModel = Engine.CreateModel(list.serverBrowserRootModel, "serverListSortType") + list.serverListSortTypeSubscription = list:subscribeToModel(serverListSortTypeModel, function(model) + list:updateDataSource(false, false) + end, false) end, - getCount = function ( list ) + getCount = function(list) return list.serverCount end, - getItem = function ( controller, list, index ) + getItem = function(controller, list, index) local offset = index - 1 - return list.updateModels( controller, list, offset ) + return list.updateModels(controller, list, offset) end, - cleanup = function ( list ) + cleanup = function(list) if list.serverBrowserRootModel then - Engine.UnsubscribeAndFreeModel( list.serverBrowserRootModel ) + Engine.UnsubscribeAndFreeModel(list.serverBrowserRootModel) list.serverBrowserRootModel = nil end end } -CoD.ServerBrowserRowInternal.new = function ( menu, controller ) - local self = LUI.UIHorizontalList.new( { +CoD.ServerBrowserRowInternal.new = function(menu, controller) + local self = LUI.UIHorizontalList.new({ left = 0, top = 0, right = 0, @@ -102,254 +102,254 @@ CoD.ServerBrowserRowInternal.new = function ( menu, controller ) rightAnchor = true, bottomAnchor = true, spacing = 2 - } ) - self:setAlignment( LUI.Alignment.Left ) + }) + self:setAlignment(LUI.Alignment.Left) if PreLoadFunc then - PreLoadFunc( self, controller ) + PreLoadFunc(self, controller) end - self:setUseStencil( false ) - self:setClass( CoD.ServerBrowserRowInternal ) + self:setUseStencil(false) + self:setClass(CoD.ServerBrowserRowInternal) self.id = "ServerBrowserRowInternal" self.soundSet = "default" - self:setLeftRight( true, false, 0, 700 ) - self:setTopBottom( true, false, 0, 22 ) + self:setLeftRight(true, false, 0, 700) + self:setTopBottom(true, false, 0, 22) self:makeFocusable() self.onlyChildrenFocusable = true self.anyChildUsesUpdateState = true - - local passwordFlag = CoD.ServerBrowserFlag.new( menu, controller ) - passwordFlag:setLeftRight( true, false, 0, 28 ) - passwordFlag:setTopBottom( true, true, 0, 0 ) - passwordFlag.icon:setImage( RegisterImage( "uie_t7_icon_serverbrowser_protected" ) ) - passwordFlag:linkToElementModel( self, nil, false, function ( model ) - passwordFlag:setModel( model, controller ) - end ) - passwordFlag:mergeStateConditions( { + + local passwordFlag = CoD.ServerBrowserFlag.new(menu, controller) + passwordFlag:setLeftRight(true, false, 0, 28) + passwordFlag:setTopBottom(true, true, 0, 0) + passwordFlag.icon:setImage(RegisterImage("uie_t7_icon_serverbrowser_protected")) + passwordFlag:linkToElementModel(self, nil, false, function(model) + passwordFlag:setModel(model, controller) + end) + passwordFlag:mergeStateConditions({ { stateName = "FlagOn", - condition = function ( menu, element, event ) - return IsSelfModelValueTrue( element, controller, "passwordProtected" ) + condition = function(menu, element, event) + return IsSelfModelValueTrue(element, controller, "passwordProtected") end } - } ) - passwordFlag:linkToElementModel( passwordFlag, "passwordProtected", true, function ( model ) - menu:updateElementState( passwordFlag, { + }) + passwordFlag:linkToElementModel(passwordFlag, "passwordProtected", true, function(model) + menu:updateElementState(passwordFlag, { name = "model_validation", menu = menu, - modelValue = Engine.GetModelValue( model ), + modelValue = Engine.GetModelValue(model), modelName = "passwordProtected" - } ) - end ) - self:addElement( passwordFlag ) + }) + end) + self:addElement(passwordFlag) self.passwordFlag = passwordFlag - - local dedicatedFlag = CoD.ServerBrowserFlag.new( menu, controller ) - dedicatedFlag:setLeftRight( true, false, 30, 58 ) - dedicatedFlag:setTopBottom( true, true, 0, 0 ) - dedicatedFlag.icon:setImage( RegisterImage( "uie_t7_icon_serverbrowser_dedicated" ) ) - dedicatedFlag:linkToElementModel( self, nil, false, function ( model ) - dedicatedFlag:setModel( model, controller ) - end ) - dedicatedFlag:mergeStateConditions( { + + local dedicatedFlag = CoD.ServerBrowserFlag.new(menu, controller) + dedicatedFlag:setLeftRight(true, false, 30, 58) + dedicatedFlag:setTopBottom(true, true, 0, 0) + dedicatedFlag.icon:setImage(RegisterImage("uie_t7_icon_serverbrowser_dedicated")) + dedicatedFlag:linkToElementModel(self, nil, false, function(model) + dedicatedFlag:setModel(model, controller) + end) + dedicatedFlag:mergeStateConditions({ { stateName = "FlagOn", - condition = function ( menu, element, event ) - return IsSelfModelValueTrue( element, controller, "dedicated" ) + condition = function(menu, element, event) + return IsSelfModelValueTrue(element, controller, "dedicated") end } - } ) - dedicatedFlag:linkToElementModel( dedicatedFlag, "dedicated", true, function ( model ) - menu:updateElementState( dedicatedFlag, { + }) + dedicatedFlag:linkToElementModel(dedicatedFlag, "dedicated", true, function(model) + menu:updateElementState(dedicatedFlag, { name = "model_validation", menu = menu, - modelValue = Engine.GetModelValue( model ), + modelValue = Engine.GetModelValue(model), modelName = "dedicated" - } ) - end ) - self:addElement( dedicatedFlag ) + }) + end) + self:addElement(dedicatedFlag) self.dedicatedFlag = dedicatedFlag - - local rankedFlag = CoD.ServerBrowserFlag.new( menu, controller ) - rankedFlag:setLeftRight( true, false, 60, 88 ) - rankedFlag:setTopBottom( true, true, 0, 0 ) - rankedFlag.icon:setImage( RegisterImage( "uie_t7_icon_serverbrowser_ranked" ) ) - rankedFlag:linkToElementModel( self, nil, false, function ( model ) - rankedFlag:setModel( model, controller ) - end ) - rankedFlag:mergeStateConditions( { + + local rankedFlag = CoD.ServerBrowserFlag.new(menu, controller) + rankedFlag:setLeftRight(true, false, 60, 88) + rankedFlag:setTopBottom(true, true, 0, 0) + rankedFlag.icon:setImage(RegisterImage("uie_t7_icon_serverbrowser_ranked")) + rankedFlag:linkToElementModel(self, nil, false, function(model) + rankedFlag:setModel(model, controller) + end) + rankedFlag:mergeStateConditions({ { stateName = "FlagOn", - condition = function ( menu, element, event ) - return IsSelfModelValueTrue( element, controller, "ranked" ) + condition = function(menu, element, event) + return IsSelfModelValueTrue(element, controller, "ranked") end } - } ) - rankedFlag:linkToElementModel( rankedFlag, "ranked", true, function ( model ) - menu:updateElementState( rankedFlag, { + }) + rankedFlag:linkToElementModel(rankedFlag, "ranked", true, function(model) + menu:updateElementState(rankedFlag, { name = "model_validation", menu = menu, - modelValue = Engine.GetModelValue( model ), + modelValue = Engine.GetModelValue(model), modelName = "ranked" - } ) - end ) - self:addElement( rankedFlag ) + }) + end) + self:addElement(rankedFlag) self.rankedFlag = rankedFlag - - local name = CoD.horizontalScrollingTextBox_18pt.new( menu, controller ) - name:setLeftRight( true, false, 90, 330 ) - name:setTopBottom( true, false, 2, 20 ) - name.textBox:setTTF( "fonts/default.ttf" ) - name.textBox:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) - name:linkToElementModel( self, "name", true, function ( model ) - local _name = Engine.GetModelValue( model ) + + local name = CoD.horizontalScrollingTextBox_18pt.new(menu, controller) + name:setLeftRight(true, false, 90, 330) + name:setTopBottom(true, false, 2, 20) + name.textBox:setTTF("fonts/default.ttf") + name.textBox:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT) + name:linkToElementModel(self, "name", true, function(model) + local _name = Engine.GetModelValue(model) if _name then - name.textBox:setText( Engine.Localize( _name ) ) + name.textBox:setText(Engine.Localize(_name)) end - end ) - self:addElement( name ) + end) + self:addElement(name) self.name = name - - local spacer = LUI.UIFrame.new( menu, controller, 0, 0, false ) - spacer:setLeftRight( true, false, 332, 339 ) - spacer:setTopBottom( true, false, 0, 22 ) - spacer:setAlpha( 0 ) - self:addElement( spacer ) + + local spacer = LUI.UIFrame.new(menu, controller, 0, 0, false) + spacer:setLeftRight(true, false, 332, 339) + spacer:setTopBottom(true, false, 0, 22) + spacer:setAlpha(0) + self:addElement(spacer) self.spacer = spacer - - local map = CoD.horizontalScrollingTextBox_18pt.new( menu, controller ) - map:setLeftRight( true, false, 341, 446 ) - map:setTopBottom( true, false, 2, 20 ) - map.textBox:setTTF( "fonts/default.ttf" ) - map.textBox:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) - map:linkToElementModel( self, "mapName", true, function ( model ) - local mapName = Engine.GetModelValue( model ) + + local map = CoD.horizontalScrollingTextBox_18pt.new(menu, controller) + map:setLeftRight(true, false, 341, 446) + map:setTopBottom(true, false, 2, 20) + map.textBox:setTTF("fonts/default.ttf") + map.textBox:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT) + map:linkToElementModel(self, "mapName", true, function(model) + local mapName = Engine.GetModelValue(model) if mapName then - map.textBox:setText( MapNameToLocalizedMapName( mapName ) ) + map.textBox:setText(MapNameToLocalizedMapName(mapName)) end - end ) - self:addElement( map ) + end) + self:addElement(map) self.map = map - - local hardcoreFlag = CoD.ServerBrowserFlag.new( menu, controller ) - hardcoreFlag:setLeftRight( true, false, 448, 470 ) - hardcoreFlag:setTopBottom( true, true, 0, 0 ) - hardcoreFlag.icon:setImage( RegisterImage( "uie_t7_icon_serverbrowser_skull" ) ) - hardcoreFlag:linkToElementModel( self, nil, false, function ( model ) - hardcoreFlag:setModel( model, controller ) - end ) - hardcoreFlag:mergeStateConditions( { + + local hardcoreFlag = CoD.ServerBrowserFlag.new(menu, controller) + hardcoreFlag:setLeftRight(true, false, 448, 470) + hardcoreFlag:setTopBottom(true, true, 0, 0) + hardcoreFlag.icon:setImage(RegisterImage("uie_t7_icon_serverbrowser_skull")) + hardcoreFlag:linkToElementModel(self, nil, false, function(model) + hardcoreFlag:setModel(model, controller) + end) + hardcoreFlag:mergeStateConditions({ { stateName = "FlagOn", - condition = function ( menu, element, event ) - return IsSelfModelValueTrue( element, controller, "hardcore" ) + condition = function(menu, element, event) + return IsSelfModelValueTrue(element, controller, "hardcore") end } - } ) - hardcoreFlag:linkToElementModel( hardcoreFlag, "hardcore", true, function ( model ) - menu:updateElementState( hardcoreFlag, { + }) + hardcoreFlag:linkToElementModel(hardcoreFlag, "hardcore", true, function(model) + menu:updateElementState(hardcoreFlag, { name = "model_validation", menu = menu, - modelValue = Engine.GetModelValue( model ), + modelValue = Engine.GetModelValue(model), modelName = "hardcore" - } ) - end ) - self:addElement( hardcoreFlag ) + }) + end) + self:addElement(hardcoreFlag) self.hardcoreFlag = hardcoreFlag - + local gametype = LUI.UIText.new() - gametype:setLeftRight( true, false, 472, 576 ) - gametype:setTopBottom( true, false, 2, 20 ) - gametype:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) - gametype:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) - gametype:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) - gametype:linkToElementModel( self, "gameType", true, function ( model ) - local gameType = Engine.GetModelValue( model ) + gametype:setLeftRight(true, false, 472, 576) + gametype:setTopBottom(true, false, 2, 20) + gametype:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf") + gametype:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT) + gametype:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP) + gametype:linkToElementModel(self, "gameType", true, function(model) + local gameType = Engine.GetModelValue(model) if gameType then - gametype:setText( Engine.Localize( GetGameTypeDisplayString( gameType ) ) ) + gametype:setText(Engine.Localize(GetGameTypeDisplayString(gameType))) end - end ) - self:addElement( gametype ) + end) + self:addElement(gametype) self.gametype = gametype - + local playerCount = LUI.UIText.new() - playerCount:setLeftRight( true, false, 593, 613 ) - playerCount:setTopBottom( true, false, 2, 20 ) - playerCount:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) - playerCount:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_RIGHT ) - playerCount:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) - playerCount:linkToElementModel( self, "clientCount", true, function ( model ) - local clientCount = Engine.GetModelValue( model ) + playerCount:setLeftRight(true, false, 593, 613) + playerCount:setTopBottom(true, false, 2, 20) + playerCount:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf") + playerCount:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_RIGHT) + playerCount:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP) + playerCount:linkToElementModel(self, "clientCount", true, function(model) + local clientCount = Engine.GetModelValue(model) if clientCount then - playerCount:setText( Engine.Localize( clientCount ) ) + playerCount:setText(Engine.Localize(clientCount)) end - end ) - self:addElement( playerCount ) + end) + self:addElement(playerCount) self.playerCount = playerCount - + local slash = LUI.UIText.new() - slash:setLeftRight( true, false, 615, 624 ) - slash:setTopBottom( true, false, 2, 20 ) - slash:setText( Engine.Localize( "/" ) ) - slash:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) - slash:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) - slash:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) - self:addElement( slash ) + slash:setLeftRight(true, false, 615, 624) + slash:setTopBottom(true, false, 2, 20) + slash:setText(Engine.Localize("/")) + slash:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf") + slash:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT) + slash:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP) + self:addElement(slash) self.slash = slash - + local maxPlayers = LUI.UIText.new() - maxPlayers:setLeftRight( true, false, 626, 645 ) - maxPlayers:setTopBottom( true, false, 2, 20 ) - maxPlayers:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) - maxPlayers:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) - maxPlayers:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) - maxPlayers:linkToElementModel( self, "maxClients", true, function ( model ) - local maxClients = Engine.GetModelValue( model ) + maxPlayers:setLeftRight(true, false, 626, 645) + maxPlayers:setTopBottom(true, false, 2, 20) + maxPlayers:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf") + maxPlayers:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT) + maxPlayers:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP) + maxPlayers:linkToElementModel(self, "maxClients", true, function(model) + local maxClients = Engine.GetModelValue(model) if maxClients then - maxPlayers:setText( Engine.Localize( maxClients ) ) + maxPlayers:setText(Engine.Localize(maxClients)) end - end ) - self:addElement( maxPlayers ) + end) + self:addElement(maxPlayers) self.maxPlayers = maxPlayers - + local botCount = LUI.UIText.new() - botCount:setLeftRight( true, false, 637, 659 ) - botCount:setTopBottom( true, false, 2, 20 ) - botCount:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) - botCount:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_LEFT ) - botCount:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) - botCount:linkToElementModel( self, "botCount", true, function ( model ) - local _botCount = Engine.GetModelValue( model ) + botCount:setLeftRight(true, false, 637, 659) + botCount:setTopBottom(true, false, 2, 20) + botCount:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf") + botCount:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT) + botCount:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP) + botCount:linkToElementModel(self, "botCount", true, function(model) + local _botCount = Engine.GetModelValue(model) if _botCount then - botCount:setText( "[".. Engine.Localize( _botCount ) .."]" ) + botCount:setText("[" .. Engine.Localize(_botCount) .. "]") end - end ) - self:addElement( botCount ) + end) + self:addElement(botCount) self.botCount = botCount - + local ping = LUI.UIText.new() - ping:setLeftRight( true, false, 661, 699.37 ) - ping:setTopBottom( true, false, 2, 20 ) - ping:setTTF( "fonts/RefrigeratorDeluxe-Regular.ttf" ) - ping:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_CENTER ) - ping:setAlignment( Enum.LUIAlignment.LUI_ALIGNMENT_TOP ) - ping:linkToElementModel( self, "ping", true, function ( model ) - local _ping = Engine.GetModelValue( model ) + ping:setLeftRight(true, false, 661, 699.37) + ping:setTopBottom(true, false, 2, 20) + ping:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf") + ping:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_CENTER) + ping:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP) + ping:linkToElementModel(self, "ping", true, function(model) + local _ping = Engine.GetModelValue(model) if _ping then - ping:setText( Engine.Localize( _ping ) ) + ping:setText(Engine.Localize(_ping)) end - end ) - self:addElement( ping ) + end) + self:addElement(ping) self.ping = ping - + spacer.id = "spacer" - self:registerEventHandler( "gain_focus", function ( self, event ) - if self.m_focusable and self.spacer:processEvent( event ) then + self:registerEventHandler("gain_focus", function(self, event) + if self.m_focusable and self.spacer:processEvent(event) then return true else - return LUI.UIElement.gainFocus( self, event ) + return LUI.UIElement.gainFocus(self, event) end - end ) - LUI.OverrideFunction_CallOriginalSecond( self, "close", function ( element ) + end) + LUI.OverrideFunction_CallOriginalSecond(self, "close", function(element) element.passwordFlag:close() element.dedicatedFlag:close() element.rankedFlag:close() @@ -360,12 +360,11 @@ CoD.ServerBrowserRowInternal.new = function ( menu, controller ) element.playerCount:close() element.maxPlayers:close() element.ping:close() - end ) - + end) + if PostLoadFunc then - PostLoadFunc( self, controller, menu ) + PostLoadFunc(self, controller, menu) end - + return self end - From 51582936c4f853adf7e418ea9c29818d69e52ef1 Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Mon, 10 Apr 2023 16:37:32 +0200 Subject: [PATCH 3/4] fix: added serverinfo struct --- src/client/component/server_list.cpp | 10 +++++----- src/client/game/structs.hpp | 26 ++++++++++++++++++++++++++ src/client/game/symbols.hpp | 2 +- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/client/component/server_list.cpp b/src/client/component/server_list.cpp index ab0d291f..7c0ca6ad 100644 --- a/src/client/component/server_list.cpp +++ b/src/client/component/server_list.cpp @@ -15,7 +15,7 @@ namespace server_list { namespace { - utils::hook::detour lua_gameitem_to_table_hook; + utils::hook::detour lua_serverinfo_to_table_hook; struct state { @@ -77,13 +77,13 @@ namespace server_list callback(true, result); } - void lua_gameitem_to_table_stub(game::hks::lua_State* state, __int64 gameItem, int index) + void lua_serverinfo_to_table_stub(game::hks::lua_State* state, game::ServerInfo serverInfo, int index) { - lua_gameitem_to_table_hook.invoke(state, gameItem, index); + lua_serverinfo_to_table_hook.invoke(state, serverInfo, index); if (state) { - auto botCount = atoi(game::Info_ValueForKey(gameItem + 276, "bots")); + auto botCount = atoi(game::Info_ValueForKey(serverInfo.tags, "bots")); game::Lua_SetTableInt("botCount", botCount, state); } } @@ -147,7 +147,7 @@ namespace server_list }); }, scheduler::async, 200ms); - lua_gameitem_to_table_hook.create(0x141F1FD10_g, lua_gameitem_to_table_stub); + lua_serverinfo_to_table_hook.create(0x141F1FD10_g, lua_serverinfo_to_table_stub); } void pre_destroy() override diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index ca9b7904..57d38e2c 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -1032,6 +1032,32 @@ namespace game Agreement debugAgreement; JoinType joinType; JoinResult joinResult; + }; + + struct ServerInfo + { + uint16_t m_usConnectionPort; + uint16_t m_usQueryPort; + uint32_t m_unIP; + int m_nPing; + byte unk[0x22]; + char mapname[32]; + char description[64]; + char gamemode[16]; + char modname[32]; + int playerCount; + int maxPlayers; + int unk2; + int unk3; + int unk4; + bool dedicated; + bool ranked; + bool hardcore; + bool zombies; + char servername[64]; + char tags[128]; + int unk5; + int unk6; }; #ifdef __cplusplus diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 820d68c6..205c0348 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -76,7 +76,7 @@ namespace game WEAK symbol Live_GetConnectivityInformation{0x141E0C380}; // Info - WEAK symbol Info_ValueForKey{ 0x1422E87B0 }; + WEAK symbol Info_ValueForKey{ 0x1422E87B0 }; // MSG WEAK symbol MSG_ReadByte{0x142155450, 0x14050D1B0}; From 3f97e5d4e6b8b6988d3d6e613e60b3eabd85212a Mon Sep 17 00:00:00 2001 From: Jari van der Kaap Date: Mon, 10 Apr 2023 16:46:55 +0200 Subject: [PATCH 4/4] fix: only have bot count on multiplayer servers --- data/ui_scripts/server_browser/__init__.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/data/ui_scripts/server_browser/__init__.lua b/data/ui_scripts/server_browser/__init__.lua index c29af165..493795a4 100644 --- a/data/ui_scripts/server_browser/__init__.lua +++ b/data/ui_scripts/server_browser/__init__.lua @@ -53,6 +53,7 @@ DataSources.LobbyServer = { SetModelValue(serverModel, "dedicated", serverInfo.dedicated) SetModelValue(serverModel, "ranked", serverInfo.ranked) SetModelValue(serverModel, "hardcore", serverInfo.hardcore) + SetModelValue(serverModel, "zombies", serverInfo.zombies) -- Added the bot count SetModelValue(serverModel, "botCount", serverInfo.botCount) return serverModel @@ -323,6 +324,12 @@ CoD.ServerBrowserRowInternal.new = function(menu, controller) botCount:setText("[" .. Engine.Localize(_botCount) .. "]") end end) + botCount:linkToElementModel(self, "zombies", true, function(model) + local zombies = Engine.GetModelValue(model) + if zombies ~= nil then + botCount:setAlpha(zombies and 0 or 1) + end + end) self:addElement(botCount) self.botCount = botCount @@ -359,6 +366,7 @@ CoD.ServerBrowserRowInternal.new = function(menu, controller) element.gametype:close() element.playerCount:close() element.maxPlayers:close() + element.botCount:close() element.ping:close() end)