Browse Source

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
pull/3/head
Jessica James 9 years ago
parent
commit
7e9b92907d
  1. BIN
      Release/Plugins/RenX.Core.lib
  2. 19
      RenX.Commands/RenX_Commands.cpp
  3. 77
      RenX.Core/RenX_Server.cpp
  4. 25
      RenX.Core/RenX_Server.h

BIN
Release/Plugins/RenX.Core.lib

Binary file not shown.

19
RenX.Commands/RenX_Commands.cpp

@ -1300,7 +1300,7 @@ void GameOverIRCCommand::create()
this->setAccessLevel(3); this->setAccessLevel(3);
} }
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 &parameters)
{ {
Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); Jupiter::IRC::Client::Channel *chan = source->getChannel(channel);
if (chan != nullptr) if (chan != nullptr)
@ -1313,8 +1313,19 @@ void GameOverIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString
if (server->isLogChanType(type)) if (server->isLogChanType(type))
{ {
match = true; match = true;
if (server->gameover() == false) if (parameters.equalsi("empty"_jrs))
source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support gameover.")); 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) if (match == false)
@ -1324,7 +1335,7 @@ void GameOverIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString
const Jupiter::ReadableString &GameOverIRCCommand::getHelp(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; return defaultHelp;
} }

77
RenX.Core/RenX_Server.cpp

@ -38,6 +38,7 @@ int RenX::Server::think()
{ {
if (RenX::Server::connected == false) if (RenX::Server::connected == false)
{ {
// Not connected; attempt retry if needed
if (RenX::Server::maxAttempts < 0 || RenX::Server::attempts < RenX::Server::maxAttempts) if (RenX::Server::maxAttempts < 0 || RenX::Server::attempts < RenX::Server::maxAttempts)
{ {
if (std::chrono::steady_clock::now() >= RenX::Server::lastAttempt + RenX::Server::delay) 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 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::sendLogChan(STRING_LITERAL_AS_REFERENCE(IRCCOLOR "04[Error]" IRCCOLOR " Disconnected from Renegade-X server (ping timeout)."));
RenX::Server::disconnect(RenX::DisconnectReason::PingTimeout); RenX::Server::disconnect(RenX::DisconnectReason::PingTimeout);
} }
else else
{ {
// Connected and fine
if (RenX::Server::sock.recv() > 0) if (RenX::Server::sock.recv() > 0)
{ {
Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> result = Jupiter::ReferenceString::tokenize(RenX::Server::sock.getBuffer(), '\n'); Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> 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) if (RenX::Server::buildingUpdateRate != std::chrono::milliseconds::zero() && std::chrono::steady_clock::now() > RenX::Server::lastBuildingListUpdate + RenX::Server::buildingUpdateRate)
RenX::Server::updateBuildingList(); 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; return 0;
} }
@ -279,18 +288,27 @@ std::chrono::milliseconds RenX::Server::getGameTime(const RenX::PlayerInfo *play
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - player->joinTime); return std::chrono::duration_cast<std::chrono::milliseconds>(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 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<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) for (Jupiter::DLList<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next)
if (node->data->id == id) if (node->data->id == id)
return node->data; return node->data;
return nullptr; return nullptr;
} }
RenX::PlayerInfo *RenX::Server::getPlayerByName(const Jupiter::ReadableString &name) const 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<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) for (Jupiter::DLList<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next)
if (node->data->name == name) 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 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); RenX::PlayerInfo *r = RenX::Server::getPlayerByName(partName);
if (r != nullptr) return r; if (r != nullptr)
return r;
return RenX::Server::getPlayerByPartNameFast(partName); return RenX::Server::getPlayerByPartNameFast(partName);
} }
RenX::PlayerInfo *RenX::Server::getPlayerByPartNameFast(const Jupiter::ReadableString &partName) const 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<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) for (Jupiter::DLList<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next)
if (node->data->name.findi(partName) != Jupiter::INVALID_INDEX) if (node->data->name.findi(partName) != Jupiter::INVALID_INDEX)
return node->data; return node->data;
return nullptr; return nullptr;
} }
@ -587,7 +612,9 @@ void RenX::Server::banPlayer(const RenX::PlayerInfo *player, const Jupiter::Read
bool RenX::Server::removePlayer(int id) 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<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) for (Jupiter::DLList<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next)
{ {
if (node->data->id == id) if (node->data->id == id)
@ -596,6 +623,8 @@ bool RenX::Server::removePlayer(int id)
Jupiter::ArrayList<RenX::Plugin> &xPlugins = *RenX::getCore()->getPlugins(); Jupiter::ArrayList<RenX::Plugin> &xPlugins = *RenX::getCore()->getPlugins();
for (size_t i = 0; i < xPlugins.size(); i++) for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnPlayerDelete(this, p); xPlugins.get(i)->RenX_OnPlayerDelete(this, p);
if (p->isBot)
--this->bot_count;
delete p; delete p;
return true; return true;
} }
@ -619,16 +648,11 @@ bool RenX::Server::updateClientList()
{ {
RenX::Server::lastClientListUpdate = std::chrono::steady_clock::now(); 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; 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; 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; r |= RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cbotvarlist ID\xA0""SCORE\xA0""CREDITS\n")) > 0;
return r != 0; return r != 0;
@ -642,9 +666,29 @@ bool RenX::Server::updateBuildingList()
bool RenX::Server::gameover() bool RenX::Server::gameover()
{ {
RenX::Server::gameover_when_empty = false;
return RenX::Server::send("endmap"_jrs) > 0; 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) bool RenX::Server::setMap(const Jupiter::ReadableString &map)
{ {
return RenX::Server::send(Jupiter::StringS::Format("changemap %.*s", map.size(), map.ptr())) > 0; 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); RenX::exemptionDatabase->exemption_check(r);
this->banCheck(r); this->banCheck(r);
} }
else
++bot_count;
for (size_t i = 0; i < xPlugins.size(); i++) for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnPlayerCreate(this, r); 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++) for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnGameOver(this, RenX::WinType::Tie, RenX::TeamType::None, gScore, nScore); xPlugins.get(i)->RenX_OnGameOver(this, RenX::WinType::Tie, RenX::TeamType::None, gScore, nScore);
} }
this->gameover_pending = false;
} }
else else
{ {
@ -2278,6 +2325,9 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line)
for (size_t i = 0; i < xPlugins.size(); i++) for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnPart(this, player); xPlugins.get(i)->RenX_OnPart(this, player);
this->removePlayer(player); this->removePlayer(player);
if (this->gameover_when_empty && this->players.size() == this->bot_count)
this->gameover();
} }
else if (subHeader.equals("Kick;")) else if (subHeader.equals("Kick;"))
{ {
@ -2801,6 +2851,7 @@ void RenX::Server::wipeData()
xPlugins.get(index)->RenX_OnPlayerDelete(this, player); xPlugins.get(index)->RenX_OnPlayerDelete(this, player);
delete player; delete player;
} }
RenX::Server::bot_count = 0;
RenX::Server::buildings.emptyAndDelete(); RenX::Server::buildings.emptyAndDelete();
RenX::Server::mutators.emptyAndDelete(); RenX::Server::mutators.emptyAndDelete();
RenX::Server::maps.emptyAndDelete(); RenX::Server::maps.emptyAndDelete();

