From d0840e6458cc3e3ec29544ecf049c6e77e802c76 Mon Sep 17 00:00:00 2001 From: furo Date: Sat, 26 Oct 2024 18:55:46 +0200 Subject: [PATCH] Add a "connection problems" icon to nameplate --- CMakeLists.txt | 2 + data/license.txt | 3 ++ data/network.png | Bin 0 -> 3967 bytes datasrc/content.py | 7 +++ datasrc/network.py | 2 +- src/engine/server.h | 1 + src/engine/server/server.cpp | 3 ++ src/engine/server/server.h | 1 + src/engine/shared/config_variables.h | 1 + src/game/client/components/menus_settings.cpp | 37 +++++++++++++-- src/game/client/components/nameplates.cpp | 42 ++++++++++++++++-- src/game/client/gameclient.cpp | 2 + src/game/client/gameclient.h | 1 + src/game/server/player.cpp | 8 ++++ 14 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 data/license.txt create mode 100644 data/network.png diff --git a/CMakeLists.txt b/CMakeLists.txt index d07f0f0db..404981649 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1486,6 +1486,7 @@ set(EXPECTED_DATA languages/traditional_chinese.txt languages/turkish.txt languages/ukrainian.txt + license.txt mapres/basic_freeze.png mapres/bg_cloud1.png mapres/bg_cloud2.png @@ -1569,6 +1570,7 @@ set(EXPECTED_DATA menuimages/local_server.png menuimages/play_game.png menuimages/settings.png + network.png particles.png race_flag.png shader/pipeline.frag diff --git a/data/license.txt b/data/license.txt new file mode 100644 index 000000000..2f6b927a7 --- /dev/null +++ b/data/license.txt @@ -0,0 +1,3 @@ +network.png: +Copyright leovilok +CC BY-SA 3.0 license (https://creativecommons.org/licenses/by-sa/3.0/) diff --git a/data/network.png b/data/network.png new file mode 100644 index 0000000000000000000000000000000000000000..6586f9c9fc020b0607ae1eb2309f33e68dabaab4 GIT binary patch literal 3967 zcmV-_4}kEAP)6=y*EjbXQnf~ z$-U>E=Q;1W_nh~<=M8WLSMaljB-#}a38?@k0#E|*18@N724D_6@p2PD2H*w&<3fCI z1kl9%KpL5PMFcVcHv$+pd-m+)mX?;MT`t!LPN(yqjg5_Kv|8;L022UQ6YYwM0U3Z? z0MxQ&%a-={_jmdO(A(Slja)7-1~7-5f7w6|U?u>ntgP(bfq{YUK=L$Re);7!04M-g z(HD>QE+7Xm13>bM6)Psb{`%`LB_<|L40Uo=R@Nl)uY&$;Gz&nJAG>npO3iDpy|yhe zF>yk;3r?Ln)k6Lqh)fm5LmYrS0Mx2gs~&JVou*J`Pou4^?K5Kjw~q3LM;w5B08~Xq zMVZs->}4ZwG#bCm$jG>Z2oUNO852+f$N-Q{%zFla>j7v0BrwTWR#uh`4i0i5e}X|i zEAWP~G7w4ukO^Qc%XwY^@-=JLWYpBu)W*lhtHYgaG#XFj<>mdpySv*1pc8;j*lLd) z5&+kd)}acj-Bu3d52#eC z`GkCCw2218F!}ua{Kb8Jec!T?;);%rj(wwwyxD9%FCh8-4DwT=O*9z9B+qR5$2#kc6pDF-d`7g12E#DYIdW&k|^`h_Z62#99(Oz3pFkBJ4$h&Ev+=$5AdP$rYcklb^tFL|p z&@yPp695<2>x7;c(`G-uprAmx ze*OCE86x=Bu3g)(Wy_YTp`jtcA5>ni*DrLLeDRY9p4aPjGW>9J$RAZ*UA@}t^*RK6 z4ERb)N|uoOBt(mRcCe>?fCzKN5W!}%HIecQqeVXKt4?f7`0&FIUkK&!hy?kdEgvZn z3-9RtumZo|?>CuDUo%=hTTHX( zYXLq0_P)M8ufbsWLW~O8Y_`VI($aP0uou90Vz&IHI7EH`fL*(GeIRsY>~?!|X=&-& zlP6C)B4ze+p6ADrP&1g#W~a~Rb4jIAL1th!o2{{=q~z&HlIM%z;Dj}6);#EPx%!0a z^Re`v4+S|LlT%q)S>|%Ne)w6Euc)Zt6qa(ik)I_7`M$osv-$b?i({F*jE=y3^wCG} z=Ms(8($eyAU0vOla9zab^LZK@8{gMxGz&%r`SSAecx*ix9=wfSmy;C?JF60lzdRPh{!~>YCQmN)!t=2|1@?BkB zhc74c0H6jyz5VvvzvDpu2qOqFCZn;qf;kyV1c1!U%t@h72Mh+ov01ZbZRqRk^8&a4 zpk4G@iU_6vPW*43y(84gMx*h>%$YNv@9F9B0MG+yi%2aagg5|m6bi+>U>;wi(RhL} zc$pgQ%8G?_08~y+&YcYn4ZHjM`!Cq-_Lk$vkN=tRz>D|_te6NKtVqbaJJ`U-Px||X z2-Phj2sK(uAp@DQ#0~Z%fG)BF^9ruu3a;P^E*Hd{Cq^KQ1CYjei#fG2gYpNJ2`Ip`?;M#c||w zFWDB;M;x%z0VGvcR;Jg~)YK{ziqudAPM_hCm23y?+}sKFLqZ@V?dBB9j?&&`g(fra7^thVnRZ8i&J!bP*YRW9=qM%>hXB&9*@WFa5yfs zwYBYi^UXJ_BpP_m75+ z)Y)Q?@960GoI(EQ)$%PZEgz4Dy~NBu-y{_Ip`oEcM%+P6dap$zPve_!zImGwdk|9) z&Fq&9{q)m^Gcq!Y#kh$~CQAfxV*mdAeE=)~21A`2=~+<^ zNoRuv3l{vvXf%ovZ3+N+d3p2#&X{oLMPpj11JK#i)8om_&0W{s-F-}qn<$k^Iww(B zE05N^cvys4vt~Unh6qlllTMiC3wK^L9RnAMAar*)fBrnZY#*}!#|oy>$&?HR!*LTka7iMV&E|8Ajnsmr>EVLm z;Von8nE`-OC=~O)|Ni@bIi1d)EnBwymVAE;GpT6^@ahf$9j2l~*1YT7;M(Z?#&#>+0$nPGY!i+qSiVmGyeP{X8upY3qmvVt2TO!`MAD8sw)i$n*B$F-16XqF@YJ+=nCV-79a-zRbOAf<5I~76M<<7 z9*@VdVZ(+;d5q!n83NoaCV4r4IVzQEK9_9Hd_~x^XU}$z$K%+vY11k~rhtQ^Rt0pe*6?yD34$x5YMdRsy2@;Qa-2NVjq zl!U`w#d2*>un8c;|2(XMI~JHCkVp^>hs!bm;LU9_iTbY+q({jb|+&S8GX7i~2>>lEEg|<2jT9P< zW^P?wT^Tvd2ovO(0RTH+$txN=R(?JG;n=bAtQ|GE`OI_pfK32909033|HtR^iDCs7 zi{;#k6)Sd=!yYEsfR{JUn0a+d+>L=>s;^GCsb+&#OAdKi0h<7E^n>u& zv13R16wC&**?g|JxR?w1M7monU7{%q@;v}x`I1SrWsKu6sTxK&0piF;>M>PSRo5Hhg?s{8Qb+myQyye1du7=a`t2}*YktvS0?_#bl&e;) zx~8_aww5gdlPd`Ms?(=W_Y?ALNs`h5NFHA~b+TqcLJ?c}lO`kbY( zD=SNT_0?Bv6$(YzUuC**;lcr%&DP9zllJ!Z&-3!~p5#Fu}$n?KfQGz}>! zDZcpl_(Zu}u9Qe5{=vaPQ)g#q{mz{`Us}9)@%vV*b%^}zWitozGU9%dzV}A{V^^od zbIuwokw~P|ZWt?hZD-p_vNqTqE=GXqeo6))*|B5Ct;xyB*M+-DdwcumIXO9-2L}gz z0DKQW{P0NtC&OIgCOgfI9C=IvAiwACiK&^BlNNHkW*F15l%)&ir2T#0(H<+AV}#u9 z`;+_ulP6COYc`#ood>j9?IuFL6~Gq&z9%C%7o&Au@~$*5A5OyHqBVa30YGLN1pkZTqA47vwNKl=GDN3~&Ru;BYvml$4Y_ z_0Bu*tV~Z&FZ6o7gXhkjt1Brfd5^Tbn3*Gn2QX48}2A002ovPDHLkV1g=Si46b% literal 0 HcmV?d00001 diff --git a/datasrc/content.py b/datasrc/content.py index 7cb5fbe1a..b6feadbef 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -238,6 +238,7 @@ image_audio_source = Image("audio_source", "editor/audio_source.png") image_strongweak = Image("strongweak", "strong_weak.png") image_hud = Image("hud", "hud.png") image_extras = Image("extras", "extras.png") +image_networkicons = Image("networkicons", "network.png", 1) container.images.Add(image_null) container.images.Add(image_game) @@ -256,6 +257,7 @@ container.images.Add(image_strongweak) container.images.Add(image_hud) container.images.Add(image_extras) container.images.Add(Image("raceflag", "race_flag.png")) +container.images.Add(image_networkicons) container.pickups.Add(Pickup("health")) container.pickups.Add(Pickup("armor")) @@ -277,6 +279,7 @@ set_audio_source = SpriteSet("audio_source", image_audio_source, 1, 1) set_strongweak = SpriteSet("strongweak", image_strongweak, 2, 1) set_hud = SpriteSet("hud", image_hud, 16, 16) set_extras = SpriteSet("extras", image_extras, 16, 16) +set_networkicons = SpriteSet("networkicons", image_networkicons, 1, 2) container.spritesets.Add(set_particles) container.spritesets.Add(set_game) @@ -289,6 +292,7 @@ container.spritesets.Add(set_audio_source) container.spritesets.Add(set_strongweak) container.spritesets.Add(set_hud) container.spritesets.Add(set_extras) +container.spritesets.Add(set_networkicons) container.sprites.Add(Sprite("part_slice", set_particles, 0,0,1,1)) container.sprites.Add(Sprite("part_ball", set_particles, 1,0,1,1)) @@ -454,6 +458,9 @@ container.sprites.Add(Sprite("hud_team0_mode", set_hud, 12,6,2,2)) container.sprites.Add(Sprite("part_snowflake", set_extras, 0,0,2,2)) container.sprites.Add(Sprite("part_sparkle", set_extras, 2,0,2,2)) +container.sprites.Add(Sprite("network_good", set_networkicons, 0,0,1,1)) +container.sprites.Add(Sprite("network_bad", set_networkicons, 0,1,1,1)) + anim = Animation("base") anim.body.frames.Add(AnimKeyframe(0, 0, -4, 0)) diff --git a/datasrc/network.py b/datasrc/network.py index 01c6661e2..5a21e8067 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -28,7 +28,7 @@ GameInfoFlags2 = [ "ALLOW_X_SKINS", "GAMETYPE_CITY", "GAMETYPE_FDDRACE", "ENTITIES_FDDRACE", "HUD_HEALTH_ARMOR", "HUD_AMMO", "HUD_DDRACE", "NO_WEAK_HOOK", "NO_SKIN_CHANGE_FOR_FROZEN" ] -ExPlayerFlags = ["AFK", "PAUSED", "SPEC"] +ExPlayerFlags = ["AFK", "PAUSED", "SPEC", "CONNECTION_PROBLEMS"] LegacyProjectileFlags = [f"CLIENTID_BIT{i}" for i in range(8)] + [ "NO_OWNER", "IS_DDNET", "BOUNCE_HORIZONTAL", "BOUNCE_VERTICAL", "EXPLOSIVE", "FREEZE", diff --git a/src/engine/server.h b/src/engine/server.h index 42e246319..92e0b0be6 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -44,6 +44,7 @@ public: int m_DDNetVersion; const char *m_pDDNetVersionStr; const CUuid *m_pConnectionId; + int m_LastPacketTick; }; int Tick() const { return m_CurrentGameTick; } diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 76da5914f..141b23b5a 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -214,6 +214,7 @@ void CServer::CClient::Reset() m_Snapshots.PurgeAll(); m_LastAckedSnapshot = -1; m_LastInputTick = -1; + m_LastPacketTick = -1; m_SnapRate = CClient::SNAPRATE_INIT; m_Score = -1; m_NextMapChunk = 0; @@ -587,6 +588,7 @@ bool CServer::GetClientInfo(int ClientId, CClientInfo *pInfo) const pInfo->m_Latency = m_aClients[ClientId].m_Latency; pInfo->m_GotDDNetVersion = m_aClients[ClientId].m_DDNetVersionSettled; pInfo->m_DDNetVersion = m_aClients[ClientId].m_DDNetVersion >= 0 ? m_aClients[ClientId].m_DDNetVersion : VERSION_VANILLA; + pInfo->m_LastPacketTick = m_aClients[ClientId].m_LastPacketTick; if(m_aClients[ClientId].m_GotDDNetVersionPacket) { pInfo->m_pConnectionId = &m_aClients[ClientId].m_ConnectionId; @@ -1458,6 +1460,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) return; } + m_aClients[ClientId].m_LastPacketTick = Tick(); if(Config()->m_SvNetlimit && Msg != NETMSG_REQUEST_MAP_DATA) { int64_t Now = time_get(); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index ec4950716..27e8f4c7c 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -145,6 +145,7 @@ public: int m_LastAckedSnapshot; int m_LastInputTick; + int m_LastPacketTick; CSnapshotStorage m_Snapshots; CInput m_LatestInput; diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index f41e2dfd5..6c8f0e681 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -34,6 +34,7 @@ MACRO_CONFIG_INT(ClNameplatesIds, cl_nameplates_ids, 0, 0, 1, CFGFLAG_CLIENT | C MACRO_CONFIG_INT(ClNameplatesOwn, cl_nameplates_own, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show own name plate (useful for demo recording)") MACRO_CONFIG_INT(ClNameplatesFriendMark, cl_nameplates_friendmark, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show friend mark (♥) in name plates") MACRO_CONFIG_INT(ClNameplatesStrong, cl_nameplates_strong, 0, 0, 2, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show strong/weak in name plates (0 - off, 1 - icons, 2 - icons + numbers)") +MACRO_CONFIG_INT(ClNameplatesNetwork, cl_nameplates_network, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show a network icon if the player has connection problems") MACRO_CONFIG_INT(ClTextEntities, cl_text_entities, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Render textual entity data") MACRO_CONFIG_INT(ClTextEntitiesSize, cl_text_entities_size, 100, 1, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Size of textual entity data from 1 to 100%") MACRO_CONFIG_INT(ClStreamerMode, cl_streamer_mode, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Censor sensitive information such as /save password") diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index ee6c6be93..268f40e6d 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -2774,6 +2774,12 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView) g_Config.m_ClNameplatesStrong = g_Config.m_ClNameplatesStrong != 2 ? 2 : 1; } + LeftView.HSplitTop(LineSize, &Button, &LeftView); + if(DoButton_CheckBox(&g_Config.m_ClNameplatesNetwork, Localize("Show connection problems icon"), g_Config.m_ClNameplatesNetwork, &Button)) + { + g_Config.m_ClNameplatesNetwork = g_Config.m_ClNameplatesNetwork ^ 1; + } + LeftView.HSplitTop(LineSize, &Button, &LeftView); if(DoButton_CheckBox(&g_Config.m_ClShowDirection, Localize("Show other players' key presses"), g_Config.m_ClShowDirection >= 1 && g_Config.m_ClShowDirection != 3, &Button)) { @@ -2863,6 +2869,8 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView) TextRender()->Text(TeeRenderPos.x - TextRender()->TextWidth(FontSize, "0") / 2.0f, YOffset, FontSize, "0"); } + float XOffset = TeeRenderPos.x; + bool ChangedOffset = false; if(g_Config.m_ClNameplatesStrong) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_STRONGWEAK].m_Id); @@ -2878,15 +2886,38 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView) const float StrongImgSize = 40.0f; YOffset -= StrongImgSize * ScaleY; - RenderTools()->DrawSprite(TeeRenderPos.x, YOffset + (StrongImgSize / 2.0f) * ScaleY, StrongImgSize); + ChangedOffset = true; + if(g_Config.m_ClNameplatesNetwork) + XOffset = XOffset - (StrongImgSize / 2); + RenderTools()->DrawSprite(XOffset, YOffset + (StrongImgSize / 2.0f) * ScaleY, StrongImgSize); Graphics()->QuadsEnd(); if(g_Config.m_ClNameplatesStrong == 2) { - YOffset -= FontSize; - TextRender()->Text(TeeRenderPos.x - TextRender()->TextWidth(FontSize, "0") / 2.0f, YOffset, FontSize, "0"); + TextRender()->Text(TeeRenderPos.x - TextRender()->TextWidth(FontSize, "0") / 2.0f, YOffset - FontSize, FontSize, "0"); } } + + if(g_Config.m_ClNameplatesNetwork) + { + ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_NETWORKICONS].m_Id); + + Graphics()->QuadsBegin(); + RenderTools()->SelectSprite(SPRITE_NETWORK_BAD); + float ScaleX, ScaleY; + RenderTools()->GetSpriteScale(SPRITE_NETWORK_BAD, ScaleX, ScaleY); + + const float NetworkImgSize = 40.0f; + if(!ChangedOffset) + YOffset -= NetworkImgSize * ScaleY; + else + XOffset += NetworkImgSize; + + Graphics()->SetColor(Color); + RenderTools()->DrawSprite(XOffset, YOffset + (NetworkImgSize / 2.0f) * ScaleY, NetworkImgSize); + Graphics()->QuadsEnd(); + } } TextRender()->TextColor(TextRender()->DefaultTextColor()); diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 59366afe5..79ab3f101 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -204,6 +204,9 @@ void CNamePlates::RenderNameplate(vec2 Position, const CNetObj_PlayerInfo *pPlay } } + float XOffset = Position.x; + bool ChangedOffset = false; + bool ConnectionProblems = m_pClient->m_aClients[pPlayerInfo->m_ClientId].m_ConnectionProblems; if((g_Config.m_Debug || g_Config.m_ClNameplatesStrong) && g_Config.m_ClNameplates) { const bool Following = (m_pClient->m_Snap.m_SpecInfo.m_Active && !GameClient()->m_MultiViewActivated && m_pClient->m_Snap.m_SpecInfo.m_SpectatorId != SPEC_FREEVIEW); @@ -251,20 +254,53 @@ void CNamePlates::RenderNameplate(vec2 Position, const CNetObj_PlayerInfo *pPlay const float StrongWeakImgSize = 40.0f; YOffset -= StrongWeakImgSize * ScaleY; - RenderTools()->DrawSprite(Position.x, YOffset + (StrongWeakImgSize / 2.0f) * ScaleY, StrongWeakImgSize); + ChangedOffset = true; + if(ConnectionProblems && g_Config.m_ClNameplatesNetwork) + XOffset = XOffset - (StrongWeakImgSize / 2); + + RenderTools()->DrawSprite(XOffset, YOffset + (StrongWeakImgSize / 2.0f) * ScaleY, StrongWeakImgSize); Graphics()->QuadsEnd(); } if(g_Config.m_Debug || g_Config.m_ClNameplatesStrong == 2) { - YOffset -= FontSize; char aBuf[12]; str_format(aBuf, sizeof(aBuf), "%d", Other.m_ExtendedData.m_StrongWeakId); - TextRender()->Text(Position.x - TextRender()->TextWidth(FontSize, aBuf) / 2.0f, YOffset, FontSize, aBuf); + TextRender()->Text(Position.x - TextRender()->TextWidth(FontSize, aBuf) / 2.0f, YOffset - FontSize, FontSize, aBuf); } } } } + // Connection problems icon + if(g_Config.m_ClNameplates && g_Config.m_ClNameplatesNetwork) + { + if(ConnectionProblems) + { + ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); + if(OtherTeam && !ForceAlpha) + Color.a = g_Config.m_ClShowOthersAlpha / 100.0f; + else if(g_Config.m_ClNameplatesAlways == 0) + Color.a = clamp(1 - std::pow(distance(m_pClient->m_Controls.m_aTargetPos[g_Config.m_ClDummy], Position) / 200.0f, 16.0f), 0.0f, 1.0f); + + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_NETWORKICONS].m_Id); + + Graphics()->QuadsBegin(); + RenderTools()->SelectSprite(SPRITE_NETWORK_BAD); + float ScaleX, ScaleY; + RenderTools()->GetSpriteScale(SPRITE_NETWORK_BAD, ScaleX, ScaleY); + + const float NetworkImgSize = 40.0f; + if(!ChangedOffset) + YOffset -= NetworkImgSize * ScaleY; + else + XOffset += NetworkImgSize; + + Graphics()->SetColor(Color); + RenderTools()->DrawSprite(XOffset, YOffset + (NetworkImgSize / 2.0f) * ScaleY, NetworkImgSize); + Graphics()->QuadsEnd(); + } + } + TextRender()->TextColor(TextRender()->DefaultTextColor()); TextRender()->TextOutlineColor(TextRender()->DefaultTextOutlineColor()); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index dd62db703..f4d733bfc 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1615,6 +1615,7 @@ void CGameClient::OnNewSnapshot() m_aClients[Item.m_Id].m_Afk = pInfo->m_Flags & EXPLAYERFLAG_AFK; m_aClients[Item.m_Id].m_Paused = pInfo->m_Flags & EXPLAYERFLAG_PAUSED; m_aClients[Item.m_Id].m_Spec = pInfo->m_Flags & EXPLAYERFLAG_SPEC; + m_aClients[Item.m_Id].m_ConnectionProblems = pInfo->m_Flags & EXPLAYERFLAG_CONNECTION_PROBLEMS; if(Item.m_Id == m_Snap.m_LocalClientId && (m_aClients[Item.m_Id].m_Paused || m_aClients[Item.m_Id].m_Spec)) { @@ -2498,6 +2499,7 @@ void CGameClient::CClientData::Reset() m_Afk = false; m_Paused = false; m_Spec = false; + m_ConnectionProblems = false; std::fill(std::begin(m_aSwitchStates), std::end(m_aSwitchStates), 0); diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index b8f2d9c95..2c9573aa0 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -420,6 +420,7 @@ public: bool m_Afk; bool m_Paused; bool m_Spec; + bool m_ConnectionProblems; // Editor allows 256 switches for now. bool m_aSwitchStates[256]; diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index f4c540449..aa6694455 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -424,6 +424,14 @@ void CPlayer::Snap(int SnappingClient) if(m_Paused == PAUSE_PAUSED) pDDNetPlayer->m_Flags |= EXPLAYERFLAG_PAUSED; + IServer::CClientInfo Info; + if(Server()->GetClientInfo(id, &Info)) + { + // Send "connection problems" flag if player hasn't sent any packets after 5 seconds. + if(Server()->Tick() - Info.m_LastPacketTick >= 5 * Server()->TickSpeed()) + pDDNetPlayer->m_Flags |= EXPLAYERFLAG_CONNECTION_PROBLEMS; + } + if(Server()->IsSixup(SnappingClient) && m_pCharacter && m_pCharacter->m_DDRaceState == DDRACE_STARTED && GameServer()->m_apPlayers[SnappingClient]->m_TimerType == TIMERTYPE_SIXUP) {