From 7e9b92907deb48dada0477b38a1a7d557a02e1c9 Mon Sep 17 00:00:00 2001 From: JAJames Date: Sun, 31 Jan 2016 00:03:28 -0500 Subject: [PATCH] RenX.Core: * Added 'gameoverWhenEmpty' and 'gameover(std::chrono::seconds)' functions to RenX::Server RenX.Commands 'GameOverIRCCommand': * Added parsing of parameters for the strings "empty", and "now" * Added parsing of parameters as time in seconds, when above not matches * Changed default (no-args) behavior to 10 second delay --- Release/Plugins/RenX.Core.lib | Bin 187196 -> 188314 bytes RenX.Commands/RenX_Commands.cpp | 19 ++++++-- RenX.Core/RenX_Server.cpp | 77 ++++++++++++++++++++++++++------ RenX.Core/RenX_Server.h | 25 ++++++++++- 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index 8d90ffcb6649fdf279f911f2d76d40d0271c2984..ba038cab55bb4e02e5341bfde0639c4cd3e63945 100644 GIT binary patch delta 19222 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 TY0$_X0dI{OJ1AgaLIV3geyptd delta 19262 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 } -void GameOverIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &) +void GameOverIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) @@ -1313,8 +1313,19 @@ void GameOverIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString if (server->isLogChanType(type)) { match = true; - if (server->gameover() == false) - source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support gameover.")); + if (parameters.equalsi("empty"_jrs)) + server->gameoverWhenEmpty(); + if (parameters.equalsi("if empty"_jrs)) + { + if (server->players.size() == 0) + server->gameover(); + } + else if (parameters.equalsi("now"_jrs)) + server->gameover(); + else if (parameters.isEmpty()) + server->gameover(std::chrono::seconds(10)); + else + server->gameover(std::chrono::seconds(parameters.asInt())); } } if (match == false) @@ -1324,7 +1335,7 @@ void GameOverIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString const Jupiter::ReadableString &GameOverIRCCommand::getHelp(const Jupiter::ReadableString &) { - static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Ends the game immediately. Syntax: Gameover"); + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Ends the game immediately. Syntax: Gameover [NOW | Empty | Seconds = 10]"); return defaultHelp; } diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp index d92057a..bf039a1 100644 --- a/RenX.Core/RenX_Server.cpp +++ b/RenX.Core/RenX_Server.cpp @@ -38,6 +38,7 @@ int RenX::Server::think() { if (RenX::Server::connected == false) { + // Not connected; attempt retry if needed if (RenX::Server::maxAttempts < 0 || RenX::Server::attempts < RenX::Server::maxAttempts) { if (std::chrono::steady_clock::now() >= RenX::Server::lastAttempt + RenX::Server::delay) @@ -52,11 +53,13 @@ int RenX::Server::think() } else if (RenX::Server::awaitingPong && std::chrono::steady_clock::now() - RenX::Server::lastActivity >= RenX::Server::pingTimeoutThreshold) // ping timeout { + // Ping timeout; disconnect immediately RenX::Server::sendLogChan(STRING_LITERAL_AS_REFERENCE(IRCCOLOR "04[Error]" IRCCOLOR " Disconnected from Renegade-X server (ping timeout).")); RenX::Server::disconnect(RenX::DisconnectReason::PingTimeout); } else { + // Connected and fine if (RenX::Server::sock.recv() > 0) { Jupiter::ReadableString::TokenizeResult result = Jupiter::ReferenceString::tokenize(RenX::Server::sock.getBuffer(), '\n'); @@ -110,6 +113,12 @@ int RenX::Server::think() if (RenX::Server::buildingUpdateRate != std::chrono::milliseconds::zero() && std::chrono::steady_clock::now() > RenX::Server::lastBuildingListUpdate + RenX::Server::buildingUpdateRate) RenX::Server::updateBuildingList(); } + + if (RenX::Server::gameover_pending && RenX::Server::gameover_time < std::chrono::steady_clock::now()) + { + this->gameover(); + RenX::Server::gameover_pending = false; + } } return 0; } @@ -279,18 +288,27 @@ std::chrono::milliseconds RenX::Server::getGameTime(const RenX::PlayerInfo *play return std::chrono::duration_cast(std::chrono::steady_clock::now() - player->joinTime); } +size_t RenX::Server::getBotCount() const +{ + return RenX::Server::bot_count; +} + RenX::PlayerInfo *RenX::Server::getPlayer(int id) const { - if (RenX::Server::players.size() == 0) return nullptr; + if (RenX::Server::players.size() == 0) + return nullptr; + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) if (node->data->id == id) return node->data; + return nullptr; } RenX::PlayerInfo *RenX::Server::getPlayerByName(const Jupiter::ReadableString &name) const { - if (RenX::Server::players.size() == 0) return nullptr; + if (RenX::Server::players.size() == 0) + return nullptr; for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) if (node->data->name == name) @@ -314,18 +332,25 @@ RenX::PlayerInfo *RenX::Server::getPlayerByName(const Jupiter::ReadableString &n RenX::PlayerInfo *RenX::Server::getPlayerByPartName(const Jupiter::ReadableString &partName) const { - if (RenX::Server::players.size() == 0) return nullptr; + if (RenX::Server::players.size() == 0) + return nullptr; + RenX::PlayerInfo *r = RenX::Server::getPlayerByName(partName); - if (r != nullptr) return r; + if (r != nullptr) + return r; + return RenX::Server::getPlayerByPartNameFast(partName); } RenX::PlayerInfo *RenX::Server::getPlayerByPartNameFast(const Jupiter::ReadableString &partName) const { - if (RenX::Server::players.size() == 0) return nullptr; + if (RenX::Server::players.size() == 0) + return nullptr; + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) if (node->data->name.findi(partName) != Jupiter::INVALID_INDEX) return node->data; + return nullptr; } @@ -587,7 +612,9 @@ void RenX::Server::banPlayer(const RenX::PlayerInfo *player, const Jupiter::Read bool RenX::Server::removePlayer(int id) { - if (RenX::Server::players.size() == 0) return false; + if (RenX::Server::players.size() == 0) + return false; + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) { if (node->data->id == id) @@ -596,6 +623,8 @@ bool RenX::Server::removePlayer(int id) Jupiter::ArrayList &xPlugins = *RenX::getCore()->getPlugins(); for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnPlayerDelete(this, p); + if (p->isBot) + --this->bot_count; delete p; return true; } @@ -619,16 +648,11 @@ bool RenX::Server::updateClientList() { RenX::Server::lastClientListUpdate = std::chrono::steady_clock::now(); - size_t botCount = 0; - for (size_t i = 0; i != RenX::Server::players.size(); i++) - if (RenX::Server::players.get(i)->isBot) - botCount++; - int r = 0; - if (RenX::Server::players.size() != botCount) + if (RenX::Server::players.size() != RenX::Server::bot_count) r = RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cclientvarlist ID\xA0""SCORE\xA0""CREDITS\xA0""PING\n")) > 0; - if (botCount != 0) + if (RenX::Server::bot_count != 0) r |= RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cbotvarlist ID\xA0""SCORE\xA0""CREDITS\n")) > 0; return r != 0; @@ -642,9 +666,29 @@ bool RenX::Server::updateBuildingList() bool RenX::Server::gameover() { + RenX::Server::gameover_when_empty = false; return RenX::Server::send("endmap"_jrs) > 0; } +void RenX::Server::gameover(std::chrono::seconds delay) +{ + if (delay == std::chrono::seconds::zero()) + this->gameover(); + else + { + this->gameover_time = std::chrono::steady_clock::now() + delay; + this->gameover_pending = true; + } +} + +void RenX::Server::gameoverWhenEmpty() +{ + if (this->players.size() != this->bot_count) + this->gameover(); + else + this->gameover_when_empty = true; +} + bool RenX::Server::setMap(const Jupiter::ReadableString &map) { return RenX::Server::send(Jupiter::StringS::Format("changemap %.*s", map.size(), map.ptr())) > 0; @@ -1239,6 +1283,8 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) RenX::exemptionDatabase->exemption_check(r); this->banCheck(r); } + else + ++bot_count; for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnPlayerCreate(this, r); @@ -2185,6 +2231,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnGameOver(this, RenX::WinType::Tie, RenX::TeamType::None, gScore, nScore); } + this->gameover_pending = false; } else { @@ -2278,6 +2325,9 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnPart(this, player); this->removePlayer(player); + + if (this->gameover_when_empty && this->players.size() == this->bot_count) + this->gameover(); } else if (subHeader.equals("Kick;")) { @@ -2801,6 +2851,7 @@ void RenX::Server::wipeData() xPlugins.get(index)->RenX_OnPlayerDelete(this, player); delete player; } + RenX::Server::bot_count = 0; RenX::Server::buildings.emptyAndDelete(); RenX::Server::mutators.emptyAndDelete(); RenX::Server::maps.emptyAndDelete(); diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h index 2256b40..bb779d5 100644 --- a/RenX.Core/RenX_Server.h +++ b/RenX.Core/RenX_Server.h @@ -265,6 +265,13 @@ namespace RenX */ std::chrono::milliseconds getGameTime(const RenX::PlayerInfo *player) const; + /** + * @brief Fetches the number of bots in the server. + * + * @return Number of bots in the server. + */ + size_t getBotCount() const; + /** * @brief Fetches a player's data based on their ID number. * @@ -410,12 +417,24 @@ namespace RenX bool updateBuildingList(); /** - * @brief Forces the current game to end. + * @brief Forces the current game to end immediately. * * @return True on success, false otherwise. */ bool gameover(); + /** + * @brief Forces the game to end, after a given delay. + * + * @param delay The number of seconds from now that the gameover should trigger. + */ + void gameover(std::chrono::seconds delay); + + /** + * @brief Forces the game to end when the server is empty + */ + void gameoverWhenEmpty(); + /** * @brief Forces the current game to end and changes the map. * @@ -922,6 +941,8 @@ namespace RenX void init(); /** Tracking variables */ + bool gameover_when_empty = false; + bool gameover_pending = false; bool pure = false; bool connected = false; bool seamless = false; @@ -946,6 +967,7 @@ namespace RenX int vehicleLimit = 0; int mineLimit = 0; int timeLimit = 0; + size_t bot_count = 0; unsigned int rconVersion = 0; double crateRespawnAfterPickup = 0.0; uuid_func calc_uuid; @@ -954,6 +976,7 @@ namespace RenX std::chrono::steady_clock::time_point lastClientListUpdate = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point lastBuildingListUpdate = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point lastActivity = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point gameover_time; Jupiter::String lastLine; Jupiter::StringS rconUser; Jupiter::StringS gameVersion;