25
RenX.Core/RenX_Server.h

@ -265,6 +265,13 @@ namespace RenX
*/ */
std::chrono::milliseconds getGameTime(const RenX::PlayerInfo *player) const; 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. * @brief Fetches a player's data based on their ID number.
* *
@ -410,12 +417,24 @@ namespace RenX
bool updateBuildingList(); bool updateBuildingList();
/** /**
* @brief Forces the current game to end. * @brief Forces the current game to end immediately.
* *
* @return True on success, false otherwise. * @return True on success, false otherwise.
*/ */
bool gameover(); 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. * @brief Forces the current game to end and changes the map.
* *
@ -922,6 +941,8 @@ namespace RenX
void init(); void init();
/** Tracking variables */ /** Tracking variables */
bool gameover_when_empty = false;
bool gameover_pending = false;
bool pure = false; bool pure = false;
bool connected = false; bool connected = false;
bool seamless = false; bool seamless = false;
@ -946,6 +967,7 @@ namespace RenX
int vehicleLimit = 0; int vehicleLimit = 0;
int mineLimit = 0; int mineLimit = 0;
int timeLimit = 0; int timeLimit = 0;
size_t bot_count = 0;
unsigned int rconVersion = 0; unsigned int rconVersion = 0;
double crateRespawnAfterPickup = 0.0; double crateRespawnAfterPickup = 0.0;
uuid_func calc_uuid; 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 lastClientListUpdate = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point lastBuildingListUpdate = 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 lastActivity = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point gameover_time;
Jupiter::String lastLine; Jupiter::String lastLine;
Jupiter::StringS rconUser; Jupiter::StringS rconUser;
Jupiter::StringS gameVersion; Jupiter::StringS gameVersion;

Loading…
Cancel
Save