mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-01 23:35:41 +00:00
Use proper argument parser
This commit is contained in:
parent
548b2512cc
commit
588c68ebe1
@ -4,8 +4,10 @@
|
|||||||
#include "commandline.h"
|
#include "commandline.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TLuaEngine;
|
class TLuaEngine;
|
||||||
@ -34,10 +36,20 @@ private:
|
|||||||
void Command_Settings(const std::string& cmd, const std::vector<std::string>& args);
|
void Command_Settings(const std::string& cmd, const std::vector<std::string>& args);
|
||||||
|
|
||||||
void Command_Say(const std::string& FullCommand);
|
void Command_Say(const std::string& FullCommand);
|
||||||
bool ExpectArgsCount(const std::vector<std::string>& args, size_t n);
|
bool EnsureArgsCount(const std::vector<std::string>& args, size_t n);
|
||||||
bool ExpectArgsCount(const std::vector<std::string>& args, size_t min, size_t max);
|
bool EnsureArgsCount(const std::vector<std::string>& args, size_t min, size_t max);
|
||||||
|
|
||||||
static std::tuple<std::string, std::vector<std::string>> ParseCommand(const std::string& cmd);
|
static std::tuple<std::string, std::vector<std::string>> ParseCommand(const std::string& cmd);
|
||||||
|
static std::string ConcatArgs(const std::vector<std::string>& args, char space = ' ');
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::function<void(const std::string&, const std::vector<std::string>&)>> mCommandMap = {
|
||||||
|
{ "lua", [this](const auto& a, const auto& b) { Command_Lua(a, b); } },
|
||||||
|
{ "help", [this](const auto& a, const auto& b) { Command_Help(a, b); } },
|
||||||
|
{ "kick", [this](const auto& a, const auto& b) { Command_Kick(a, b); } },
|
||||||
|
{ "list", [this](const auto& a, const auto& b) { Command_List(a, b); } },
|
||||||
|
{ "status", [this](const auto& a, const auto& b) { Command_Status(a, b); } },
|
||||||
|
{ "settings", [this](const auto& a, const auto& b) { Command_Settings(a, b); } },
|
||||||
|
};
|
||||||
|
|
||||||
Commandline mCommandline;
|
Commandline mCommandline;
|
||||||
std::vector<std::string> mCachedLuaHistory;
|
std::vector<std::string> mCachedLuaHistory;
|
||||||
|
115
src/TConsole.cpp
115
src/TConsole.cpp
@ -133,8 +133,11 @@ void TConsole::ChangeToRegularConsole() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TConsole::ExpectArgsCount(const std::vector<std::string>& args, size_t n) {
|
bool TConsole::EnsureArgsCount(const std::vector<std::string>& args, size_t n) {
|
||||||
if (args.size() != n) {
|
if (n == 0 && args.size() != 0) {
|
||||||
|
Application::Console().WriteRaw("This command expects no arguments.");
|
||||||
|
return false;
|
||||||
|
} else if (args.size() != n) {
|
||||||
Application::Console().WriteRaw("Expected " + std::to_string(n) + " argument(s), instead got " + std::to_string(args.size()));
|
Application::Console().WriteRaw("Expected " + std::to_string(n) + " argument(s), instead got " + std::to_string(args.size()));
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -142,9 +145,9 @@ bool TConsole::ExpectArgsCount(const std::vector<std::string>& args, size_t n) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TConsole::ExpectArgsCount(const std::vector<std::string>& args, size_t min, size_t max) {
|
bool TConsole::EnsureArgsCount(const std::vector<std::string>& args, size_t min, size_t max) {
|
||||||
if (min == max) {
|
if (min == max) {
|
||||||
return ExpectArgsCount(args, min);
|
return EnsureArgsCount(args, min);
|
||||||
} else {
|
} else {
|
||||||
if (args.size() > max) {
|
if (args.size() > max) {
|
||||||
Application::Console().WriteRaw("Too many arguments. At most " + std::to_string(max) + " arguments expected, got " + std::to_string(args.size()) + " instead.");
|
Application::Console().WriteRaw("Too many arguments. At most " + std::to_string(max) + " arguments expected, got " + std::to_string(args.size()) + " instead.");
|
||||||
@ -158,7 +161,8 @@ bool TConsole::ExpectArgsCount(const std::vector<std::string>& args, size_t min,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TConsole::Command_Lua(const std::string& cmd, const std::vector<std::string>& args) {
|
void TConsole::Command_Lua(const std::string& cmd, const std::vector<std::string>& args) {
|
||||||
if (!ExpectArgsCount(args, 0, 1)) {
|
if (!EnsureArgsCount(args, 0, 1)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (args.size() == 1) {
|
if (args.size() == 1) {
|
||||||
auto NewStateId = args.at(0);
|
auto NewStateId = args.at(0);
|
||||||
@ -174,6 +178,9 @@ void TConsole::Command_Lua(const std::string& cmd, const std::vector<std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TConsole::Command_Help(const std::string&, const std::vector<std::string>& args) {
|
void TConsole::Command_Help(const std::string&, const std::vector<std::string>& args) {
|
||||||
|
if (!EnsureArgsCount(args, 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
static constexpr const char* sHelpString = R"(
|
static constexpr const char* sHelpString = R"(
|
||||||
Commands:
|
Commands:
|
||||||
help displays this help
|
help displays this help
|
||||||
@ -187,38 +194,46 @@ void TConsole::Command_Help(const std::string&, const std::vector<std::string>&
|
|||||||
Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString));
|
Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string TConsole::ConcatArgs(const std::vector<std::string>& args, char space) {
|
||||||
|
std::string Result;
|
||||||
|
for (const auto& arg : args) {
|
||||||
|
Result += arg + space;
|
||||||
|
}
|
||||||
|
Result = Result.substr(0, Result.size() - 1); // strip trailing space
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
void TConsole::Command_Kick(const std::string& cmd, const std::vector<std::string>& args) {
|
void TConsole::Command_Kick(const std::string& cmd, const std::vector<std::string>& args) {
|
||||||
if (cmd.size() > 4) {
|
if (!EnsureArgsCount(args, 1, size_t(-1))) {
|
||||||
auto Name = cmd.substr(5);
|
return;
|
||||||
std::string Reason = "Kicked by server console";
|
}
|
||||||
auto SpacePos = Name.find(' ');
|
auto Name = args.at(0);
|
||||||
if (SpacePos != Name.npos) {
|
std::string Reason = "Kicked by server console";
|
||||||
Reason = Name.substr(SpacePos + 1);
|
if (args.size() > 1) {
|
||||||
Name = cmd.substr(5, cmd.size() - Reason.size() - 5 - 1);
|
Reason = ConcatArgs({ args.begin() + 1, args.end() });
|
||||||
}
|
}
|
||||||
beammp_trace("attempt to kick '" + Name + "' for '" + Reason + "'");
|
beammp_trace("attempt to kick '" + Name + "' for '" + Reason + "'");
|
||||||
bool Kicked = false;
|
bool Kicked = false;
|
||||||
auto NameCompare = [](std::string Name1, std::string Name2) -> bool {
|
auto NameCompare = [](std::string Name1, std::string Name2) -> bool {
|
||||||
std::for_each(Name1.begin(), Name1.end(), [](char& c) { c = tolower(c); });
|
std::for_each(Name1.begin(), Name1.end(), [](char& c) { c = tolower(c); });
|
||||||
std::for_each(Name2.begin(), Name2.end(), [](char& c) { c = tolower(c); });
|
std::for_each(Name2.begin(), Name2.end(), [](char& c) { c = tolower(c); });
|
||||||
return StringStartsWith(Name1, Name2) || StringStartsWith(Name2, Name1);
|
return StringStartsWith(Name1, Name2) || StringStartsWith(Name2, Name1);
|
||||||
};
|
};
|
||||||
mLuaEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
mLuaEngine->Server().ForEachClient([&](std::weak_ptr<TClient> Client) -> bool {
|
||||||
if (!Client.expired()) {
|
if (!Client.expired()) {
|
||||||
auto locked = Client.lock();
|
auto locked = Client.lock();
|
||||||
if (NameCompare(locked->GetName(), Name)) {
|
if (NameCompare(locked->GetName(), Name)) {
|
||||||
mLuaEngine->Network().ClientKick(*locked, Reason);
|
mLuaEngine->Network().ClientKick(*locked, Reason);
|
||||||
Kicked = true;
|
Kicked = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (!Kicked) {
|
|
||||||
Application::Console().WriteRaw("Error: No player with name matching '" + Name + "' was found.");
|
|
||||||
} else {
|
|
||||||
Application::Console().WriteRaw("Kicked player '" + Name + "' for reason: '" + Reason + "'.");
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (!Kicked) {
|
||||||
|
Application::Console().WriteRaw("Error: No player with name matching '" + Name + "' was found.");
|
||||||
|
} else {
|
||||||
|
Application::Console().WriteRaw("Kicked player '" + Name + "' for reason: '" + Reason + "'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,6 +291,9 @@ std::tuple<std::string, std::vector<std::string>> TConsole::ParseCommand(const s
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TConsole::Command_Settings(const std::string& cmd, const std::vector<std::string>& args) {
|
void TConsole::Command_Settings(const std::string& cmd, const std::vector<std::string>& args) {
|
||||||
|
if (!EnsureArgsCount(args, 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TConsole::Command_Say(const std::string& FullCmd) {
|
void TConsole::Command_Say(const std::string& FullCmd) {
|
||||||
@ -289,6 +307,9 @@ void TConsole::Command_Say(const std::string& FullCmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TConsole::Command_List(const std::string&, const std::vector<std::string>& args) {
|
void TConsole::Command_List(const std::string&, const std::vector<std::string>& args) {
|
||||||
|
if (!EnsureArgsCount(args, 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mLuaEngine->Server().ClientCount() == 0) {
|
if (mLuaEngine->Server().ClientCount() == 0) {
|
||||||
Application::Console().WriteRaw("No players online.");
|
Application::Console().WriteRaw("No players online.");
|
||||||
} else {
|
} else {
|
||||||
@ -309,6 +330,9 @@ void TConsole::Command_List(const std::string&, const std::vector<std::string>&
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TConsole::Command_Status(const std::string&, const std::vector<std::string>& args) {
|
void TConsole::Command_Status(const std::string&, const std::vector<std::string>& args) {
|
||||||
|
if (!EnsureArgsCount(args, 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::stringstream Status;
|
std::stringstream Status;
|
||||||
|
|
||||||
size_t CarCount = 0;
|
size_t CarCount = 0;
|
||||||
@ -533,25 +557,16 @@ TConsole::TConsole() {
|
|||||||
} else if (cmd == "exit") {
|
} else if (cmd == "exit") {
|
||||||
beammp_info("gracefully shutting down");
|
beammp_info("gracefully shutting down");
|
||||||
Application::GracefullyShutdown();
|
Application::GracefullyShutdown();
|
||||||
} else if (cmd == "lua") {
|
|
||||||
Command_Lua(cmd, args);
|
|
||||||
} else if (cmd == "help") {
|
|
||||||
RunAsCommand(TrimmedCmd, true);
|
|
||||||
Command_Help(cmd, args);
|
|
||||||
} else if (cmd == "kick") {
|
|
||||||
RunAsCommand(TrimmedCmd, true);
|
|
||||||
Command_Kick(cmd, args);
|
|
||||||
} else if (cmd == "say") {
|
} else if (cmd == "say") {
|
||||||
RunAsCommand(TrimmedCmd, true);
|
RunAsCommand(TrimmedCmd, true);
|
||||||
Command_Say(TrimmedCmd);
|
Command_Say(TrimmedCmd);
|
||||||
} else if (cmd == "list") {
|
} else {
|
||||||
RunAsCommand(TrimmedCmd, true);
|
if (mCommandMap.find(cmd) != mCommandMap.end()) {
|
||||||
Command_List(cmd, args);
|
mCommandMap.at(cmd)(cmd, args);
|
||||||
} else if (cmd == "status") {
|
RunAsCommand(TrimmedCmd, true);
|
||||||
RunAsCommand(TrimmedCmd, true);
|
} else {
|
||||||
Command_Status(cmd, args);
|
RunAsCommand(TrimmedCmd);
|
||||||
} else if (!cmd.empty()) {
|
}
|
||||||
RunAsCommand(TrimmedCmd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user