diff --git a/README.md b/README.md index 017eecfb..9e9376ec 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ Darkflame Universe is a server emulator and does not distribute any LEGO® Unive * Single player installs now no longer require building the server from source or installing development tools. * Download the [latest release](https://github.com/DarkflameUniverse/DarkflameServer/releases) and extract the files into a folder inside your client. * You should be able to see the folder with the server executables in the same folder as `legouniverse.exe`. -* To run the server, double-click MasterServer.exe. -* A default account called `admin` will be created with a password of `password`. +* To run the server, double-click `MasterServer.exe`. +* You will be asked to create an account the first time you run the server. * When shutting down the server, it is highly recommended to click the `MasterServer.exe` window and hold `ctrl` while pressing `c` to stop the server. * We are working on a way to make it so when you close the game, the server saves automatically alongside when you open the game, the server starts automatically. @@ -283,8 +283,8 @@ systemctl stop darkflame.service journalctl -xeu darkflame.service ``` -### First admin user -Run `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users! +### First user or adding more users. +The first time you run `MasterServer`, you will be prompted to create an account. To create more accounts from the command line, `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users! ### Account management tool (Nexus Dashboard) **If you are just using this server for yourself, you can skip setting up Nexus Dashboard** diff --git a/dDatabase/GameDatabase/ITables/IAccounts.h b/dDatabase/GameDatabase/ITables/IAccounts.h index a0377f4b..13ecf29b 100644 --- a/dDatabase/GameDatabase/ITables/IAccounts.h +++ b/dDatabase/GameDatabase/ITables/IAccounts.h @@ -36,6 +36,8 @@ class IAccounts { // Update the GameMaster level of an account. virtual void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) = 0; + + virtual uint32_t GetAccountCount() = 0; }; #endif //!__IACCOUNTS__H__ diff --git a/dDatabase/GameDatabase/MySQL/MySQLDatabase.h b/dDatabase/GameDatabase/MySQL/MySQLDatabase.h index a124e661..fa3edfbc 100644 --- a/dDatabase/GameDatabase/MySQL/MySQLDatabase.h +++ b/dDatabase/GameDatabase/MySQL/MySQLDatabase.h @@ -124,6 +124,7 @@ class MySQLDatabase : public GameDatabase { void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional characterId) override; void DeleteUgcBuild(const LWOOBJID bigId) override; sql::PreparedStatement* CreatePreppedStmt(const std::string& query); + uint32_t GetAccountCount() override; private: // Generic query functions that can be used for any query. diff --git a/dDatabase/GameDatabase/MySQL/Tables/Accounts.cpp b/dDatabase/GameDatabase/MySQL/Tables/Accounts.cpp index 9e9812f3..f4310dd8 100644 --- a/dDatabase/GameDatabase/MySQL/Tables/Accounts.cpp +++ b/dDatabase/GameDatabase/MySQL/Tables/Accounts.cpp @@ -39,3 +39,8 @@ void MySQLDatabase::InsertNewAccount(const std::string_view username, const std: void MySQLDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) { ExecuteUpdate("UPDATE accounts SET gm_level = ? WHERE id = ?;", static_cast(gmLevel), accountId); } + +uint32_t MySQLDatabase::GetAccountCount() { + auto res = ExecuteSelect("SELECT COUNT(*) as count FROM accounts;"); + return res->next() ? res->getUInt("count") : 0; +} diff --git a/dDatabase/GameDatabase/SQLite/SQLiteDatabase.h b/dDatabase/GameDatabase/SQLite/SQLiteDatabase.h index 39712d02..97385765 100644 --- a/dDatabase/GameDatabase/SQLite/SQLiteDatabase.h +++ b/dDatabase/GameDatabase/SQLite/SQLiteDatabase.h @@ -121,6 +121,7 @@ class SQLiteDatabase : public GameDatabase { void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override; void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional characterId) override; void DeleteUgcBuild(const LWOOBJID bigId) override; + uint32_t GetAccountCount() override; private: CppSQLite3Statement CreatePreppedStmt(const std::string& query); diff --git a/dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp b/dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp index 8d0781fa..9431d407 100644 --- a/dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp +++ b/dDatabase/GameDatabase/SQLite/Tables/Accounts.cpp @@ -40,3 +40,10 @@ void SQLiteDatabase::InsertNewAccount(const std::string_view username, const std void SQLiteDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) { ExecuteUpdate("UPDATE accounts SET gm_level = ? WHERE id = ?;", static_cast(gmLevel), accountId); } + +uint32_t SQLiteDatabase::GetAccountCount() { + auto [_, res] = ExecuteSelect("SELECT COUNT(*) as count FROM accounts;"); + if (res.eof()) return 0; + + return res.getIntField("count"); +} diff --git a/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h b/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h index dce16c78..ffa14020 100644 --- a/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h +++ b/dDatabase/GameDatabase/TestSQL/TestSQLDatabase.h @@ -100,6 +100,7 @@ class TestSQLDatabase : public GameDatabase { void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override {}; void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional characterId) override {}; void DeleteUgcBuild(const LWOOBJID bigId) override {}; + uint32_t GetAccountCount() override { return 0; }; }; #endif //!TESTSQLDATABASE_H diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 9a54a64e..bfc2a8d0 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -176,12 +176,16 @@ int main(int argc, char** argv) { } // Run migrations should any need to be run. - MigrationRunner::RunSQLiteMigrations(); + MigrationRunner::RunSQLiteMigrations(); //If the first command line argument is -a or --account then make the user //input a username and password, with the password being hidden. - if (argc > 1 && - (strcmp(argv[1], "-a") == 0 || strcmp(argv[1], "--account") == 0)) { + bool doesAnyAccountExist = Database::Get()->GetAccountCount() > 0; + if (!doesAnyAccountExist) { + LOG("No accounts exist in the database. Please create an account."); + } + if ((argc > 1 && + (strcmp(argv[1], "-a") == 0 || strcmp(argv[1], "--account") == 0)) || !doesAnyAccountExist) { std::string username; std::string password;