diff --git a/NETWORKING.md b/NETWORKING.md
index 8b15c25de..e4e0a2db9 100644
--- a/NETWORKING.md
+++ b/NETWORKING.md
@@ -147,17 +147,23 @@ The current server configuration xml looks like this:
-
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
@@ -242,9 +248,9 @@ Current players in server with ip in human readable format and time played of ea
`*_player_stats`
All players with online id and username with their time played stats in this server since creation of this database.
-For IP or online ID ban list, you need to create one yourself:
+For IP, online ID ban list or player reports, you need to create one yourself:
```sql
-CREATE TABLE ipban
+CREATE TABLE ip_ban
(
ip_start INTEGER UNSIGNED NOT NULL UNIQUE, -- Starting of ip decimal for banning (inclusive)
ip_end INTEGER UNSIGNED NOT NULL UNIQUE, -- Ending of ip decimal for banning (inclusive)
@@ -256,7 +262,7 @@ CREATE TABLE ipban
last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered
);
-CREATE TABLE onlineidban
+CREATE TABLE online_id_ban
(
online_id INTEGER UNSIGNED NOT NULL UNIQUE, -- Online id from STK addons database for banning
starting_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Starting time of this banning entry to be effective
@@ -266,4 +272,14 @@ CREATE TABLE onlineidban
trigger_count INTEGER UNSIGNED NOT NULL DEFAULT 0, -- Number of banning triggered by this ban entry
last_trigger TIMESTAMP NULL DEFAULT NULL -- Latest time this banning entry was triggered
);
+
+CREATE TABLE player_reports
+(
+ reported_online_id INTEGER UNSIGNED NOT NULL, -- Online id of player who reports, 0 for offline player
+ reported_username TEXT NOT NULL, -- Player name who reports
+ reported_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- Time of reporting
+ info TEXT NOT NULL, -- Report info by reporter
+ reporting_online_id INTEGER UNSIGNED NOT NULL, -- Online id of player being reported, 0 for offline player
+ reporting_username TEXT NOT NULL -- Player name being reported
+);
```
diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp
index 6f7cd2b37..c9bdd2cdf 100644
--- a/src/network/protocols/client_lobby.cpp
+++ b/src/network/protocols/client_lobby.cpp
@@ -99,6 +99,7 @@ ClientLobby::ClientLobby(const TransportAddress& a, std::shared_ptr s)
m_server_send_live_load_world = false;
m_server_enabled_chat = true;
m_server_enabled_track_voting = true;
+ m_server_enabled_report_player = false;
} // ClientLobby
//-----------------------------------------------------------------------------
@@ -622,6 +623,9 @@ void ClientLobby::connectionAccepted(Event* event)
if (auto_start_timer != std::numeric_limits::max())
NetworkingLobby::getInstance()->setStartingTimerTo(auto_start_timer);
m_server_enabled_chat = data.getUInt8() == 1;
+ if (NetworkConfig::get()->getServerCapabilities().find("report_player") !=
+ NetworkConfig::get()->getServerCapabilities().end())
+ m_server_enabled_report_player = data.getUInt8() == 1;
} // connectionAccepted
//-----------------------------------------------------------------------------
diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp
index 2bf11b6b6..6a59df1c0 100644
--- a/src/network/protocols/client_lobby.hpp
+++ b/src/network/protocols/client_lobby.hpp
@@ -107,6 +107,8 @@ private:
bool m_server_enabled_track_voting;
+ bool m_server_enabled_report_player;
+
uint64_t m_auto_back_to_lobby_time;
uint64_t m_start_live_game_time;
@@ -173,6 +175,8 @@ public:
bool serverEnabledChat() const { return m_server_enabled_chat; }
bool serverEnabledTrackVoting() const
{ return m_server_enabled_track_voting; }
+ bool serverEnabledReportPlayer() const
+ { return m_server_enabled_report_player; }
};
#endif // CLIENT_LOBBY_HPP
diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp
index 4492d080c..c2a358f98 100644
--- a/src/network/protocols/server_lobby.cpp
+++ b/src/network/protocols/server_lobby.cpp
@@ -144,6 +144,7 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
m_difficulty.store(ServerConfig::m_server_difficulty);
m_game_mode.store(ServerConfig::m_server_mode);
m_default_vote = new PeerVote();
+ m_player_reports_table_exists = false;
initDatabase();
} // ServerLobby
@@ -171,7 +172,6 @@ void ServerLobby::initDatabase()
#ifdef ENABLE_SQLITE3
m_last_cleanup_db_time = StkTime::getMonoTimeMs();
m_db = NULL;
- sqlite3_stmt* stmt = NULL;;
m_ip_ban_table_exists = false;
m_online_id_ban_table_exists = false;
if (!ServerConfig::m_sql_management)
@@ -186,80 +186,11 @@ void ServerLobby::initDatabase()
return;
}
- const std::string ip_ban_table = ServerConfig::m_ip_ban_table;
- if (!ip_ban_table.empty())
- {
- std::string query = StringUtils::insertValues(
- "SELECT count(type) FROM sqlite_master "
- "WHERE type='table' AND name='%s';", ip_ban_table.c_str());
-
- ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
- if (ret == SQLITE_OK)
- {
- ret = sqlite3_step(stmt);
- if (ret == SQLITE_ROW)
- {
- int number = sqlite3_column_int(stmt, 0);
- if (number == 1)
- {
- Log::info("ServerLobby", "%s ip ban table will used.",
- ip_ban_table.c_str());
- m_ip_ban_table_exists = true;
- }
- }
- ret = sqlite3_finalize(stmt);
- if (ret != SQLITE_OK)
- {
- Log::error("ServerLobby",
- "Error finalize database for query %s: %s", query.c_str(),
- sqlite3_errmsg(m_db));
- }
- }
- }
- if (!m_ip_ban_table_exists && !ip_ban_table.empty())
- {
- Log::warn("ServerLobby", "%s ip ban table not found in database.",
- ip_ban_table.c_str());
- }
-
- const std::string online_id_ban_table =
- ServerConfig::m_online_id_ban_table;
- if (!online_id_ban_table.empty())
- {
- std::string query = StringUtils::insertValues(
- "SELECT count(type) FROM sqlite_master "
- "WHERE type='table' AND name='%s';", online_id_ban_table.c_str());
-
- int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
- if (ret == SQLITE_OK)
- {
- ret = sqlite3_step(stmt);
- if (ret == SQLITE_ROW)
- {
- int number = sqlite3_column_int(stmt, 0);
- if (number == 1)
- {
- Log::info("ServerLobby",
- "%s online id ban table will used.",
- online_id_ban_table.c_str());
- m_online_id_ban_table_exists = true;
- }
- }
- ret = sqlite3_finalize(stmt);
- if (ret != SQLITE_OK)
- {
- Log::error("ServerLobby",
- "Error finalize database for query %s: %s",
- query.c_str(), sqlite3_errmsg(m_db));
- }
- }
- }
- if (!m_online_id_ban_table_exists && !online_id_ban_table.empty())
- {
- Log::warn("ServerLobby",
- "%s online id ban table not found in database.",
- online_id_ban_table.c_str());
- }
+ checkTableExists(ServerConfig::m_ip_ban_table, m_ip_ban_table_exists);
+ checkTableExists(ServerConfig::m_online_id_ban_table,
+ m_online_id_ban_table_exists);
+ checkTableExists(ServerConfig::m_player_reports_table,
+ m_player_reports_table_exists);
#endif
} // initDatabase
@@ -790,6 +721,49 @@ void ServerLobby::easySQLQuery(const std::string& query) const
query.c_str(), sqlite3_errmsg(m_db));
}
} // easySQLQuery
+
+//-----------------------------------------------------------------------------
+/* Write true to result if table name exists in database. */
+void ServerLobby::checkTableExists(const std::string& table, bool& result)
+{
+ if (!m_db)
+ return;
+ sqlite3_stmt* stmt = NULL;
+ if (!table.empty())
+ {
+ std::string query = StringUtils::insertValues(
+ "SELECT count(type) FROM sqlite_master "
+ "WHERE type='table' AND name='%s';", table.c_str());
+
+ int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &stmt, 0);
+ if (ret == SQLITE_OK)
+ {
+ ret = sqlite3_step(stmt);
+ if (ret == SQLITE_ROW)
+ {
+ int number = sqlite3_column_int(stmt, 0);
+ if (number == 1)
+ {
+ Log::info("ServerLobby", "Table named %s will used.",
+ table.c_str());
+ result = true;
+ }
+ }
+ ret = sqlite3_finalize(stmt);
+ if (ret != SQLITE_OK)
+ {
+ Log::error("ServerLobby",
+ "Error finalize database for query %s: %s",
+ query.c_str(), sqlite3_errmsg(m_db));
+ }
+ }
+ }
+ if (!result && !table.empty())
+ {
+ Log::warn("ServerLobby", "Table named %s not found in database.",
+ table.c_str());
+ }
+} // checkTableExists
#endif
//-----------------------------------------------------------------------------
@@ -2767,7 +2741,8 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer,
message_ack->addFloat(auto_start_timer)
.addUInt32(ServerConfig::m_state_frequency)
- .addUInt8(ServerConfig::m_chat ? 1 : 0);
+ .addUInt8(ServerConfig::m_chat ? 1 : 0)
+ .addUInt8(m_player_reports_table_exists ? 1 : 0);
peer->setSpectator(false);
if (game_started)
diff --git a/src/network/protocols/server_lobby.hpp b/src/network/protocols/server_lobby.hpp
index e0a88c238..bc27ac8bc 100644
--- a/src/network/protocols/server_lobby.hpp
+++ b/src/network/protocols/server_lobby.hpp
@@ -70,6 +70,8 @@ private:
irr::core::stringw m_name;
bool m_tried = false;
};
+ bool m_player_reports_table_exists;
+
#ifdef ENABLE_SQLITE3
sqlite3* m_db;
@@ -84,6 +86,8 @@ private:
void cleanupDatabase();
void easySQLQuery(const std::string& query) const;
+
+ void checkTableExists(const std::string& table, bool& result);
#endif
void initDatabase();
diff --git a/src/network/server_config.cpp b/src/network/server_config.cpp
index 418996d72..e2f7cb9ae 100644
--- a/src/network/server_config.cpp
+++ b/src/network/server_config.cpp
@@ -311,6 +311,8 @@ void loadServerLobbyFromConfig()
}
NetworkConfig::get()->setStateFrequency(m_state_frequency);
+ if (m_player_reports_expired_days < 0.0f)
+ m_player_reports_expired_days.revertToDefaults();
if (m_server_difficulty > RaceManager::DIFFICULTY_LAST)
m_server_difficulty = RaceManager::DIFFICULTY_LAST;
if (m_server_mode > 8)
diff --git a/src/network/server_config.hpp b/src/network/server_config.hpp
index 2ac3434ea..df4b613b2 100644
--- a/src/network/server_config.hpp
+++ b/src/network/server_config.hpp
@@ -322,8 +322,8 @@ namespace ServerConfig
SERVER_CFG_PREFIX BoolServerConfigParam m_sql_management
SERVER_CFG_DEFAULT(BoolServerConfigParam(false,
"sql-management",
- "Use sql to manage server stats and banlist, STK needs to be compiled "
- "with sqlite3 supported."));
+ "Use sql database for handling server stats and maintenance, STK "
+ "needs to be compiled with sqlite3 supported."));
SERVER_CFG_PREFIX StringServerConfigParam m_database_file
SERVER_CFG_DEFAULT(StringServerConfigParam("stkservers.db",
@@ -334,17 +334,29 @@ namespace ServerConfig
"NETWORKING.md for details"));
SERVER_CFG_PREFIX StringServerConfigParam m_ip_ban_table
- SERVER_CFG_DEFAULT(StringServerConfigParam("ipban",
+ SERVER_CFG_DEFAULT(StringServerConfigParam("ip_ban",
"ip-ban-table",
"Ip ban list table name, you need to create the table first, see "
"NETWORKING.md for details, empty to disable."));
SERVER_CFG_PREFIX StringServerConfigParam m_online_id_ban_table
- SERVER_CFG_DEFAULT(StringServerConfigParam("onlineidban",
+ SERVER_CFG_DEFAULT(StringServerConfigParam("online_id_ban",
"online-id-ban-table",
"Online ID ban list table name, you need to create the table first, "
"see NETWORKING.md for details, empty to disable."));
+ SERVER_CFG_PREFIX StringServerConfigParam m_player_reports_table
+ SERVER_CFG_DEFAULT(StringServerConfigParam("player_reports",
+ "player-reports-table",
+ "Player reports table name, which will be written when a player "
+ "reports player in the network user dialog, you need to create the "
+ "table first, see NETWORKING.md for details, empty to disable."));
+
+ SERVER_CFG_PREFIX FloatServerConfigParam m_player_reports_expired_days
+ SERVER_CFG_DEFAULT(FloatServerConfigParam(3.0f,
+ "player-reports-expired-days", "Days to keep player reports, "
+ "older than that will be auto cleared, 0 to keep them forever."));
+
// ========================================================================
/** Server version, will be advanced if there are protocol changes. */
static const uint32_t m_server_version = 6;
diff --git a/src/states_screens/dialogs/network_user_dialog.cpp b/src/states_screens/dialogs/network_user_dialog.cpp
index fd8ee2733..dce66ada9 100644
--- a/src/states_screens/dialogs/network_user_dialog.cpp
+++ b/src/states_screens/dialogs/network_user_dialog.cpp
@@ -26,7 +26,7 @@
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "online/online_profile.hpp"
-#include "network/protocols/lobby_protocol.hpp"
+#include "network/protocols/client_lobby.hpp"
#include "network/stk_host.hpp"
#include "states_screens/dialogs/general_text_field_dialog.hpp"
#include "states_screens/state_manager.hpp"
@@ -129,7 +129,9 @@ void NetworkUserDialog::beforeAddingWidgets()
getWidget("remove")->setVisible(false);
m_report_widget = getWidget("enter");
assert(m_report_widget != NULL);
- if (m_host_id != STKHost::get()->getMyHostId())
+ auto cl = LobbyProtocol::get();
+ if (cl->serverEnabledReportPlayer() &&
+ m_host_id != STKHost::get()->getMyHostId())
{
// I18N: In the network user dialog,
// report player about for example abusive behaviour in game