diff --git a/README.md b/README.md index e7b19eeaa..3f104b294 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Whether to prefer bundled libraries over system libraries. Setting to ON will ma Whether to enable WebSocket support for server. Setting to ON requires the `libwebsockets-dev` library installed. Default value is OFF. * **-DMYSQL=[ON|OFF]**
-Whether to enable MySQL/MariaDB support for server. Setting to ON requires the `libmariadbclient-dev`, `libmysqlcppconn-dev` and `libboost-dev` libraries installed, which are also provided as bundled libraries for the common platforms. Default value is OFF. +Whether to enable MySQL/MariaDB support for server. Requires at least MySQL 8.0 or MariaDB 10.2. Setting to ON requires the `libmariadbclient-dev`, `libmysqlcppconn-dev` and `libboost-dev` libraries installed, which are also provided as bundled libraries for the common platforms. Default value is OFF. Note that the bundled MySQL libraries might not work properly on your system. If you run into connection problems with the MySQL server, for example that it connects as root while you chose another user, make sure to install your system libraries for the MySQL client and C++ connector. Make sure that the CMake configuration summary says that it found MySQL libs that were not bundled (no "using bundled libs"). diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index d27b70f8e..30e4132f7 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1956,7 +1956,7 @@ void CServer::CacheServerInfoSixup(CCache *pCache, bool SendClients) } char aVersion[32]; - str_format(aVersion, sizeof(aVersion), "0.7, %s", GameServer()->Version()); + str_format(aVersion, sizeof(aVersion), "0.7↔%s", GameServer()->Version()); Packer.AddString(aVersion, 32); Packer.AddString(g_Config.m_SvName, 64); Packer.AddString(g_Config.m_SvHostname, 128); @@ -1972,7 +1972,7 @@ void CServer::CacheServerInfoSixup(CCache *pCache, bool SendClients) Packer.AddInt(Flags); int MaxClients = m_NetServer.MaxClients(); - Packer.AddInt(0); // server skill level //TODO: Implement this with IGameServer::GetSkillLevel() + Packer.AddInt(g_Config.m_SvSkillLevel); // server skill level Packer.AddInt(PlayerCount); // num players Packer.AddInt(maximum(MaxClients - maximum(g_Config.m_SvSpectatorSlots, g_Config.m_SvReservedSlots), PlayerCount)); // max players Packer.AddInt(ClientCount); // num clients diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 580cd1b4f..69ff6112f 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -146,6 +146,7 @@ MACRO_CONFIG_INT(SvDemoChat, sv_demo_chat, 0, 0, 1, CFGFLAG_SERVER, "Record chat MACRO_CONFIG_INT(SvServerInfoPerSecond, sv_server_info_per_second, 50, 0, 10000, CFGFLAG_SERVER, "Maximum number of complete server info responses that are sent out per second (0 for no limit)") MACRO_CONFIG_INT(SvVanConnPerSecond, sv_van_conn_per_second, 10, 0, 10000, CFGFLAG_SERVER, "Antispoof specific ratelimit (0 for no limit)") MACRO_CONFIG_INT(SvSixup, sv_sixup, 1, 0, 1, CFGFLAG_SERVER, "Enable sixup connections") +MACRO_CONFIG_INT(SvSkillLevel, sv_skill_level, 1, SERVERINFO_LEVEL_MIN, SERVERINFO_LEVEL_MAX, CFGFLAG_SERVER, "Difficulty level for Teeworlds 0.7 (0: Casual, 1: Normal, 2: Competitive)") MACRO_CONFIG_STR(EcBindaddr, ec_bindaddr, 128, "localhost", CFGFLAG_ECON, "Address to bind the external console to. Anything but 'localhost' is dangerous") MACRO_CONFIG_INT(EcPort, ec_port, 0, 0, 0, CFGFLAG_ECON, "Port to use for the external console") @@ -377,6 +378,4 @@ MACRO_CONFIG_INT(GfxEnableTextureUnitOptimization, gfx_enable_texture_unit_optim #endif MACRO_CONFIG_INT(GfxUsePreinitBuffer, gfx_use_preinitialized_buffer, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use only one buffer for data, that is uploaded to the GPU(might help when using an iGPUs).") -#if defined(CONF_VIDEORECORDER) MACRO_CONFIG_INT(ClVideoRecorderFPS, cl_video_recorder_fps, 60, 1, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "At which FPS the videorecorder should record demos.") -#endif diff --git a/src/engine/shared/protocol.h b/src/engine/shared/protocol.h index 0ea7850e0..25276ffeb 100644 --- a/src/engine/shared/protocol.h +++ b/src/engine/shared/protocol.h @@ -80,6 +80,8 @@ enum SERVER_TICK_SPEED=50, SERVER_FLAG_PASSWORD = 1<<0, SERVER_FLAG_TIMESCORE = 1<<1, + SERVERINFO_LEVEL_MIN = 0, + SERVERINFO_LEVEL_MAX = 2, MAX_CLIENTS=64, VANILLA_MAX_CLIENTS=16, diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 81309dd4e..d78b142a6 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -497,11 +497,10 @@ void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput) m_pCharacter->OnPredictedInput(NewInput); // Magic number when we can hope that client has successfully identified itself - if(m_NumInputs == 20) - { - if(g_Config.m_SvClientSuggestion[0] != '\0' && GetClientVersion() <= VERSION_DDNET_OLD) - GameServer()->SendBroadcast(g_Config.m_SvClientSuggestion, m_ClientID); - } + if(m_NumInputs == 20 && g_Config.m_SvClientSuggestion[0] != '\0' && GetClientVersion() <= VERSION_DDNET_OLD) + GameServer()->SendBroadcast(g_Config.m_SvClientSuggestion, m_ClientID); + else if(m_NumInputs == 200 && Server()->IsSixup(m_ClientID)) + GameServer()->SendBroadcast("This server uses an experimental translation from Teeworlds 0.7 to 0.6. Please report bugs on ddnet.tw/discord", m_ClientID); } void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput) diff --git a/src/game/server/teams.cpp b/src/game/server/teams.cpp index 8c5d3d0fe..eeb3f9748 100644 --- a/src/game/server/teams.cpp +++ b/src/game/server/teams.cpp @@ -19,7 +19,6 @@ void CGameTeams::Reset() { m_TeamState[i] = TEAMSTATE_EMPTY; m_TeeFinished[i] = false; - m_MembersCount[i] = 0; m_LastChat[i] = 0; m_TeamLocked[i] = false; m_Invited[i] = 0; @@ -271,17 +270,8 @@ void CGameTeams::SetForceCharacterTeam(int ClientID, int Team) if (Team != m_Core.Team(ClientID)) ForceLeaveTeam(ClientID); else - { m_TeeFinished[ClientID] = false; - if (Count(m_Core.Team(ClientID)) > 0) - m_MembersCount[m_Core.Team(ClientID)]--; - } - SetForceCharacterNewTeam(ClientID, Team); -} - -void CGameTeams::SetForceCharacterNewTeam(int ClientID, int Team) -{ int OldTeam = m_Core.Team(ClientID); m_Core.Team(ClientID, Team); @@ -296,8 +286,6 @@ void CGameTeams::SetForceCharacterNewTeam(int ClientID, int Team) GetPlayer(ClientID)->m_VotedForPractice = false; } - if (m_Core.Team(ClientID) != TEAM_SUPER) - m_MembersCount[m_Core.Team(ClientID)]++; if (Team != TEAM_SUPER && (m_TeamState[Team] == TEAMSTATE_EMPTY || m_TeamLocked[Team])) { if (!m_TeamLocked[Team]) @@ -340,16 +328,20 @@ void CGameTeams::ForceLeaveTeam(int ClientID) // do not reset SaveTeamResult, because it should be logged into teehistorian even if the team leaves } } - - if (Count(m_Core.Team(ClientID)) > 0) - m_MembersCount[m_Core.Team(ClientID)]--; } int CGameTeams::Count(int Team) const { if (Team == TEAM_SUPER) return -1; - return m_MembersCount[Team]; + + int Count = 0; + + for (int i = 0; i < MAX_CLIENTS; ++i) + if (m_Core.Team(i) == Team) + Count++; + + return Count; } void CGameTeams::ChangeTeamState(int Team, int State) @@ -716,12 +708,12 @@ void CGameTeams::ProcessSaveTeam() break; } case CSqlSaveResult::SAVE_FAILED: - if(m_MembersCount[Team] > 0) + if(Count(Team) > 0) m_pSaveTeamResult[Team]->m_SavedTeam.load(Team); break; case CSqlSaveResult::LOAD_SUCCESS: { - if(m_MembersCount[Team] > 0) + if(Count(Team) > 0) m_pSaveTeamResult[Team]->m_SavedTeam.load(Team); char aSaveID[UUID_MAXSTRSIZE]; FormatUuid(m_pSaveTeamResult[Team]->m_SaveID, aSaveID, UUID_MAXSTRSIZE); @@ -748,10 +740,7 @@ void CGameTeams::OnCharacterSpawn(int ClientID) if (m_Core.Team(ClientID) >= TEAM_SUPER || !m_TeamLocked[Team]) { - // Important to only set a new team here, don't remove from an existing - // team since a newly joined player does by definition not have an old team - // to remove from. Doing so would destroy the count in m_MembersCount. - SetForceCharacterNewTeam(ClientID, 0); + SetForceCharacterTeam(ClientID, 0); CheckTeamFinished(Team); } } @@ -794,7 +783,7 @@ void CGameTeams::OnCharacterDeath(int ClientID, int Weapon) if (Weapon == WEAPON_SELF) GameServer()->m_apPlayers[i]->Respawn(true); // spawn the rest of team with weak hook on the killer } - if(m_MembersCount[Team] > 1) + if(Count(Team) > 1) GameServer()->SendChatTarget(i, aBuf); } } diff --git a/src/game/server/teams.h b/src/game/server/teams.h index e5fdbfc9c..80b0b3202 100644 --- a/src/game/server/teams.h +++ b/src/game/server/teams.h @@ -12,7 +12,6 @@ class CSqlSaveResult; class CGameTeams { int m_TeamState[MAX_CLIENTS]; - int m_MembersCount[MAX_CLIENTS]; bool m_TeeFinished[MAX_CLIENTS]; bool m_TeamLocked[MAX_CLIENTS]; uint64_t m_Invited[MAX_CLIENTS]; diff --git a/src/game/teamscore.cpp b/src/game/teamscore.cpp index 8b227bde4..e84e12481 100644 --- a/src/game/teamscore.cpp +++ b/src/game/teamscore.cpp @@ -6,12 +6,12 @@ CTeamsCore::CTeamsCore() Reset(); } -bool CTeamsCore::SameTeam(int ClientID1, int ClientID2) +bool CTeamsCore::SameTeam(int ClientID1, int ClientID2) const { return m_Team[ClientID1] == m_Team[ClientID2]; } -int CTeamsCore::Team(int ClientID) +int CTeamsCore::Team(int ClientID) const { return m_Team[ClientID]; } @@ -21,7 +21,7 @@ void CTeamsCore::Team(int ClientID, int Team) m_Team[ClientID] = Team; } -bool CTeamsCore::CanKeepHook(int ClientID1, int ClientID2) +bool CTeamsCore::CanKeepHook(int ClientID1, int ClientID2) const { if (m_Team[ClientID1] == (m_IsDDRace16 ? VANILLA_TEAM_SUPER : TEAM_SUPER) || m_Team[ClientID2] == (m_IsDDRace16 ? VANILLA_TEAM_SUPER : TEAM_SUPER) || ClientID1 == ClientID2) @@ -29,7 +29,7 @@ bool CTeamsCore::CanKeepHook(int ClientID1, int ClientID2) return m_Team[ClientID1] == m_Team[ClientID2]; } -bool CTeamsCore::CanCollide(int ClientID1, int ClientID2) +bool CTeamsCore::CanCollide(int ClientID1, int ClientID2) const { if (m_Team[ClientID1] == (m_IsDDRace16 ? VANILLA_TEAM_SUPER : TEAM_SUPER) || m_Team[ClientID2] == (m_IsDDRace16 ? VANILLA_TEAM_SUPER : TEAM_SUPER) || ClientID1 == ClientID2) diff --git a/src/game/teamscore.h b/src/game/teamscore.h index 3246bcf5f..13704ca52 100644 --- a/src/game/teamscore.h +++ b/src/game/teamscore.h @@ -16,14 +16,14 @@ class CTeamsCore public: bool m_IsDDRace16; - CTeamsCore(void); + CTeamsCore(); - bool SameTeam(int ClientID1, int ClientID2); + bool SameTeam(int ClientID1, int ClientID2) const; - bool CanKeepHook(int ClientID1, int ClientID2); - bool CanCollide(int ClientID1, int ClientID2); + bool CanKeepHook(int ClientID1, int ClientID2) const; + bool CanCollide(int ClientID1, int ClientID2) const; - int Team(int ClientID); + int Team(int ClientID) const; void Team(int ClientID, int Team); void Reset(); @@ -32,7 +32,7 @@ public: m_IsSolo[ClientID] = Value; } - bool GetSolo(int ClientID) + bool GetSolo(int ClientID) const { return m_IsSolo[ClientID]; }