From a48c69b0a98a8a816ef65298190fcecff4000b91 Mon Sep 17 00:00:00 2001 From: def Date: Tue, 3 May 2016 21:25:24 +0200 Subject: [PATCH 01/58] Fix ddnet.tw link --- README.md | 6 +++--- autoexec_server.cfg | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c0ed21602..54e55399f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -[![DDraceNetwork](http://ddnet.tw/ddnet-small.png)](http://ddnet.tw) [![Build Status](https://circleci.com/gh/ddnet/ddnet/tree/master.png)](https://circleci.com/gh/ddnet/ddnet) +[![DDraceNetwork](https://ddnet.tw/ddnet-small.png)](https://ddnet.tw) [![Build Status](https://circleci.com/gh/ddnet/ddnet/tree/master.png)](https://circleci.com/gh/ddnet/ddnet) ================================ -Our own flavor of DDRace, a Teeworlds mod. See the [website](http://ddnet.tw) for more information. +Our own flavor of DDRace, a Teeworlds mod. See the [website](https://ddnet.tw) for more information. Development discussions happen on #ddnet on Quakenet ([Webchat](http://webchat.quakenet.org/?channels=ddnet&uio=d4)). -You can get binary releases on the [DDNet website](http://ddnet.tw/downloads/). +You can get binary releases on the [DDNet website](https://ddnet.tw/downloads/). Building -------- diff --git a/autoexec_server.cfg b/autoexec_server.cfg index 499a01fb0..de6dd13b7 100644 --- a/autoexec_server.cfg +++ b/autoexec_server.cfg @@ -1,7 +1,7 @@ # # autoexec_server.cfg # -# See http://ddnet.tw/settingscommands for all available settings. +# See https://ddnet.tw/settingscommands/ for all available settings. # Everything following a # is considered a comment and ignored by the server. # When an option can be enabled or disabled, it's enabled with 1, disabled with 0. # From dee629acf017d4624daa7889d163e00fc2a9e335 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 4 May 2016 01:22:38 +0200 Subject: [PATCH 02/58] SDL2 in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 54e55399f..11d1c81f9 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ To compile DDNet yourself, you can follow the [instructions for compiling Teewor DDNet requires additional libraries, that are bundled for the most common platforms (Windows, Mac, Linux, all x86 and x86_64). Instead you can install these libraries on your system, remove the `config.lua` and `bam` should use the system-wide libraries by default. You can install all required dependencies on Debian and Ubuntu like this: - apt-get install libsdl1.2-dev libfreetype6-dev libcurl4-openssl-dev libogg-dev libopus-dev libopusfile-dev + apt-get install libsdl2-2.0-dev libfreetype6-dev libcurl4-openssl-dev libogg-dev libopus-dev libopusfile-dev If you have the libraries installed, but still want to use the bundled ones instead, you can specify so by running `bam config curl.use_pkgconfig=false opus.use_pkgconfig=false opusfile.use_pkgconfig=false ogg.use_pkgconfig=false`. From 45971ee8e9b2cff8beb960e75a404baad17ebf09 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 4 May 2016 16:01:58 +0200 Subject: [PATCH 03/58] no player antiping when appropriate tunings set --- src/game/client/gameclient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 3818a5886..001dd9740 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -365,7 +365,7 @@ public: void FindWeaker(bool IsWeaker[2][MAX_CLIENTS]); - bool AntiPingPlayers() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingPlayers && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK; } + bool AntiPingPlayers() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingPlayers && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK && !(m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_Tuning[g_Config.m_ClDummy].m_PlayerHooking || m_Tuning[g_Config.m_ClDummy].m_HammerStrength > 0); } bool AntiPingGrenade() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingGrenade && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK; } bool AntiPingWeapons() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingWeapons && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK; } From 1b668047c8f022a40dbba1de92c5294862680c13 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 4 May 2016 18:23:00 +0200 Subject: [PATCH 04/58] Clean up auto reconnect and make it independent of rendering --- src/engine/client.h | 1 + src/engine/client/client.cpp | 17 +++++++++++ src/game/client/components/menus.cpp | 44 ++++------------------------ src/game/client/components/menus.h | 1 - 4 files changed, 23 insertions(+), 40 deletions(-) diff --git a/src/engine/client.h b/src/engine/client.h index c2b7b1ada..c304a82e4 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -41,6 +41,7 @@ protected: public: int m_LocalIDs[2]; char m_aNews[NEWS_SIZE]; + int64 m_ReconnectTime; CNetObj_PlayerInput m_DummyInput; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 9a00dc0a5..4e71053c5 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -345,6 +345,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta) m_LastDummyConnectTime = 0; m_DDNetSrvListTokenSet = false; + m_ReconnectTime = 0; } // ----- send functions ----- @@ -622,7 +623,17 @@ void CClient::SetState(int s) } m_State = s; if(Old != s) + { GameClient()->OnStateChange(m_State, Old); + + if(s == IClient::STATE_OFFLINE && m_ReconnectTime == 0) + { + if(g_Config.m_ClReconnectFull > 0 && (str_find_nocase(ErrorString(), "full") || str_find_nocase(ErrorString(), "reserved"))) + m_ReconnectTime = time_get() + time_freq() * g_Config.m_ClReconnectFull; + else if(g_Config.m_ClReconnectTimeout > 0 && str_find_nocase(ErrorString(), "Timeout")) + m_ReconnectTime = time_get() + time_freq() * g_Config.m_ClReconnectTimeout; + } + } } // called when the map is loaded and we should init for a new round @@ -2467,6 +2478,12 @@ void CClient::Update() // update gameclient if(!m_EditorActive) GameClient()->OnUpdate(); + + if(m_ReconnectTime > 0 && time_get() > m_ReconnectTime) + { + Connect(g_Config.m_UiServerAddress); + m_ReconnectTime = 0; + } } void CClient::VersionUpdate() diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index c251b6b32..2e5923d4c 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1057,29 +1057,12 @@ int CMenus::Render() pTitle = Localize("Disconnected"); pExtraText = Client()->ErrorString(); pButtonText = Localize("Ok"); - if ((str_find_nocase(Client()->ErrorString(), "full")) || (str_find_nocase(Client()->ErrorString(), "reserved"))) + if(Client()->m_ReconnectTime > 0) { - if (g_Config.m_ClReconnectFull > 0) - { - if (_my_rtime == 0) - _my_rtime = time_get(); - str_format(aBuf, sizeof(aBuf), Localize("\n\nReconnect in %d sec"), ((_my_rtime - time_get()) / time_freq() + g_Config.m_ClReconnectFull)); - pTitle = Client()->ErrorString(); - pExtraText = aBuf; - pButtonText = Localize("Abort"); - } - } - else if (str_find_nocase(Client()->ErrorString(), "Timeout")) - { - if (g_Config.m_ClReconnectTimeout > 0) - { - if (_my_rtime == 0) - _my_rtime = time_get(); - str_format(aBuf, sizeof(aBuf), Localize("\n\nReconnect in %d sec"), ((_my_rtime - time_get()) / time_freq() + g_Config.m_ClReconnectTimeout)); - pTitle = Client()->ErrorString(); - pExtraText = aBuf; - pButtonText = Localize("Abort"); - } + str_format(aBuf, sizeof(aBuf), Localize("\n\nReconnect in %d sec"), ((Client()->m_ReconnectTime - time_get()) / time_freq() + g_Config.m_ClReconnectFull)); + pTitle = Client()->ErrorString(); + pExtraText = aBuf; + pButtonText = Localize("Abort"); } ExtraAlign = 0; } @@ -1620,23 +1603,6 @@ int CMenus::Render() if(m_Popup == POPUP_NONE) UI()->SetActiveItem(0); } - - if (m_Popup == POPUP_DISCONNECTED) - { - if (str_find_nocase(Client()->ErrorString(), "full") || str_find_nocase(Client()->ErrorString(), "reserved")) - { - if (g_Config.m_ClReconnectFull > 0 && time_get() > _my_rtime + time_freq() * g_Config.m_ClReconnectFull) - Client()->Connect(g_Config.m_UiServerAddress); - } - else if (str_find_nocase(Client()->ErrorString(), "Timeout")) - { - if (g_Config.m_ClReconnectTimeout > 0 && time_get() > _my_rtime + time_freq() * g_Config.m_ClReconnectTimeout) - Client()->Connect(g_Config.m_UiServerAddress); - } - } - else if (_my_rtime != 0) { - _my_rtime = 0; - } return 0; } diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 18d624bc6..cf910d8a2 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -320,7 +320,6 @@ public: }; // DDRace - int64 _my_rtime; // reconnect time int DoButton_CheckBox_DontCare(const void *pID, const char *pText, int Checked, const CUIRect *pRect); sorted_array m_lDemos; void DemolistPopulate(); From 2df9c79483ab711500cf3bd068a389ec9c4361ea Mon Sep 17 00:00:00 2001 From: def Date: Wed, 4 May 2016 18:43:54 +0200 Subject: [PATCH 05/58] proper str_copy size (fixes #461) --- src/game/server/gamecontroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 935a72445..0d13ffead 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -422,7 +422,7 @@ void IGameController::ChangeMap(const char *pToMap) { /*str_copy(m_aMapWish, pToMap, sizeof(m_aMapWish)); EndRound();*/ - str_copy(g_Config.m_SvMap, pToMap, sizeof(m_aMapWish)); + str_copy(g_Config.m_SvMap, pToMap, sizeof(g_Config.m_SvMap)); } /*void IGameController::CycleMap() From 7a3f96431ab415c5f7a153b091143b108912a4b6 Mon Sep 17 00:00:00 2001 From: gamertyp Date: Wed, 4 May 2016 22:30:16 +0200 Subject: [PATCH 06/58] Re-ordered the Gametiles-menu --- src/game/editor/popups.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 2d77028cc..f85fbe6b4 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -1307,7 +1307,7 @@ static int s_GametileOpSelected = -1; int CEditor::PopupSelectGametileOp(CEditor *pEditor, CUIRect View) { - static const char *s_pButtonNames[] = { "Clear", "Collision", "Death", "Unhookable", "Freeze", "Unfreeze", "Deep Freeze", "Deep Unfreeze", "Check-Tele From", "Evil Check-Tele From", "Hookthrough" }; + static const char *s_pButtonNames[] = { "Clear", "Collision", "Death", "Unhookable", "Hookthrough", "Freeze", "Unfreeze", "Deep Freeze", "Deep Unfreeze", "Blue Check-Tele", "Red Check-Tele" }; static unsigned s_NumButtons = sizeof(s_pButtonNames) / sizeof(char*); CUIRect Button; From e9378973de8e159a219dcde8ea48e7258cd76034 Mon Sep 17 00:00:00 2001 From: gamertyp Date: Wed, 4 May 2016 22:33:10 +0200 Subject: [PATCH 07/58] Re-ordered the Gametiles-menu --- src/game/editor/layer_tiles.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index 8e09ef6f8..c16ef3792 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -600,27 +600,27 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) int Result = m_pEditor->PopupSelectGameTileOpResult(); switch(Result) - { + { case 4: - Result = TILE_FREEZE; + Result = TILE_THROUGH_CUT; break; case 5: - Result = TILE_UNFREEZE; + Result = TILE_FREEZE; break; case 6: - Result = TILE_DFREEZE; + Result = TILE_UNFREEZE; break; case 7: - Result = TILE_DUNFREEZE; + Result = TILE_DFREEZE; break; case 8: - Result = TILE_TELECHECKIN; + Result = TILE_DUNFREEZE; break; case 9: - Result = TILE_TELECHECKINEVIL; + Result = TILE_TELECHECKIN; break; case 10: - Result = TILE_THROUGH_CUT; + Result = TILE_TELECHECKINEVIL; default: break; } From b479dd412c791fcdc47603ce7fca1809951766f8 Mon Sep 17 00:00:00 2001 From: gamertyp Date: Wed, 4 May 2016 23:37:02 +0200 Subject: [PATCH 08/58] Removed a tab --- src/game/editor/layer_tiles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index c16ef3792..c0609a3cf 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -600,7 +600,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) int Result = m_pEditor->PopupSelectGameTileOpResult(); switch(Result) - { + { case 4: Result = TILE_THROUGH_CUT; break; From 77b584c12f925f9099803d669c8e2ab4ab18c7d4 Mon Sep 17 00:00:00 2001 From: Henningstone Date: Thu, 5 May 2016 01:33:28 +0200 Subject: [PATCH 09/58] Forbid showing /top5 from rank 0 on --- src/game/server/ddracechat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/server/ddracechat.cpp b/src/game/server/ddracechat.cpp index fbd2a1203..8cc44c675 100644 --- a/src/game/server/ddracechat.cpp +++ b/src/game/server/ddracechat.cpp @@ -396,7 +396,7 @@ void CGameContext::ConTeamTop5(IConsole::IResult *pResult, void *pUserData) return; } - if (pResult->NumArguments() > 0 && pResult->GetInteger(0) >= 0) + if (pResult->NumArguments() > 0 && pResult->GetInteger(0) > 0) pSelf->Score()->ShowTeamTop5(pResult, pResult->m_ClientID, pUserData, pResult->GetInteger(0)); else @@ -427,7 +427,7 @@ void CGameContext::ConTop5(IConsole::IResult *pResult, void *pUserData) return; } - if (pResult->NumArguments() > 0 && pResult->GetInteger(0) >= 0) + if (pResult->NumArguments() > 0 && pResult->GetInteger(0) > 0) pSelf->Score()->ShowTop5(pResult, pResult->m_ClientID, pUserData, pResult->GetInteger(0)); else From 82d2a994ed38cad6932be0d0dd271a0112c6ca57 Mon Sep 17 00:00:00 2001 From: Ryozuki Date: Thu, 5 May 2016 18:07:00 +0200 Subject: [PATCH 10/58] Fixed cl_showping (now cl_showpred) --- src/engine/client.h | 2 ++ src/engine/client/client.cpp | 10 +++++++--- src/engine/client/client.h | 1 + src/game/client/components/hud.cpp | 5 ++--- src/game/client/components/killmessages.cpp | 2 +- src/game/server/player.cpp | 2 -- src/game/variables.h | 2 +- 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/engine/client.h b/src/engine/client.h index c304a82e4..a8fef7f0e 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -140,6 +140,8 @@ public: virtual void CheckVersionUpdate() = 0; + virtual int GetPredictionTime() = 0; + // snapshot interface enum diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 4e71053c5..0f670bf65 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -933,7 +933,6 @@ void CClient::DebugRender() static NETSTATS Prev, Current; static int64 LastSnap = 0; static float FrameTimeAvg = 0; - int64 Now = time_get(); char aBuffer[512]; if(!g_Config.m_Debug) @@ -999,8 +998,7 @@ void CClient::DebugRender() } } - str_format(aBuffer, sizeof(aBuffer), "pred: %d ms", - (int)((m_PredictedTime.Get(Now)-m_GameTime[g_Config.m_ClDummy].Get(Now))*1000/(float)time_freq())); + str_format(aBuffer, sizeof(aBuffer), "pred: %d ms", GetPredictionTime()); Graphics()->QuadsText(2, 70, 16, aBuffer); Graphics()->QuadsEnd(); @@ -3548,3 +3546,9 @@ void CClient::RequestDDNetSrvList() Packet.m_Flags = NETSENDFLAG_CONNLESS; m_NetClient[g_Config.m_ClDummy].Send(&Packet); } + +int CClient::GetPredictionTime() +{ + int64 Now = time_get(); + return (int)((m_PredictedTime.Get(Now)-m_GameTime[g_Config.m_ClDummy].Get(Now))*1000/(float)time_freq()); +} diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 7bed98ad6..0b35c2e00 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -270,6 +270,7 @@ public: // --- + int GetPredictionTime(); void *SnapGetItem(int SnapID, int Index, CSnapItem *pItem); void SnapInvalidateItem(int SnapID, int Index); void *SnapFindItem(int SnapID, int Type, int ID); diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index a8ca987cb..f1452a317 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -319,11 +319,10 @@ void CHud::RenderTextInfo() str_format(Buf, sizeof(Buf), "%d", (int)m_AverageFPS); TextRender()->Text(0, m_Width-10-TextRender()->TextWidth(0,12,Buf,-1), 5, 12, Buf, -1); } - - if(g_Config.m_ClShowping) + if(g_Config.m_ClShowpred) { char aBuf[64]; - str_format(aBuf, sizeof(aBuf), "%d", clamp(m_pClient->m_Snap.m_pLocalInfo->m_Latency, 0, 1000)); + str_format(aBuf, sizeof(aBuf), "%d", Client()->GetPredictionTime()); TextRender()->Text(0, m_Width-10-TextRender()->TextWidth(0,12,aBuf,-1), g_Config.m_ClShowfps ? 20 : 5, 12, aBuf, -1); } } diff --git a/src/game/client/components/killmessages.cpp b/src/game/client/components/killmessages.cpp index 07ca1e927..0a1e44ef7 100644 --- a/src/game/client/components/killmessages.cpp +++ b/src/game/client/components/killmessages.cpp @@ -54,7 +54,7 @@ void CKillMessages::OnRender() Graphics()->MapScreen(0, 0, Width*1.5f, Height*1.5f); float StartX = Width*1.5f-10.0f; - float y = 30.0f + 100.0f * (g_Config.m_ClShowfps + g_Config.m_ClShowping); + float y = 30.0f + 100.0f * (g_Config.m_ClShowfps + g_Config.m_ClShowpred); for(int i = 1; i <= MAX_KILLMSGS; i++) { diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 1c82da654..207215c6b 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -263,8 +263,6 @@ void CPlayer::PostTick() m_aActLatency[i] = GameServer()->m_apPlayers[i]->m_Latency.m_Min; } } - else - m_aActLatency[m_ClientID] = GameServer()->m_apPlayers[m_ClientID]->m_Latency.m_Min; // update view pos for spectators if((m_Team == TEAM_SPECTATORS || m_Paused) && m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID] && GameServer()->m_apPlayers[m_SpectatorID]->GetCharacter()) diff --git a/src/game/variables.h b/src/game/variables.h index 5fa371680..b42192d2b 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -36,7 +36,7 @@ MACRO_CONFIG_INT(ClShowKillMessages, cl_showkillmessages, 1, 0, 1, CFGFLAG_CLIEN MACRO_CONFIG_INT(ClShowVotesAfterVoting, cl_show_votes_after_voting, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show votes window after voting") MACRO_CONFIG_INT(ClShowLocalTimeAlways, cl_show_local_time_always, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show local time") MACRO_CONFIG_INT(ClShowfps, cl_showfps, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame FPS counter") -MACRO_CONFIG_INT(ClShowping, cl_showping, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame ping counter") +MACRO_CONFIG_INT(ClShowpred, cl_showpred, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame prediction time in milliseconds") MACRO_CONFIG_INT(ClEyeWheel, cl_eye_wheel, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show eye wheel along together with emotes") MACRO_CONFIG_INT(ClEyeDuration, cl_eye_duration, 999999, 1, 999999, CFGFLAG_CLIENT|CFGFLAG_SAVE, "How long the eyes emotes last") From afd0e5a3eb65e36a0c9c485fd18538e7b922e4b9 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Thu, 5 May 2016 18:23:04 +0200 Subject: [PATCH 11/58] rename some auto game tile placers --- src/game/editor/popups.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index f85fbe6b4..0690029d5 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -1307,7 +1307,7 @@ static int s_GametileOpSelected = -1; int CEditor::PopupSelectGametileOp(CEditor *pEditor, CUIRect View) { - static const char *s_pButtonNames[] = { "Clear", "Collision", "Death", "Unhookable", "Hookthrough", "Freeze", "Unfreeze", "Deep Freeze", "Deep Unfreeze", "Blue Check-Tele", "Red Check-Tele" }; + static const char *s_pButtonNames[] = { "Air", "Hookable", "Death", "Unhookable", "Hookthrough", "Freeze", "Unfreeze", "Deep Freeze", "Deep Unfreeze", "Blue Check-Tele", "Red Check-Tele" }; static unsigned s_NumButtons = sizeof(s_pButtonNames) / sizeof(char*); CUIRect Button; From 78f8c9978daafdb86cfedaa4860b855062df70eb Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Thu, 5 May 2016 18:40:38 +0200 Subject: [PATCH 12/58] fix editor gametiles automapper overlap --- src/game/editor/editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 4c2f3c4b4..d0befc2db 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3012,7 +3012,7 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) m_SelectedGroup = g; static int s_LayerPopupID = 0; if(Result == 2) - UiInvokePopupMenu(&s_LayerPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 260, PopupLayer); + UiInvokePopupMenu(&s_LayerPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 280, PopupLayer); } LayerCur += 14.0f; From 14f1670fda0636121f60be918a2d7a2c5fe4e652 Mon Sep 17 00:00:00 2001 From: def Date: Thu, 5 May 2016 18:48:15 +0200 Subject: [PATCH 13/58] Fix fifo console to remove newline character at end --- src/engine/shared/fifo.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/shared/fifo.cpp b/src/engine/shared/fifo.cpp index f6200249e..bd4d05aa3 100644 --- a/src/engine/shared/fifo.cpp +++ b/src/engine/shared/fifo.cpp @@ -63,7 +63,11 @@ void CFifo::Update() while(true) { char *pResult = fgets(aBuf, sizeof(aBuf), m_File); - if(pResult == NULL) break; + if(pResult == NULL) + break; + int Last = str_length(pResult) - 1; + if(Last >= 0 && pResult[Last] == '\n') + pResult[Last] = '\0'; m_pConsole->ExecuteLineFlag(pResult, m_Flag, -1); } } From 513c74219700f3cbd40323cece292eba0aecb597 Mon Sep 17 00:00:00 2001 From: def Date: Thu, 5 May 2016 18:57:35 +0200 Subject: [PATCH 14/58] Fix cl_antiping_players to be off on solo (thanks HMH) --- src/game/client/gameclient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 001dd9740..9e9f70999 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -365,7 +365,7 @@ public: void FindWeaker(bool IsWeaker[2][MAX_CLIENTS]); - bool AntiPingPlayers() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingPlayers && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK && !(m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_Tuning[g_Config.m_ClDummy].m_PlayerHooking || m_Tuning[g_Config.m_ClDummy].m_HammerStrength > 0); } + bool AntiPingPlayers() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingPlayers && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK && (m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_Tuning[g_Config.m_ClDummy].m_PlayerHooking); } bool AntiPingGrenade() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingGrenade && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK; } bool AntiPingWeapons() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingWeapons && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK; } From 072eadbb998dcb9c78a7fd34dc2be95ccc4a916a Mon Sep 17 00:00:00 2001 From: def Date: Thu, 5 May 2016 20:17:13 +0200 Subject: [PATCH 15/58] Use DDNet entities by default, fixes seeing unhookable from start (thanks to kamillentee) --- src/game/client/components/mapimages.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp index 1afc7f682..cb1e0402d 100644 --- a/src/game/client/components/mapimages.cpp +++ b/src/game/client/components/mapimages.cpp @@ -94,7 +94,8 @@ int CMapImages::GetEntities() if(m_EntitiesTextures == -1 || str_comp(m_aEntitiesGameType, Info.m_aGameType)) { - char file[64] = "vanilla"; + // DDNet default to prevent delay in seeing entities + char file[64] = "ddnet"; if(IsDDNet(&Info)) str_copy(file, "ddnet", sizeof(file)); else if(IsDDRace(&Info)) From 41f34aa1875bc79297e903ce4c07b97d0b670267 Mon Sep 17 00:00:00 2001 From: def Date: Thu, 5 May 2016 20:21:34 +0200 Subject: [PATCH 16/58] Add vanilla check for entities_clear --- src/game/client/components/mapimages.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game/client/components/mapimages.cpp b/src/game/client/components/mapimages.cpp index cb1e0402d..e4069ee9e 100644 --- a/src/game/client/components/mapimages.cpp +++ b/src/game/client/components/mapimages.cpp @@ -104,6 +104,8 @@ int CMapImages::GetEntities() str_copy(file, "race", sizeof(file)); else if(IsFNG(&Info)) str_copy(file, "fng", sizeof(file)); + else if(IsVanilla(&Info)) + str_copy(file, "vanilla", sizeof(file)); char path[64]; str_format(path, sizeof(path), "editor/entities_clear/%s.png", file); From 491d878a6443c1aa65035d41098b14cdc35a2ee3 Mon Sep 17 00:00:00 2001 From: H-M-H Date: Thu, 5 May 2016 20:29:31 +0200 Subject: [PATCH 17/58] always read fifo from start --- src/engine/shared/fifo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/shared/fifo.cpp b/src/engine/shared/fifo.cpp index bd4d05aa3..8baaede19 100644 --- a/src/engine/shared/fifo.cpp +++ b/src/engine/shared/fifo.cpp @@ -58,6 +58,8 @@ void CFifo::Update() if(m_File == NULL) return; + rewind(m_File); + char aBuf[8192]; while(true) From 3965155e06c7e4a9ee2c2e4986c17f53ba749b62 Mon Sep 17 00:00:00 2001 From: H-M-H Date: Thu, 5 May 2016 20:33:16 +0200 Subject: [PATCH 18/58] updated .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2252680cd..cfef20170 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ mastersrv* packetgen* teeworlds* teeworlds_srv* +serverlaunch_* tileset_border* twping* versionsrv* From 319729e207eada1f0fed64d62632064832967877 Mon Sep 17 00:00:00 2001 From: H-M-H Date: Thu, 5 May 2016 21:15:15 +0200 Subject: [PATCH 19/58] ifdef for rewind as it is only required of OS X --- src/engine/shared/fifo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/shared/fifo.cpp b/src/engine/shared/fifo.cpp index 8baaede19..afd1b4839 100644 --- a/src/engine/shared/fifo.cpp +++ b/src/engine/shared/fifo.cpp @@ -58,7 +58,9 @@ void CFifo::Update() if(m_File == NULL) return; +#ifdef CONF_PLATFORM_MACOSX rewind(m_File); +#endif char aBuf[8192]; From 939f2136c08838434d82500e7daf9d7dc7ca939b Mon Sep 17 00:00:00 2001 From: def Date: Thu, 5 May 2016 23:32:55 +0200 Subject: [PATCH 20/58] Nicer way of handling Mac fifo rewinding (just don't use high level file streams) --- src/engine/shared/fifo.cpp | 40 ++++++++++++++++++-------------------- src/engine/shared/fifo.h | 4 +--- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/engine/shared/fifo.cpp b/src/engine/shared/fifo.cpp index afd1b4839..9ff4d45c6 100644 --- a/src/engine/shared/fifo.cpp +++ b/src/engine/shared/fifo.cpp @@ -5,15 +5,15 @@ #include -#include #include #include #include #include +#include void CFifo::Init(IConsole *pConsole, char *pFifoFile, int Flag) { - m_File = NULL; + m_File = -1; m_pConsole = pConsole; if(pFifoFile[0] == '\0') @@ -40,39 +40,37 @@ void CFifo::Init(IConsole *pConsole, char *pFifoFile, int Flag) } } - int fileFD = open(pFifoFile, O_RDONLY|O_NONBLOCK); - if(fileFD >= 0) - m_File = fdopen(fileFD, "r"); - if(m_File == NULL) + m_File = open(pFifoFile, O_RDONLY|O_NONBLOCK); + if(m_File < 0) dbg_msg("fifo", "can't open file '%s'", pFifoFile); } void CFifo::Shutdown() { - if(m_File) - fclose(m_File); + if(m_File >= 0) + close(m_File); } void CFifo::Update() { - if(m_File == NULL) + if(m_File < 0) return; -#ifdef CONF_PLATFORM_MACOSX - rewind(m_File); -#endif - char aBuf[8192]; + int Length = read(m_File, aBuf, sizeof(aBuf)); + if(Length <= 0) + return; - while(true) + char *pCur = aBuf; + for(int i = 0; i < Length; ++i) { - char *pResult = fgets(aBuf, sizeof(aBuf), m_File); - if(pResult == NULL) - break; - int Last = str_length(pResult) - 1; - if(Last >= 0 && pResult[Last] == '\n') - pResult[Last] = '\0'; - m_pConsole->ExecuteLineFlag(pResult, m_Flag, -1); + if(aBuf[i] != '\n') + continue; + aBuf[i] = '\0'; + m_pConsole->ExecuteLineFlag(pCur, m_Flag, -1); + pCur = aBuf+i+1; } + if(pCur < aBuf+Length) // missed the last line + m_pConsole->ExecuteLineFlag(pCur, m_Flag, -1); } #endif diff --git a/src/engine/shared/fifo.h b/src/engine/shared/fifo.h index e8c85f275..f7d4dfd42 100644 --- a/src/engine/shared/fifo.h +++ b/src/engine/shared/fifo.h @@ -5,13 +5,11 @@ #if defined(CONF_FAMILY_UNIX) -#include // FILE - class CFifo { IConsole *m_pConsole; int m_Flag; - FILE *m_File; + int m_File; public: void Init(IConsole *pConsole, char *pFifoFile, int Flag); From f2100fbad78f724a90d06e5d947025879794f90d Mon Sep 17 00:00:00 2001 From: def Date: Fri, 6 May 2016 11:29:34 +0200 Subject: [PATCH 21/58] Change window focus handling (disable input grab when focus lost) --- src/engine/client/input.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index 498dca6b8..be7b641a3 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -249,7 +249,12 @@ int CInput::Update() case SDL_WINDOWEVENT_FOCUS_LOST: m_MouseFocus = false; IgnoreKeys = true; - SDL_SetRelativeMouseMode(SDL_FALSE); + if(m_InputGrabbed) + { + MouseModeAbsolute(); + // Remember that we had relative mouse + m_InputGrabbed = true; + } break; #if defined(CONF_PLATFORM_MACOSX) // Todo: remove this when fixed in SDL case SDL_WINDOWEVENT_MAXIMIZED: From d80d2de1340288a20d316144b5648563e617ee5f Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Fri, 6 May 2016 16:45:30 +0200 Subject: [PATCH 22/58] fix tab --- src/game/collision.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/collision.cpp b/src/game/collision.cpp index 7f74843e6..ca0fd2e82 100644 --- a/src/game/collision.cpp +++ b/src/game/collision.cpp @@ -70,11 +70,11 @@ void CCollision::Init(class CLayers *pLayers) } if(m_pLayers->TuneLayer()) - { + { unsigned int Size = m_pLayers->Map()->GetUncompressedDataSize(m_pLayers->TuneLayer()->m_Tune); if (Size >= m_Width*m_Height*sizeof(CTuneTile)) m_pTune = static_cast(m_pLayers->Map()->GetData(m_pLayers->TuneLayer()->m_Tune)); - } + } if(m_pLayers->FrontLayer()) { From 997713f9a1045d11e6a4039f13b02a49e1950aea Mon Sep 17 00:00:00 2001 From: Henningstone Date: Fri, 6 May 2016 17:16:31 +0200 Subject: [PATCH 23/58] Jump to special characters with CTRL+arrowkeys in chat input --- src/game/client/components/chat.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index be21fb2ab..cb0e49d9b 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -150,6 +150,35 @@ bool CChat::OnInput(IInput::CEvent Event) Input()->SetClipboardText(m_Input.GetString()); } + if(Input()->KeyIsPressed(KEY_LCTRL)) // jump in front of spaces, special characters and upper case letters + { + int SearchDirection = 0; + if(Input()->KeyPress(KEY_LEFT)) + SearchDirection = -1; + else if(Input()->KeyPress(KEY_RIGHT)) + SearchDirection = 1; + + if(SearchDirection != 0) + { + int FoundAt = SearchDirection > 0 ? m_Input.GetLength()-1 : 0; + for(int i = m_Input.GetCursorOffset()+SearchDirection; SearchDirection > 0 ? i < m_Input.GetLength()-1 : i > 0; i+=SearchDirection) + { + int next = i+SearchDirection; + if( (m_Input.GetString()[next] == ' ') || + (m_Input.GetString()[next] >= 32 && m_Input.GetString()[next] <= 47) || // special character + (m_Input.GetString()[next] >= 58 && m_Input.GetString()[next] <= 64) || // special character + (m_Input.GetString()[next] >= 91 && m_Input.GetString()[next] <= 96) || // special character + ((m_Input.GetString()[next] >= 65 && m_Input.GetString()[next] <= 90) // upper case + && !(m_Input.GetString()[i] >= 65 && m_Input.GetString()[i] <= 90))) + { + FoundAt = i; + break; + } + } + m_Input.SetCursorOffset(FoundAt); + } + } + if(Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE) { m_Mode = MODE_NONE; From cdc37493c2835e79d93167f74f252a40d6042ac2 Mon Sep 17 00:00:00 2001 From: Henningstone Date: Fri, 6 May 2016 19:48:36 +0200 Subject: [PATCH 24/58] Removed the check for uppercase letters --- src/game/client/components/chat.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index cb0e49d9b..0149228e3 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -150,7 +150,7 @@ bool CChat::OnInput(IInput::CEvent Event) Input()->SetClipboardText(m_Input.GetString()); } - if(Input()->KeyIsPressed(KEY_LCTRL)) // jump in front of spaces, special characters and upper case letters + if(Input()->KeyIsPressed(KEY_LCTRL)) // jump to spaces and special ASCII characters { int SearchDirection = 0; if(Input()->KeyPress(KEY_LEFT)) @@ -165,11 +165,9 @@ bool CChat::OnInput(IInput::CEvent Event) { int next = i+SearchDirection; if( (m_Input.GetString()[next] == ' ') || - (m_Input.GetString()[next] >= 32 && m_Input.GetString()[next] <= 47) || // special character - (m_Input.GetString()[next] >= 58 && m_Input.GetString()[next] <= 64) || // special character - (m_Input.GetString()[next] >= 91 && m_Input.GetString()[next] <= 96) || // special character - ((m_Input.GetString()[next] >= 65 && m_Input.GetString()[next] <= 90) // upper case - && !(m_Input.GetString()[i] >= 65 && m_Input.GetString()[i] <= 90))) + (m_Input.GetString()[next] >= 32 && m_Input.GetString()[next] <= 47) || + (m_Input.GetString()[next] >= 58 && m_Input.GetString()[next] <= 64) || + (m_Input.GetString()[next] >= 91 && m_Input.GetString()[next] <= 96) ) { FoundAt = i; break; From 6a10c96e02d41e89fdba60e12d9eedb7395f9312 Mon Sep 17 00:00:00 2001 From: Henningstone Date: Sat, 7 May 2016 01:01:56 +0200 Subject: [PATCH 25/58] Fix cursor behaviour when skipping backwards --- src/game/client/components/chat.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 0149228e3..4aaf0fc9a 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -170,6 +170,8 @@ bool CChat::OnInput(IInput::CEvent Event) (m_Input.GetString()[next] >= 91 && m_Input.GetString()[next] <= 96) ) { FoundAt = i; + if(SearchDirection < 0) + FoundAt++; break; } } From c325b080870d3273c631520b9acd95db5642dcfa Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 15:59:13 +0200 Subject: [PATCH 26/58] Add inp_mouseold for warped mouse input --- src/engine/client/backend_sdl.cpp | 3 +++ src/engine/shared/config_variables.h | 1 + src/game/client/components/menus.h | 3 ++- src/game/client/components/menus_settings.cpp | 22 ++++++++++++++++--- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 880f0ced9..99153e341 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -636,6 +636,9 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt // Might fix problems with Windows HighDPI scaling SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1"); + if(g_Config.m_InpMouseOld) + SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); + m_pWindow = SDL_CreateWindow( pName, SDL_WINDOWPOS_CENTERED_DISPLAY(g_Config.m_GfxScreen), diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 6e5a64bfd..4fe21acc1 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -129,6 +129,7 @@ MACRO_CONFIG_INT(GfxQuadAsTriangle, gfx_quad_as_triangle, 1, 0, 1, CFGFLAG_SAVE| #endif MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity") +MACRO_CONFIG_INT(InpMouseOld, inp_mouseold, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use old mouse mode (warp mouse instead of raw input)") MACRO_CONFIG_INT(InpIgnoredModifiers, inp_ignored_modifiers, 0, 0, 65536, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Ignored keyboard modifier mask") MACRO_CONFIG_STR(SvName, sv_name, 128, "unnamed server", CFGFLAG_SERVER, "Server name") diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index cf910d8a2..041bd077b 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -129,6 +129,7 @@ class CMenus : public CComponent bool m_NeedRestartGraphics; bool m_NeedRestartSound; bool m_NeedRestartUpdate; + bool m_NeedRestartDDNet; bool m_NeedSendinfo; bool m_NeedSendDummyinfo; int m_SettingPlayerPage; @@ -380,7 +381,7 @@ private: void RenderGhost(CUIRect MainView); // found in menus_settings.cpp - void RenderSettingsDDRace(CUIRect MainView); + void RenderSettingsDDNet(CUIRect MainView); void RenderSettingsHUD(CUIRect MainView); }; #endif diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 89ebfb044..48a85f710 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -1274,7 +1274,7 @@ void CMenus::RenderSettings(CUIRect MainView) else if(s_SettingsPage == 7) RenderSettingsSound(MainView); else if(s_SettingsPage == 8) - RenderSettingsDDRace(MainView); + RenderSettingsDDNet(MainView); if(m_NeedRestartUpdate) { @@ -1282,7 +1282,7 @@ void CMenus::RenderSettings(CUIRect MainView) UI()->DoLabelScaled(&RestartWarning, Localize("DDNet Client needs to be restarted to complete update!"), 14.0f, -1); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f); } - else if(m_NeedRestartSkins || m_NeedRestartGraphics || m_NeedRestartSound) + else if(m_NeedRestartSkins || m_NeedRestartGraphics || m_NeedRestartSound || m_NeedRestartDDNet) UI()->DoLabelScaled(&RestartWarning, Localize("You must restart the game for all settings to take effect."), 14.0f, -1); } void CMenus::RenderSettingsHUD(CUIRect MainView) @@ -1727,10 +1727,13 @@ void CMenus::RenderSettingsHUD(CUIRect MainView) g_Config.m_ClReconnectTimeout = 5;*/ } -void CMenus::RenderSettingsDDRace(CUIRect MainView) +void CMenus::RenderSettingsDDNet(CUIRect MainView) { CUIRect Button, Left, Right, LeftLeft, Demo, Gameplay, Miscellaneous, Label, Background; + bool CheckSettings = false; + static int s_InpMouseOld = g_Config.m_InpMouseOld; + MainView.HSplitTop(100.0f, &Demo , &MainView); Demo.HSplitTop(30.0f, &Label, &Demo); @@ -1868,6 +1871,19 @@ void CMenus::RenderSettingsDDRace(CUIRect MainView) } Left.HSplitTop(20.0f, &Button, &Left); + if(DoButton_CheckBox(&g_Config.m_InpMouseOld, Localize("Old mouse mode"), g_Config.m_InpMouseOld, &Button)) + { + g_Config.m_InpMouseOld ^= 1; + CheckSettings = true; + } + + if(CheckSettings) + { + if(s_InpMouseOld == g_Config.m_InpMouseOld) + m_NeedRestartDDNet = false; + else + m_NeedRestartDDNet = true; + } CUIRect aRects[2]; Left.HSplitTop(5.0f, &Button, &Left); From 340c4d2398a17b36c7ddd697d84f5ce4bc020784 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 15:59:40 +0200 Subject: [PATCH 27/58] Leave it up to the WM where to position windows --- src/engine/client/backend_sdl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 99153e341..f67d54235 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -641,8 +641,8 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt m_pWindow = SDL_CreateWindow( pName, - SDL_WINDOWPOS_CENTERED_DISPLAY(g_Config.m_GfxScreen), - SDL_WINDOWPOS_CENTERED_DISPLAY(g_Config.m_GfxScreen), + SDL_WINDOWPOS_UNDEFINED_DISPLAY(g_Config.m_GfxScreen), + SDL_WINDOWPOS_UNDEFINED_DISPLAY(g_Config.m_GfxScreen), *pWidth, *pHeight, SdlFlags); @@ -750,8 +750,8 @@ bool CGraphicsBackend_SDL_OpenGL::SetWindowScreen(int Index) if(SDL_GetDisplayBounds(Index, &ScreenPos) == 0) { SDL_SetWindowPosition(m_pWindow, - SDL_WINDOWPOS_CENTERED_DISPLAY(Index), - SDL_WINDOWPOS_CENTERED_DISPLAY(Index)); + SDL_WINDOWPOS_UNDEFINED_DISPLAY(Index), + SDL_WINDOWPOS_UNDEFINED_DISPLAY(Index)); return true; } } From 25fda2751c728da1c2ac8094d38a134c37cc76ba Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 15:59:58 +0200 Subject: [PATCH 28/58] Fix "vanilla skins only" setting in menu --- src/game/client/components/menus_settings.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 48a85f710..7bb232eef 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -344,6 +344,10 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) void CMenus::RenderSettingsTee(CUIRect MainView) { CUIRect Button, Label, Button2, Dummy, DummyLabel, SkinList, QuickSearch, QuickSearchClearButton; + + bool CheckSettings = false; + static int s_ClVanillaSkinsOnly = g_Config.m_ClVanillaSkinsOnly; + static bool s_InitSkinlist = true; MainView.HSplitTop(10.0f, 0, &MainView); @@ -396,7 +400,15 @@ void CMenus::RenderSettingsTee(CUIRect MainView) if(DoButton_CheckBox(&g_Config.m_ClVanillaSkinsOnly, Localize("Vanilla Skins only"), g_Config.m_ClVanillaSkinsOnly, &DummyLabel)) { g_Config.m_ClVanillaSkinsOnly ^= 1; - m_NeedRestartSkins = true; + CheckSettings = true; + } + + if(CheckSettings) + { + if(s_ClVanillaSkinsOnly == g_Config.m_ClVanillaSkinsOnly) + m_NeedRestartSkins = false; + else + m_NeedRestartSkins = true; } Dummy.HSplitTop(20.0f, &DummyLabel, &Dummy); From bfcf0c4067d79da2dbf3cd8d20fb7154d1d215b3 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 16:12:23 +0200 Subject: [PATCH 29/58] Fix auto reconnect abortion --- src/game/client/components/menus.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 2e5923d4c..7c9ab71b0 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1597,7 +1597,11 @@ int CMenus::Render() static int s_Button = 0; if(DoButton_Menu(&s_Button, pButtonText, 0, &Part) || m_EscapePressed || m_EnterPressed) + { + if(m_Popup == POPUP_DISCONNECTED && Client()->m_ReconnectTime > 0) + Client()->m_ReconnectTime = 0; m_Popup = POPUP_NONE; + } } if(m_Popup == POPUP_NONE) From 4631a7cfa60b0b92a09a8040dead6db3421b7596 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 16:35:31 +0200 Subject: [PATCH 30/58] Try to enable HighDPI (untested) --- src/engine/client/backend_sdl.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index f67d54235..93d119648 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -602,7 +602,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt } // set flags - int SdlFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN; + int SdlFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI; #if defined(SDL_VIDEO_DRIVER_X11) if(Flags&IGraphicsBackend::INITFLAG_RESIZABLE) SdlFlags |= SDL_WINDOW_RESIZABLE; @@ -633,9 +633,6 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } - // Might fix problems with Windows HighDPI scaling - SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1"); - if(g_Config.m_InpMouseOld) SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); @@ -654,7 +651,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt return -1; } - SDL_GetWindowSize(m_pWindow, pWidth, pHeight); + SetWindowScreen(g_Config.m_GfxScreen); m_GLContext = SDL_GL_CreateContext(m_pWindow); @@ -664,9 +661,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt return -1; } - SDL_ShowWindow(m_pWindow); - - SetWindowScreen(g_Config.m_GfxScreen); + SDL_GL_GetDrawableSize(m_pWindow, pWidth, pHeight); SDL_GL_SetSwapInterval(Flags&IGraphicsBackend::INITFLAG_VSYNC ? 1 : 0); @@ -750,8 +745,8 @@ bool CGraphicsBackend_SDL_OpenGL::SetWindowScreen(int Index) if(SDL_GetDisplayBounds(Index, &ScreenPos) == 0) { SDL_SetWindowPosition(m_pWindow, - SDL_WINDOWPOS_UNDEFINED_DISPLAY(Index), - SDL_WINDOWPOS_UNDEFINED_DISPLAY(Index)); + SDL_WINDOWPOS_CENTERED_DISPLAY(Index), + SDL_WINDOWPOS_CENTERED_DISPLAY(Index)); return true; } } From 9f08b68a01dc4f5e7fd920ccb02e2fc333445a32 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 16:41:46 +0200 Subject: [PATCH 31/58] Info.plist entry for High DPI on Mac --- scripts/make_release.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/make_release.py b/scripts/make_release.py index 6829c01a7..5798be787 100644 --- a/scripts/make_release.py +++ b/scripts/make_release.py @@ -156,6 +156,8 @@ if use_bundle: %s CFBundleIdentifier org.DDNetClient.app + NSHighResolutionCapable + """ % (version)) From 9bd30ce4472fbb0abf7cdd48603da6fd1c8017ea Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 17:47:05 +0200 Subject: [PATCH 32/58] Make high-dpi screen support optional --- src/engine/client/backend_sdl.cpp | 7 ++++++- src/engine/client/graphics_threaded.cpp | 1 + src/engine/client/graphics_threaded.h | 1 + src/engine/shared/config_variables.h | 1 + src/game/client/components/menus_settings.cpp | 11 ++++++++++- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 93d119648..cb58ba713 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -602,7 +602,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt } // set flags - int SdlFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI; + int SdlFlags = SDL_WINDOW_OPENGL; #if defined(SDL_VIDEO_DRIVER_X11) if(Flags&IGraphicsBackend::INITFLAG_RESIZABLE) SdlFlags |= SDL_WINDOW_RESIZABLE; @@ -620,6 +620,11 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt #endif } + if(Flags&IGraphicsBackend::INITFLAG_HIGHDPI) + SdlFlags |= SDL_WINDOW_ALLOW_HIGHDPI; + else + SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1"); + // set gl attributes SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if(FsaaSamples) diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 200babe32..1e5f7e372 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -787,6 +787,7 @@ int CGraphics_Threaded::IssueInit() if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN; if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC; if(g_Config.m_GfxResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE; + if(g_Config.m_GfxHighdpi) Flags |= IGraphicsBackend::INITFLAG_HIGHDPI; return m_pBackend->Init("DDNet Client", &g_Config.m_GfxScreen, &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags, &m_DesktopScreenWidth, &m_DesktopScreenHeight); } diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index bc14fba3a..adcecc887 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -318,6 +318,7 @@ public: INITFLAG_VSYNC = 2, INITFLAG_RESIZABLE = 4, INITFLAG_BORDERLESS = 8, + INITFLAG_HIGHDPI = 16, }; virtual ~IGraphicsBackend() {} diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 4fe21acc1..9f0d8211c 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -127,6 +127,7 @@ MACRO_CONFIG_INT(GfxQuadAsTriangle, gfx_quad_as_triangle, 0, 0, 0, CFGFLAG_SAVE| #else MACRO_CONFIG_INT(GfxQuadAsTriangle, gfx_quad_as_triangle, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Render quads as triangles (fixes quad coloring on some GPUs)") #endif +MACRO_CONFIG_INT(GfxHighdpi, gfx_highdpi, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Try to use high-dpi screen features") MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity") MACRO_CONFIG_INT(InpMouseOld, inp_mouseold, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use old mouse mode (warp mouse instead of raw input)") diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 7bb232eef..b42655a77 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -818,6 +818,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) static int s_GfxFsaaSamples = g_Config.m_GfxFsaaSamples; static int s_GfxTextureQuality = g_Config.m_GfxTextureQuality; static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression; + static int s_GfxHighdpi = g_Config.m_GfxHighdpi; CUIRect ModeList; MainView.VSplitLeft(300.0f, &MainView, &ModeList); @@ -937,6 +938,13 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) if(DoButton_CheckBox(&g_Config.m_GfxHighDetail, Localize("High Detail"), g_Config.m_GfxHighDetail, &Button)) g_Config.m_GfxHighDetail ^= 1; + MainView.HSplitTop(20.0f, &Button, &MainView); + if(DoButton_CheckBox(&g_Config.m_GfxHighdpi, Localize("High-DPI screen support"), g_Config.m_GfxHighdpi, &Button)) + { + g_Config.m_GfxHighdpi ^= 1; + CheckSettings = true; + } + // check if the new settings require a restart if(CheckSettings) { @@ -946,7 +954,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) s_GfxVsync == g_Config.m_GfxVsync && s_GfxFsaaSamples == g_Config.m_GfxFsaaSamples && s_GfxTextureQuality == g_Config.m_GfxTextureQuality && - s_GfxTextureCompression == g_Config.m_GfxTextureCompression) + s_GfxTextureCompression == g_Config.m_GfxTextureCompression && + s_GfxHighdpi == g_Config.m_GfxHighdpi) m_NeedRestartGraphics = false; else m_NeedRestartGraphics = true; From 1cbaa0c4efa9b9ade259fa4f2929aba317f84923 Mon Sep 17 00:00:00 2001 From: east Date: Sat, 7 May 2016 19:28:16 +0200 Subject: [PATCH 33/58] copy resendbuffer on timeout protection --- src/engine/shared/network.h | 4 +++- src/engine/shared/network_conn.cpp | 13 ++++++++++++- src/engine/shared/network_server.cpp | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 920f2297a..1fd75b113 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -220,7 +220,9 @@ public: int AckSequence() const { return m_Ack; } int SeqSequence() const { return m_Sequence; } int SecurityToken() const { return m_SecurityToken; } - void SetTimedOut(const NETADDR *pAddr, int Sequence, int Ack, SECURITY_TOKEN SecurityToken); + TStaticRingBuffer *ResendBuffer() { return &m_Buffer; }; + + void SetTimedOut(const NETADDR *pAddr, int Sequence, int Ack, SECURITY_TOKEN SecurityToken, TStaticRingBuffer *pResendBuffer); // anti spoof void DirectInit(NETADDR &Addr, SECURITY_TOKEN SecurityToken); diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index e68ef5abe..333997378 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -467,7 +467,7 @@ int CNetConnection::Update() return 0; } -void CNetConnection::SetTimedOut(const NETADDR *pAddr, int Sequence, int Ack, SECURITY_TOKEN SecurityToken) +void CNetConnection::SetTimedOut(const NETADDR *pAddr, int Sequence, int Ack, SECURITY_TOKEN SecurityToken, TStaticRingBuffer *pResendBuffer) { int64 Now = time_get(); @@ -482,5 +482,16 @@ void CNetConnection::SetTimedOut(const NETADDR *pAddr, int Sequence, int Ack, SE m_LastRecvTime = Now; m_LastUpdateTime = Now; m_SecurityToken = SecurityToken; + + // copy resend buffer m_Buffer.Init(); + while (pResendBuffer->First()) + { + CNetChunkResend *First = pResendBuffer->First(); + + CNetChunkResend *pResend = m_Buffer.Allocate(sizeof(CNetChunkResend)+First->m_DataSize); + mem_copy(pResend, First, sizeof(CNetChunkResend)+First->m_DataSize); + + pResendBuffer->PopFirst(); + } } diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index 7f994d605..93c761281 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -684,7 +684,7 @@ bool CNetServer::SetTimedOut(int ClientID, int OrigID) if (m_aSlots[ClientID].m_Connection.State() != NET_CONNSTATE_ERROR) return false; - m_aSlots[ClientID].m_Connection.SetTimedOut(ClientAddr(OrigID), m_aSlots[OrigID].m_Connection.SeqSequence(), m_aSlots[OrigID].m_Connection.AckSequence(), m_aSlots[OrigID].m_Connection.SecurityToken()); + m_aSlots[ClientID].m_Connection.SetTimedOut(ClientAddr(OrigID), m_aSlots[OrigID].m_Connection.SeqSequence(), m_aSlots[OrigID].m_Connection.AckSequence(), m_aSlots[OrigID].m_Connection.SecurityToken(), m_aSlots[OrigID].m_Connection.ResendBuffer()); m_aSlots[OrigID].m_Connection.Reset(); return true; } From 642e7f7671ec2fbf71f2025ef668c0e8b00df6b1 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 21:16:31 +0200 Subject: [PATCH 34/58] Still hide window at start (fixes fullscreen in Gnome) --- src/engine/client/backend_sdl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index cb58ba713..877717fab 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -602,7 +602,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt } // set flags - int SdlFlags = SDL_WINDOW_OPENGL; + int SdlFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN; #if defined(SDL_VIDEO_DRIVER_X11) if(Flags&IGraphicsBackend::INITFLAG_RESIZABLE) SdlFlags |= SDL_WINDOW_RESIZABLE; @@ -688,6 +688,8 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt RunBuffer(&CmdBuffer); WaitForIdle(); + SDL_ShowWindow(m_pWindow); + // return return 0; } From 461a09451d9d95fae1368fb1cc6ecaa88e927d1f Mon Sep 17 00:00:00 2001 From: def Date: Sat, 7 May 2016 23:19:46 +0200 Subject: [PATCH 35/58] Improve handling of multiple screens and missing screens --- src/engine/client/backend_sdl.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 877717fab..0fef43796 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -568,7 +568,8 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt m_NumScreens = SDL_GetNumVideoDisplays(); if(m_NumScreens > 0) { - clamp(*Screen, 0, m_NumScreens-1); + if(*Screen < 0 || *Screen >= m_NumScreens) + *Screen = 0; if(SDL_GetDisplayBounds(*Screen, &ScreenPos) != 0) { dbg_msg("gfx", "unable to retrieve screen information: %s", SDL_GetError()); @@ -643,8 +644,8 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt m_pWindow = SDL_CreateWindow( pName, - SDL_WINDOWPOS_UNDEFINED_DISPLAY(g_Config.m_GfxScreen), - SDL_WINDOWPOS_UNDEFINED_DISPLAY(g_Config.m_GfxScreen), + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, *pWidth, *pHeight, SdlFlags); @@ -656,8 +657,6 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt return -1; } - SetWindowScreen(g_Config.m_GfxScreen); - m_GLContext = SDL_GL_CreateContext(m_pWindow); if(m_GLContext == NULL) @@ -667,9 +666,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt } SDL_GL_GetDrawableSize(m_pWindow, pWidth, pHeight); - SDL_GL_SetSwapInterval(Flags&IGraphicsBackend::INITFLAG_VSYNC ? 1 : 0); - SDL_GL_MakeCurrent(NULL, NULL); // start the command processor @@ -689,6 +686,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt WaitForIdle(); SDL_ShowWindow(m_pWindow); + SetWindowScreen(g_Config.m_GfxScreen); // return return 0; From f3a406986737a4741dd6d4296d19768de139bc0d Mon Sep 17 00:00:00 2001 From: def Date: Sun, 8 May 2016 19:40:53 +0200 Subject: [PATCH 36/58] Set gfx_highdpi to 0 as default (needs someone to fix it on Win >= 8.1 and Mac) --- src/engine/shared/config_variables.h | 2 +- src/game/client/components/menus_settings.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 9f0d8211c..58fac5b1f 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -127,7 +127,7 @@ MACRO_CONFIG_INT(GfxQuadAsTriangle, gfx_quad_as_triangle, 0, 0, 0, CFGFLAG_SAVE| #else MACRO_CONFIG_INT(GfxQuadAsTriangle, gfx_quad_as_triangle, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Render quads as triangles (fixes quad coloring on some GPUs)") #endif -MACRO_CONFIG_INT(GfxHighdpi, gfx_highdpi, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Try to use high-dpi screen features") +MACRO_CONFIG_INT(GfxHighdpi, gfx_highdpi, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Try to use high-dpi screen features") MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity") MACRO_CONFIG_INT(InpMouseOld, inp_mouseold, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use old mouse mode (warp mouse instead of raw input)") diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index b42655a77..48f16a199 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -939,7 +939,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) g_Config.m_GfxHighDetail ^= 1; MainView.HSplitTop(20.0f, &Button, &MainView); - if(DoButton_CheckBox(&g_Config.m_GfxHighdpi, Localize("High-DPI screen support"), g_Config.m_GfxHighdpi, &Button)) + if(DoButton_CheckBox(&g_Config.m_GfxHighdpi, Localize("High-DPI screen support (experimental)"), g_Config.m_GfxHighdpi, &Button)) { g_Config.m_GfxHighdpi ^= 1; CheckSettings = true; From 37e822ba0f30ad4c3c00eb91a795342df521d0f7 Mon Sep 17 00:00:00 2001 From: def Date: Sun, 8 May 2016 19:41:06 +0200 Subject: [PATCH 37/58] Version 10.0.2 --- src/game/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/version.h b/src/game/version.h index 8398e7feb..a10255e30 100644 --- a/src/game/version.h +++ b/src/game/version.h @@ -3,8 +3,8 @@ #ifndef GAME_VERSION_H #define GAME_VERSION_H #include "generated/nethash.cpp" -#define GAME_VERSION "0.6.3, 10.0.1" +#define GAME_VERSION "0.6.3, 10.0.2" #define GAME_NETVERSION "0.6 626fce9a778df4d4" -static const char GAME_RELEASE_VERSION[8] = "10.0.1"; +static const char GAME_RELEASE_VERSION[8] = "10.0.2"; #define CLIENT_VERSIONNR 1000 #endif From 2fc2515e0f168ee0c3f512c9c9658425255bf26c Mon Sep 17 00:00:00 2001 From: def Date: Tue, 10 May 2016 12:40:33 +0200 Subject: [PATCH 38/58] Fix DDNet server browser to refresh only once on start, not twice --- src/engine/client/client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 0f670bf65..4efe7ce33 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1233,6 +1233,7 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) // do decompression of serverlist if (uncompress((Bytef*)aBuf, &DstLen, (Bytef*)pComp, CompLength) == Z_OK && (int)DstLen == PlainLength) { + aBuf[DstLen] = '\0'; bool ListChanged = true; IOHANDLE File = m_pStorage->OpenFile("ddnet-servers.json", IOFLAG_READ, IStorage::TYPE_SAVE); From 695bf346ac674b7685bdb223c30d29a82e6e2349 Mon Sep 17 00:00:00 2001 From: def Date: Tue, 10 May 2016 17:43:27 +0200 Subject: [PATCH 39/58] Make gfx_refresh_rate functional (fixes #255) --- src/engine/client/client.cpp | 6 ++++-- src/engine/shared/config_variables.h | 2 +- src/game/client/components/menus_settings.cpp | 9 ++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 4efe7ce33..1fed9474b 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2759,13 +2759,15 @@ void CClient::Run() m_EditorActive = false; Update(); + int64 Now = time_get(); - if((g_Config.m_GfxBackgroundRender || m_pGraphics->WindowOpen()) && (!g_Config.m_GfxAsyncRenderOld || m_pGraphics->IsIdle())) + if((g_Config.m_GfxBackgroundRender || m_pGraphics->WindowOpen()) + && (!g_Config.m_GfxAsyncRenderOld || m_pGraphics->IsIdle()) + && (!g_Config.m_GfxRefreshRate || Now >= m_LastRenderTime + time_freq() / g_Config.m_GfxRefreshRate)) { m_RenderFrames++; // update frametime - int64 Now = time_get(); m_RenderFrameTime = (Now - m_LastRenderTime) / (float)time_freq(); if(m_RenderFrameTime < m_RenderFrameTimeLow) m_RenderFrameTimeLow = m_RenderFrameTime; diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 58fac5b1f..51e160d1a 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -112,7 +112,7 @@ MACRO_CONFIG_INT(GfxHighDetail, gfx_high_detail, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_C MACRO_CONFIG_INT(GfxTextureQuality, gfx_texture_quality, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") #endif MACRO_CONFIG_INT(GfxFsaaSamples, gfx_fsaa_samples, 0, 0, 16, CFGFLAG_SAVE|CFGFLAG_CLIENT, "FSAA Samples") -MACRO_CONFIG_INT(GfxRefreshRate, gfx_refresh_rate, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen refresh rate") +MACRO_CONFIG_INT(GfxRefreshRate, gfx_refresh_rate, 0, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen refresh rate") MACRO_CONFIG_INT(GfxFinish, gfx_finish, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") MACRO_CONFIG_INT(GfxBackgroundRender, gfx_backgroundrender, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Render graphics when window is in background") MACRO_CONFIG_INT(GfxTextOverlay, gfx_text_overlay, 10, 1, 100, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Stop rendering textoverlay in editor or with entities: high value = less details = more speed") diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 48f16a199..182c2a9b6 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -804,7 +804,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) void CMenus::RenderSettingsGraphics(CUIRect MainView) { - CUIRect Button; + CUIRect Button, Label; char aBuf[128]; bool CheckSettings = false; @@ -961,6 +961,13 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView) m_NeedRestartGraphics = true; } + MainView.HSplitTop(20.0f, &Label, &MainView); + Label.VSplitLeft(130.0f, &Label, &Button); + str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Refresh Rate"), g_Config.m_GfxRefreshRate); + UI()->DoLabelScaled(&Label, aBuf, 14.0f, -1); + Button.HMargin(2.0f, &Button); + g_Config.m_GfxRefreshRate = static_cast(DoScrollbarH(&g_Config.m_GfxRefreshRate, &Button, g_Config.m_GfxRefreshRate/1000.0f)*1000.0f+0.1f); + CUIRect Text; MainView.HSplitTop(20.0f, 0, &MainView); MainView.HSplitTop(20.0f, &Text, &MainView); From 03a48dd09f932371674af088e30c4b669069fe48 Mon Sep 17 00:00:00 2001 From: def Date: Wed, 11 May 2016 12:13:54 +0200 Subject: [PATCH 40/58] Add code to remove unused tiles on game and front layers (commented out) --- src/game/editor/io.cpp | 115 +++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/src/game/editor/io.cpp b/src/game/editor/io.cpp index e1797da53..2d707da01 100644 --- a/src/game/editor/io.cpp +++ b/src/game/editor/io.cpp @@ -877,50 +877,6 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag if(pTilemapItem->m_Version >= 3) IntsToStr(pTilemapItem->m_aName, sizeof(pTiles->m_aName)/sizeof(int), pTiles->m_aName); - if (Size >= pTiles->m_Width*pTiles->m_Height*sizeof(CTile)) - { - mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile)); - - if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem)) - { - for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) - { - if(pTiles->m_pTiles[i].m_Index) - pTiles->m_pTiles[i].m_Index += ENTITY_OFFSET; - } - } - - // Convert race stoppers to ddrace stoppers - /*if(pTiles->m_Game) - { - for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) - { - if(pTiles->m_pTiles[i].m_Index == 29) - { - pTiles->m_pTiles[i].m_Index = 60; - pTiles->m_pTiles[i].m_Flags = TILEFLAG_HFLIP|TILEFLAG_VFLIP|TILEFLAG_ROTATE; - } - else if(pTiles->m_pTiles[i].m_Index == 30) - { - pTiles->m_pTiles[i].m_Index = 60; - pTiles->m_pTiles[i].m_Flags = TILEFLAG_ROTATE; - } - else if(pTiles->m_pTiles[i].m_Index == 31) - { - pTiles->m_pTiles[i].m_Index = 60; - pTiles->m_pTiles[i].m_Flags = TILEFLAG_HFLIP|TILEFLAG_VFLIP; - } - else if(pTiles->m_pTiles[i].m_Index == 32) - { - pTiles->m_pTiles[i].m_Index = 60; - pTiles->m_pTiles[i].m_Flags = 0; - } - } - }*/ - } - - DataFile.UnloadData(pTilemapItem->m_Data); - if(pTiles->m_Tele) { void *pTeleData = DataFile.GetData(pTilemapItem->m_Tele); @@ -1083,6 +1039,77 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag } DataFile.UnloadData(pTilemapItem->m_Tune); } + else // regular tile layer or game layer + { + if (Size >= pTiles->m_Width*pTiles->m_Height*sizeof(CTile)) + { + mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile)); + + if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem)) + { + for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) + { + if(pTiles->m_pTiles[i].m_Index) + pTiles->m_pTiles[i].m_Index += ENTITY_OFFSET; + } + } + } + } + + DataFile.UnloadData(pTilemapItem->m_Data); + + // Remove unused tiles on game and front layers + /*if(pTiles->m_Game) + { + for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) + { + if(!IsValidGameTile(pTiles->m_pTiles[i].m_Index)) + { + pTiles->m_pTiles[i].m_Index = 0; + pTiles->m_pTiles[i].m_Flags = 0; + } + } + } + if(pTiles->m_Front) + { + for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) + { + if(!IsValidFrontTile(pTiles->m_pTiles[i].m_Index)) + { + pTiles->m_pTiles[i].m_Index = 0; + pTiles->m_pTiles[i].m_Flags = 0; + } + } + }*/ + + // Convert race stoppers to ddrace stoppers + /*if(pTiles->m_Game) + { + for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++) + { + if(pTiles->m_pTiles[i].m_Index == 29) + { + pTiles->m_pTiles[i].m_Index = 60; + pTiles->m_pTiles[i].m_Flags = TILEFLAG_HFLIP|TILEFLAG_VFLIP|TILEFLAG_ROTATE; + } + else if(pTiles->m_pTiles[i].m_Index == 30) + { + pTiles->m_pTiles[i].m_Index = 60; + pTiles->m_pTiles[i].m_Flags = TILEFLAG_ROTATE; + } + else if(pTiles->m_pTiles[i].m_Index == 31) + { + pTiles->m_pTiles[i].m_Index = 60; + pTiles->m_pTiles[i].m_Flags = TILEFLAG_HFLIP|TILEFLAG_VFLIP; + } + else if(pTiles->m_pTiles[i].m_Index == 32) + { + pTiles->m_pTiles[i].m_Index = 60; + pTiles->m_pTiles[i].m_Flags = 0; + } + } + }*/ + } else if(pLayerItem->m_Type == LAYERTYPE_QUADS) { From b7d4beccea7d67258dbad6cad35c630f9e9347be Mon Sep 17 00:00:00 2001 From: def Date: Wed, 11 May 2016 17:51:22 +0200 Subject: [PATCH 41/58] Fix buffer overflow when pasting text (thanks to Im 'corneum) --- src/game/client/components/menus.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 7c9ab71b0..e71430164 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -244,9 +244,9 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS const char *Text = Input()->GetClipboardText(); if(Text) { - int CharsLeft = StrSize - str_length(pStr); int Offset = str_length(pStr); - for(int i = 0; i < str_length(Text) && i <= CharsLeft; i++) + int CharsLeft = StrSize - Offset - 1; + for(int i = 0; i < str_length(Text) && i < CharsLeft; i++) { if(Text[i] == '\n') pStr[i + Offset] = ' '; From b0b277469529fdccf420cfadcee0ca1d15be520b Mon Sep 17 00:00:00 2001 From: def Date: Wed, 11 May 2016 18:00:27 +0200 Subject: [PATCH 42/58] Clean up other paste code a bit --- src/game/client/components/chat.cpp | 8 ++------ src/game/client/components/console.cpp | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 4aaf0fc9a..8d61d8cb9 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -127,18 +127,14 @@ bool CChat::OnInput(IInput::CEvent Event) { if(Text[i] == '\n') { - int max = i - Begin + 1; - if(max > (int)sizeof(Line)) - max = sizeof(Line); + int max = min(i - Begin + 1, (int)sizeof(Line)); str_copy(Line, Text + Begin, max); Begin = i+1; SayChat(Line); while(Text[i] == '\n') i++; } } - int max = i - Begin + 1; - if(max > (int)sizeof(Line)) - max = sizeof(Line); + int max = min(i - Begin + 1, (int)sizeof(Line)); str_copy(Line, Text + Begin, max); Begin = i+1; m_Input.Add(Line); diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index 9ff64154b..21b72a252 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -108,17 +108,13 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event) Begin++; continue; } - int max = i - Begin + 1; - if(max > (int)sizeof(Line)) - max = sizeof(Line); + int max = min(i - Begin + 1, (int)sizeof(Line)); str_copy(Line, Text + Begin, max); Begin = i+1; ExecuteLine(Line); } } - int max = i - Begin + 1; - if(max > (int)sizeof(Line)) - max = sizeof(Line); + int max = min(i - Begin + 1, (int)sizeof(Line)); str_copy(Line, Text + Begin, max); Begin = i+1; m_Input.Add(Line); From ff747953b46298f1f894ccdccbce58a7ed2542fd Mon Sep 17 00:00:00 2001 From: def Date: Sat, 14 May 2016 00:42:40 +0200 Subject: [PATCH 43/58] Make envelopes unsynchronized by default and explain the setting better (fixes #479) --- src/game/editor/editor.cpp | 2 +- src/game/editor/editor.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index d0befc2db..bd965a2b0 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -4393,7 +4393,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) ToolBar.VSplitLeft(15.0f, &Button, &ToolBar); ToolBar.VSplitLeft(12.0f, &Button, &ToolBar); static int s_SyncButton; - if(DoButton_Editor(&s_SyncButton, pEnvelope->m_Synchronized?"X":"", 0, &Button, 0, "Enable envelope synchronization between clients")) + if(DoButton_Editor(&s_SyncButton, pEnvelope->m_Synchronized?"X":"", 0, &Button, 0, "Synchronize envelope animation to game time (restarts when you touch the start line)")) pEnvelope->m_Synchronized = !pEnvelope->m_Synchronized; ToolBar.VSplitLeft(4.0f, &Button, &ToolBar); diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 73a35414d..12b2ddd31 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -61,7 +61,7 @@ public: m_aName[0] = 0; m_Bottom = 0; m_Top = 0; - m_Synchronized = true; + m_Synchronized = false; } void Resort() From d1275f239a8843a9963b668cc1151294f6dda8c4 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 14 May 2016 01:17:18 +0200 Subject: [PATCH 44/58] cl_show_ids also shows ID in chat (fixes #454) --- src/game/client/components/chat.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 8d61d8cb9..6e2775485 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -666,12 +666,26 @@ void CChat::OnRender() if(Now > m_aLines[r].m_Time+16*time_freq() && !m_Show) break; + char aName[64] = ""; + if(g_Config.m_ClShowIDs && m_aLines[r].m_ClientID != -1 && m_aLines[r].m_aName[0] != '\0') + { + if (m_aLines[r].m_ClientID >= 10) + str_format(aName, sizeof(aName),"%d: ", m_aLines[r].m_ClientID); + else + str_format(aName, sizeof(aName)," %d: ", m_aLines[r].m_ClientID); + str_append(aName, m_aLines[r].m_aName,sizeof(aName)); + } + else + { + str_copy(aName, m_aLines[r].m_aName, sizeof(aName)); + } + // get the y offset (calculate it if we haven't done that yet) if(m_aLines[r].m_YOffset[OffsetType] < 0.0f) { TextRender()->SetCursor(&Cursor, Begin, 0.0f, FontSize, 0); Cursor.m_LineWidth = LineWidth; - TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1); + TextRender()->TextEx(&Cursor, aName, -1); TextRender()->TextEx(&Cursor, m_aLines[r].m_aText, -1); m_aLines[r].m_YOffset[OffsetType] = Cursor.m_Y + Cursor.m_FontSize; } @@ -710,7 +724,7 @@ void CChat::OnRender() else TextRender()->TextColor(0.8f, 0.8f, 0.8f, Blend); - TextRender()->TextEx(&Cursor, m_aLines[r].m_aName, -1); + TextRender()->TextEx(&Cursor, aName, -1); // render line if (m_aLines[r].m_ClientID == -1) From d6ca9dcb7b145d31a1fa5e5e0f6e96d48ec48c40 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 14 May 2016 01:17:51 +0200 Subject: [PATCH 45/58] Version 10.0.3 --- src/game/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/version.h b/src/game/version.h index a10255e30..a924772d9 100644 --- a/src/game/version.h +++ b/src/game/version.h @@ -3,8 +3,8 @@ #ifndef GAME_VERSION_H #define GAME_VERSION_H #include "generated/nethash.cpp" -#define GAME_VERSION "0.6.3, 10.0.2" +#define GAME_VERSION "0.6.3, 10.0.3" #define GAME_NETVERSION "0.6 626fce9a778df4d4" -static const char GAME_RELEASE_VERSION[8] = "10.0.2"; +static const char GAME_RELEASE_VERSION[8] = "10.0.3"; #define CLIENT_VERSIONNR 1000 #endif From 475df1413496703be8504f956b296452b76d09ef Mon Sep 17 00:00:00 2001 From: def Date: Sat, 14 May 2016 15:16:52 +0200 Subject: [PATCH 46/58] Fix editor popups a bit --- src/game/editor/editor.cpp | 4 ++-- src/game/editor/popups.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index bd965a2b0..51a9759e4 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -1196,7 +1196,7 @@ void CEditor::DoToolbar(CUIRect ToolBar) if(DoButton_Ex(&s_SpeedupButton, "Speedup", (pS && pS->m_Speedup)?0:-1, &Button, 0, "Speedup", CUI::CORNER_ALL)) { static int s_SpeedupPopupID = 0; - UiInvokePopupMenu(&s_SpeedupPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 53, PopupSpeedup); + UiInvokePopupMenu(&s_SpeedupPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 48, PopupSpeedup); } // do switch button TB_Bottom.VSplitLeft(5.0f, &Button, &TB_Bottom); @@ -1214,7 +1214,7 @@ void CEditor::DoToolbar(CUIRect ToolBar) if(DoButton_Ex(&s_TuneButton, "Tune", (pS && pS->m_Tune)?0:-1, &Button, 0, "Tune", CUI::CORNER_ALL)) { static int s_TunePopupID = 0; - UiInvokePopupMenu(&s_TunePopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 90, PopupTune); + UiInvokePopupMenu(&s_TunePopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 23, PopupTune); } } diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 0690029d5..61ae7d4d3 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -1470,14 +1470,14 @@ int CEditor::PopupSwitch(CEditor *pEditor, CUIRect View) enum { - PROP_SwitchNumber=0, - PROP_SwitchDelay, + PROP_SwitchDelay=0, + PROP_SwitchNumber, NUM_PROPS, }; CProperty aProps[] = { - {"Number", pEditor->m_SwitchNum, PROPTYPE_INT_STEP, 0, 255}, {"Delay", pEditor->m_SwitchDelay, PROPTYPE_INT_STEP, 0, 255}, + {"Number", pEditor->m_SwitchNum, PROPTYPE_INT_STEP, 0, 255}, {0}, }; From d2f57140422a69813211f6e06cecd78936f95191 Mon Sep 17 00:00:00 2001 From: def Date: Sun, 15 May 2016 00:06:32 +0200 Subject: [PATCH 47/58] Sort file names case-insensitively --- src/game/client/components/menus.h | 4 ++-- src/game/editor/editor.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 041bd077b..ad17ae77f 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -186,13 +186,13 @@ class CMenus : public CComponent { return !str_comp(m_aFilename, "..") ? true : !str_comp(Other.m_aFilename, "..") ? false : m_IsDir && !Other.m_IsDir ? true : !m_IsDir && Other.m_IsDir ? false : - str_comp_filenames(m_aFilename, Other.m_aFilename) < 0; + str_comp_nocase(m_aFilename, Other.m_aFilename) < 0; } else { return !str_comp(m_aFilename, "..") ? true : !str_comp(Other.m_aFilename, "..") ? false : m_IsDir && !Other.m_IsDir ? true : !m_IsDir && Other.m_IsDir ? false : - str_comp_filenames(m_aFilename, Other.m_aFilename) > 0; + str_comp_nocase(m_aFilename, Other.m_aFilename) > 0; } } } diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 12b2ddd31..8df78d755 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -831,7 +831,7 @@ public: bool operator<(const CFilelistItem &Other) { return !str_comp(m_aFilename, "..") ? true : !str_comp(Other.m_aFilename, "..") ? false : m_IsDir && !Other.m_IsDir ? true : !m_IsDir && Other.m_IsDir ? false : - str_comp_filenames(m_aFilename, Other.m_aFilename) < 0; } + str_comp_nocase(m_aFilename, Other.m_aFilename) < 0; } }; sorted_array m_FileList; int m_FilesStartAt; From 434b9345d8ffbd79be5b03da301c9e812255d72d Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Sat, 14 May 2016 16:21:56 +0200 Subject: [PATCH 48/58] automatically add linebreaks in broadcasts --- src/game/client/components/broadcast.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index 8225cd8fd..db0163b33 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -28,7 +28,7 @@ void CBroadcast::OnRender() if(time_get() < m_BroadcastTime) { CTextCursor Cursor; - TextRender()->SetCursor(&Cursor, m_BroadcastRenderOffset, 40.0f, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); + TextRender()->SetCursor(&Cursor, m_BroadcastRenderOffset, 40.0f, 12.0f, TEXTFLAG_RENDER); Cursor.m_LineWidth = 300*Graphics()->ScreenAspect()-m_BroadcastRenderOffset; TextRender()->TextEx(&Cursor, m_aBroadcastText, -1); } From aeadffa585db49009b5c160e1dee7c7bd3c23deb Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Sun, 15 May 2016 10:15:39 +0200 Subject: [PATCH 49/58] calculate type height in ddnet browser type filter --- src/game/client/components/menus_browser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 2fa7c97ea..34d134a5c 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -683,11 +683,11 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) int NumTypes = ServerBrowser()->NumDDNetTypes(); int PerLine = 3; - if(MaxTypes <= 12) - ServerFilter.HSplitTop(8.0f, 0, &ServerFilter); + ServerFilter.HSplitTop(4.0f, 0, &ServerFilter); + ServerFilter.HSplitBottom(4.0f, &ServerFilter, 0); const float TypesWidth = 40.0f; - const float TypesHeight = MaxTypes > 12 ? 15.0f : 20.0f; + const float TypesHeight = ServerFilter.h / ceil(MaxTypes / (float)PerLine); CUIRect TypesRect, Left, Right; From bb634d76410f7d259e10f06cd26b323fb022fcdf Mon Sep 17 00:00:00 2001 From: def Date: Tue, 17 May 2016 18:56:33 +0200 Subject: [PATCH 50/58] Reconnect to last server address, not the one selected in browser --- src/engine/client/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 1fed9474b..c58449844 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2480,7 +2480,7 @@ void CClient::Update() if(m_ReconnectTime > 0 && time_get() > m_ReconnectTime) { - Connect(g_Config.m_UiServerAddress); + Connect(m_aServerAddressStr); m_ReconnectTime = 0; } } From 1645310750ebbb4a5aa02a570248e97cc72ab2fd Mon Sep 17 00:00:00 2001 From: def Date: Tue, 17 May 2016 23:44:57 +0200 Subject: [PATCH 51/58] Keep reading packets after invalid control packet --- src/engine/shared/network_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index 93c761281..850dece93 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -596,7 +596,7 @@ int CNetServer::Recv(CNetChunk *pChunk) // drop invalid ctrl packets if (m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL && m_RecvUnpacker.m_Data.m_DataSize == 0) - return 0; + continue; // normal packet, find matching slot int Slot = GetClientSlot(Addr); From dae855ee9fc89e502b45ddcdec0a93f731b639a0 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Thu, 19 May 2016 15:51:03 +0200 Subject: [PATCH 52/58] clear ddnet filter strings before appending --- src/engine/client/serverbrowser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index dbbcf4374..9c46ae1eb 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -1066,6 +1066,7 @@ bool CServerBrowser::DDNetFiltered(char *pFilter, const char *pName) void CServerBrowser::DDNetCountryFilterClean() { char aNewList[128]; + mem_zero(aNewList, sizeof(aNewList)); for(int i = 0; i < m_NumDDNetCountries; i++) { @@ -1084,6 +1085,7 @@ void CServerBrowser::DDNetCountryFilterClean() void CServerBrowser::DDNetTypeFilterClean() { char aNewList[128]; + mem_zero(aNewList, sizeof(aNewList)); for(int i = 0; i < m_NumDDNetTypes; i++) { From 96bcedec29fa986b785c19115ad0e37d11ac2d18 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Thu, 19 May 2016 15:54:52 +0200 Subject: [PATCH 53/58] just set first char of ddnet filter to zero --- src/engine/client/serverbrowser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 9c46ae1eb..f4cad201d 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -1066,7 +1066,7 @@ bool CServerBrowser::DDNetFiltered(char *pFilter, const char *pName) void CServerBrowser::DDNetCountryFilterClean() { char aNewList[128]; - mem_zero(aNewList, sizeof(aNewList)); + aNewList[0] = '\0'; for(int i = 0; i < m_NumDDNetCountries; i++) { @@ -1085,7 +1085,7 @@ void CServerBrowser::DDNetCountryFilterClean() void CServerBrowser::DDNetTypeFilterClean() { char aNewList[128]; - mem_zero(aNewList, sizeof(aNewList)); + aNewList[0] = '\0'; for(int i = 0; i < m_NumDDNetTypes; i++) { From fa95256de66fab732cea793735be11a517b9f142 Mon Sep 17 00:00:00 2001 From: def Date: Thu, 19 May 2016 20:14:22 +0200 Subject: [PATCH 54/58] Fix Debian installation instructions (fixes #491) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11d1c81f9..6ca7f1e09 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ To compile DDNet yourself, you can follow the [instructions for compiling Teewor DDNet requires additional libraries, that are bundled for the most common platforms (Windows, Mac, Linux, all x86 and x86_64). Instead you can install these libraries on your system, remove the `config.lua` and `bam` should use the system-wide libraries by default. You can install all required dependencies on Debian and Ubuntu like this: - apt-get install libsdl2-2.0-dev libfreetype6-dev libcurl4-openssl-dev libogg-dev libopus-dev libopusfile-dev + apt-get install libsdl2-dev libfreetype6-dev libcurl4-openssl-dev libogg-dev libopus-dev libopusfile-dev If you have the libraries installed, but still want to use the bundled ones instead, you can specify so by running `bam config curl.use_pkgconfig=false opus.use_pkgconfig=false opusfile.use_pkgconfig=false ogg.use_pkgconfig=false`. From 22ad56486ae5db5ef3611d580c7b92f8e2a634b7 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Thu, 19 May 2016 21:53:01 +0200 Subject: [PATCH 55/58] revert automatically add linebreaks in broadcasts --- src/game/client/components/broadcast.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index db0163b33..8225cd8fd 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -28,7 +28,7 @@ void CBroadcast::OnRender() if(time_get() < m_BroadcastTime) { CTextCursor Cursor; - TextRender()->SetCursor(&Cursor, m_BroadcastRenderOffset, 40.0f, 12.0f, TEXTFLAG_RENDER); + TextRender()->SetCursor(&Cursor, m_BroadcastRenderOffset, 40.0f, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = 300*Graphics()->ScreenAspect()-m_BroadcastRenderOffset; TextRender()->TextEx(&Cursor, m_aBroadcastText, -1); } From ede6a9f93f2828462762b9cfad3ff640c636e5c7 Mon Sep 17 00:00:00 2001 From: def Date: Fri, 20 May 2016 18:28:33 +0200 Subject: [PATCH 56/58] More uniform /times output (thanks Soreu) --- src/game/server/score/sql_score.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/server/score/sql_score.cpp b/src/game/server/score/sql_score.cpp index 1c31ec0d6..f4f429a2a 100644 --- a/src/game/server/score/sql_score.cpp +++ b/src/game/server/score/sql_score.cpp @@ -1140,16 +1140,16 @@ void CSqlScore::ShowTimesThread(void *pUser) if(pData->m_Search) // last 5 times of a player { if(pStamp == 0) // stamp is 00:00:00 cause it's an old entry from old times where there where no stamps yet - str_format(aBuf, sizeof(aBuf), "%d min %.2f sec, don't know how long ago", (int)(pTime/60), pTime-((int)pTime/60*60)); + str_format(aBuf, sizeof(aBuf), "%02d:%05.02f, don't know how long ago", (int)(pTime/60), pTime-((int)pTime/60*60)); else - str_format(aBuf, sizeof(aBuf), "%s ago, %d min %.2f sec", pAgoString,(int)(pTime/60), pTime-((int)pTime/60*60)); + str_format(aBuf, sizeof(aBuf), "%s ago, %02d:%05.02f", pAgoString, (int)(pTime/60), pTime-((int)pTime/60*60)); } else // last 5 times of the server { if(pStamp == 0) // stamp is 00:00:00 cause it's an old entry from old times where there where no stamps yet - str_format(aBuf, sizeof(aBuf), "%s, %02d:%05.02f s, don't know when", pData->m_pSqlData->m_pResults->getString("Name").c_str(), (int)(pTime/60), pTime-((int)pTime/60*60)); + str_format(aBuf, sizeof(aBuf), "%s, %02d:%05.02f, don't know when", pData->m_pSqlData->m_pResults->getString("Name").c_str(), (int)(pTime/60), pTime-((int)pTime/60*60)); else - str_format(aBuf, sizeof(aBuf), "%s, %s ago, %02d:%05.02f s", pData->m_pSqlData->m_pResults->getString("Name").c_str(), pAgoString, (int)(pTime/60), pTime-((int)pTime/60*60)); + str_format(aBuf, sizeof(aBuf), "%s, %s ago, %02d:%05.02f", pData->m_pSqlData->m_pResults->getString("Name").c_str(), pAgoString, (int)(pTime/60), pTime-((int)pTime/60*60)); } pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); } From aff85462aac89ec0474ab624a276397633004920 Mon Sep 17 00:00:00 2001 From: def Date: Fri, 20 May 2016 18:36:32 +0200 Subject: [PATCH 57/58] Update messages a bit --- src/game/client/components/menus_browser.cpp | 2 +- src/game/server/ddracechat.cpp | 12 +++++------- src/game/server/gamecontext.cpp | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 34d134a5c..097f5e084 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1310,7 +1310,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView) char aBuf[64]; if(str_comp(Client()->LatestVersion(), "0") != 0) { - str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out! Download it at ddnet.tw!"), Client()->LatestVersion()); + str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out! Download it at DDNet.tw!"), Client()->LatestVersion()); TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f); } else diff --git a/src/game/server/ddracechat.cpp b/src/game/server/ddracechat.cpp index 8cc44c675..a57c5ba50 100644 --- a/src/game/server/ddracechat.cpp +++ b/src/game/server/ddracechat.cpp @@ -18,9 +18,9 @@ void CGameContext::ConCredits(IConsole::IResult *pResult, void *pUserData) CGameContext *pSelf = (CGameContext *) pUserData; pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "credit", - "DDRaceNetwork is maintained by deen."); + "DDNet is run by the DDNet staff (DDNet.tw/staff)"); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "credit", - "Many ideas from the great community,"); + "Great maps and many ideas from the great community"); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "credit", "Help and code by eeeee, HMH, east, CookieMichal, Learath2,"); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "credit", @@ -33,8 +33,6 @@ void CGameContext::ConCredits(IConsole::IResult *pResult, void *pUserData) "Based on DDRace by the DDRace developers,"); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "credit", "which is a mod of Teeworlds by the Teeworlds developers."); - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "credit", - "Check the changes on ddnet.tw"); } void CGameContext::ConInfo(IConsole::IResult *pResult, void *pUserData) @@ -47,11 +45,11 @@ void CGameContext::ConInfo(IConsole::IResult *pResult, void *pUserData) "Git revision hash: " GIT_SHORTREV_HASH); #endif pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "info", - "Official site: ddnet.tw"); + "Official site: DDNet.tw"); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "info", - "For more Info /cmdlist"); + "For more info: /cmdlist"); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "info", - "Or visit ddnet.tw"); + "Or visit DDNet.tw"); } void CGameContext::ConHelp(IConsole::IResult *pResult, void *pUserData) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 5eafd0e5e..7fe01b815 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -919,7 +919,7 @@ void CGameContext::OnClientEnter(int ClientID) SendChat(-1, CGameContext::CHAT_ALL, aBuf); SendChatTarget(ClientID, "DDraceNetwork Mod. Version: " GAME_VERSION); - SendChatTarget(ClientID, "please visit https://ddnet.tw or say /info for more info"); + SendChatTarget(ClientID, "please visit DDNet.tw or say /info for more info"); if(g_Config.m_SvWelcome[0]!=0) SendChatTarget(ClientID,g_Config.m_SvWelcome); @@ -930,7 +930,7 @@ void CGameContext::OnClientEnter(int ClientID) if (g_Config.m_SvShowOthersDefault) { if (g_Config.m_SvShowOthers) - SendChatTarget(ClientID, "You can see other players. To disable this use the DDNet client and type /showothers ."); + SendChatTarget(ClientID, "You can see other players. To disable this use DDNet client and type /showothers ."); m_apPlayers[ClientID]->m_ShowOthers = true; } From 3c54f443b2c019657e6a155dc49a8e5cf817959b Mon Sep 17 00:00:00 2001 From: def Date: Fri, 20 May 2016 20:05:47 +0200 Subject: [PATCH 58/58] Make sv_join_vote_delay work for /map votes and make the number of seconds configurable --- src/game/server/gamecontext.cpp | 2 +- src/game/server/player.cpp | 6 +----- src/game/server/score/sql_score.cpp | 6 ++++++ src/game/variables.h | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 7fe01b815..a3a2f71c2 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1166,7 +1166,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; } - if(g_Config.m_SvJoinVoteDelay && Now < pPlayer->m_FirstVoteTick) + if(Now < pPlayer->m_FirstVoteTick) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), "You must wait %d seconds before making your first vote", ((pPlayer->m_FirstVoteTick - Now) / TickSpeed) + 1); diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 207215c6b..3897251dd 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -134,13 +134,9 @@ void CPlayer::Reset() // // Otherwise, block voting for 60 seconds after joining. if(Now > GameServer()->m_NonEmptySince + 10 * TickSpeed) - { - m_FirstVoteTick = Now + 60 * TickSpeed; - } + m_FirstVoteTick = Now + g_Config.m_SvJoinVoteDelay * TickSpeed; else - { m_FirstVoteTick = Now; - } } void CPlayer::Tick() diff --git a/src/game/server/score/sql_score.cpp b/src/game/server/score/sql_score.cpp index f4f429a2a..6541720cf 100644 --- a/src/game/server/score/sql_score.cpp +++ b/src/game/server/score/sql_score.cpp @@ -506,6 +506,12 @@ void CSqlScore::MapVoteThread(void *pUser) str_format(aBuf, sizeof(aBuf), "No map like \"%s\" found. Try adding a '%%' at the start if you don't know the first character. Example: /map %%castle for \"Out of Castle\"", originalMap); pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); } + else if(Now < pPlayer->m_FirstVoteTick) + { + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "You must wait %d seconds before making your first vote", ((pPlayer->m_FirstVoteTick - Now) / pData->m_pSqlData->Server()->TickSpeed()) + 1); + pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); + } else if(pPlayer->m_LastVoteCall && Timeleft > 0) { char aChatmsg[512] = {0}; diff --git a/src/game/variables.h b/src/game/variables.h index b42192d2b..d7b01f105 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -149,7 +149,7 @@ MACRO_CONFIG_INT(SvVoteSpectateRejoindelay, sv_vote_spectate_rejoindelay, 3, 0, MACRO_CONFIG_INT(SvVoteKick, sv_vote_kick, 1, 0, 1, CFGFLAG_SERVER, "Allow voting to kick players") MACRO_CONFIG_INT(SvVoteKickMin, sv_vote_kick_min, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "Minimum number of players required to start a kick vote") MACRO_CONFIG_INT(SvVoteKickBantime, sv_vote_kick_bantime, 5, 0, 1440, CFGFLAG_SERVER, "The time in seconds to ban a player if kicked by vote. 0 makes it just use kick") -MACRO_CONFIG_INT(SvJoinVoteDelay, sv_join_vote_delay, 1, 0, 1, CFGFLAG_SERVER, "Add a delay before recently joined players can vote") +MACRO_CONFIG_INT(SvJoinVoteDelay, sv_join_vote_delay, 60, 0, 1000, CFGFLAG_SERVER, "Add a delay before recently joined players can vote (in seconds)") MACRO_CONFIG_INT(SvOldTeleportWeapons, sv_old_teleport_weapons, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Teleporting of all weapons (deprecated, use special entities instead)"); MACRO_CONFIG_INT(SvOldTeleportHook, sv_old_teleport_hook, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Hook through teleporter (deprecated, use special entities instead)"); MACRO_CONFIG_INT(SvTeleportHoldHook, sv_teleport_hold_hook, 0, 0, 1, CFGFLAG_SERVER|CFGFLAG_GAME, "Hold hook when teleported");