/* bzflag * Copyright (c) 1993-2021 Tim Riker * * This package is free software; you can redistribute it and/or * modify it under the terms of the license found in the file * named COPYING that should have accompanied this file. * * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ // TimeLimit.cpp : bzfs plugin to change/set the match duration // #include "bzfsAPI.h" #include #include #include #define MAX_TIMES 20 class TimeLimit : public bz_Plugin, public bz_CustomSlashCommandHandler { public: virtual const char* Name () { return "Time Limit"; } virtual void Init ( const char* config ); virtual void Cleanup (); virtual void Event ( bz_EventData *eventData ); virtual bool SlashCommand ( int playerID, bz_ApiString, bz_ApiString, bz_APIStringList*); protected: private: }; BZ_PLUGIN(TimeLimit) // variable to save the original -time value float saveTimeLimit = 0; // list to hold the available match durations bz_APIStringList* timeList = bz_newStringList(); // Displays the available match durations void showMatchDurations(int playerID) { bz_sendTextMessagef (BZ_SERVER, playerID, "Not a valid match duration, valid match durations are : "); for (unsigned i=0; i < timeList->size(); i++) bz_sendTextMessagef (BZ_SERVER, playerID, "* %s minute(s)",timeList->get(i).c_str()); } // Checks if it's a valid match duration or not bool isValidTime ( float timelimit ) { if ( timeList->size() == 0 ) return true; for (unsigned i=0; i < timeList->size(); i++) { if ( atof(timeList->get(i).c_str()) == timelimit ) return true; } return false; } void TimeLimit::Event ( bz_EventData *eventData ) { switch (eventData->eventType) { case bz_ePlayerJoinEvent: { // if it's the first player that joins, then reset the time to default if ( bz_getPlayerCount() == 1 && bz_isTimeManualStart() && !bz_isCountDownActive() && !bz_isCountDownInProgress()) bz_setTimeLimit(saveTimeLimit); } break; //reset the time to default at gameover case bz_eGameEndEvent: { bz_setTimeLimit(saveTimeLimit); } break; default: { // do nothing } } } std::string convertIntToString(const unsigned int integer) { std::ostringstream ostr; ostr << integer; return ostr.str(); } void parseCommand ( const char* commandLine ) { const size_t len = strlen(commandLine); if (len != 0) { unsigned int range_begin, range_end; char junk; if (sscanf(commandLine, "%u-%u%c", &range_begin, &range_end, &junk) == 2) { while (range_begin <= range_end) timeList->push_back(convertIntToString(range_begin++)); } else if (strspn(commandLine, ",0123456789") == len) timeList->tokenize(commandLine, ",", MAX_TIMES, false); } } bool TimeLimit::SlashCommand ( int playerID, bz_ApiString cmd, bz_ApiString, bz_APIStringList* cmdParams ) { if (strcasecmp (cmd.c_str(), "timelimit")) return false; // Check permissions if (! bz_hasPerm(playerID,"TIMELIMIT")) { bz_sendTextMessagef (BZ_SERVER, playerID, "You do not have permission to run the timelimit command"); return true; } // If the server is not configured for manual countdown the timelimit // command can't be used if (! bz_isTimeManualStart()) { bz_sendTextMessagef (BZ_SERVER, playerID, "This server was not configured for manual clock countdowns"); return true; } if (cmdParams->get(0).c_str()[0] == '\0') { bz_sendTextMessagef (BZ_SERVER, playerID, "Usage : /timelimit |show|reset"); return true; } // displaying the current timelimit if (strcasecmp(cmdParams->get(0).c_str(),"show") == 0 ) { bz_sendTextMessagef (BZ_SERVER, playerID,"Match duration is set to %.0f minute(s)",(bz_getTimeLimit() / 60)); return true; } // check if there is already a countdown in progress or if a match is // already in progress if ( bz_isCountDownInProgress() ) { bz_sendTextMessagef (BZ_SERVER, playerID, "There is a countdown already in progress, match duration can't be changed now"); return true; } else if ( bz_isCountDownActive() ) { bz_sendTextMessagef (BZ_SERVER, playerID, "A game is already in progress, match duration can't be changed now"); return true; } bz_BasePlayerRecord *playerRecord; playerRecord = bz_getPlayerByIndex(playerID); // resets the timer to the default if (strcasecmp(cmdParams->get(0).c_str(),"reset") == 0 ) { bz_setTimeLimit(saveTimeLimit); bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Match duration reset to %.0f minute(s) by %s",(bz_getTimeLimit() / 60), playerRecord->callsign.c_str()); return true; } unsigned i, nonumber=0; for (i=0; i < strlen(cmdParams->get(0).c_str()); i++) { if (isdigit(cmdParams->get(0).c_str()[i]) == 0) nonumber=1; } if (nonumber == 0 ) { float limit = (float)atof(cmdParams->get(0).c_str()); // Don't allow timelimit being equal or lower then 0 if (limit > 0 ) { if (! isValidTime(limit)) { showMatchDurations(playerID); return true; } bz_setTimeLimit(limit * 60); bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Match duration set to %.0f minute(s) by %s",(bz_getTimeLimit() / 60), playerRecord->callsign.c_str()); } else { bz_sendTextMessagef (BZ_SERVER, playerID, "Match duration can't be equal or lower then 0"); return true; } } else { bz_sendTextMessagef (BZ_SERVER, playerID, "Not a correct value"); return true; } return true; } void TimeLimit::Init ( const char* commandLine ) { parseCommand(commandLine); saveTimeLimit = bz_getTimeLimit(); bz_registerCustomSlashCommand ("timelimit",this); Register(bz_ePlayerJoinEvent); Register(bz_eGameEndEvent); } void TimeLimit::Cleanup ( void ) { // set default timelimit back before unloading //bz_setTimeLimit(saveTimeLimit); bz_removeCustomSlashCommand ("timelimit"); Flush(); // set default timelimit back before unloading bz_setTimeLimit(saveTimeLimit); } // Local Variables: *** // mode: C++ *** // tab-width: 4 *** // c-basic-offset: 4 *** // indent-tabs-mode: nil *** // End: *** // ex: shiftwidth=4 tabstop=4