/********************************************************* * Bugblatter Rate Management Extension - V3.3 * ********************************************************* * * * This plug-in is linux & win32 friendly. * * * * Version 3.3: * * * * - Updated to compile on Admin Mod V2.50.56 * * * * Version 3.2: * * * * - Updated for language plugin version 3.3 * * * * Version 3.1: * * * * - No changes * * * * Version 2.6: * * * * - Added colour and timing settings for all * * messageex class on 2.51.xx alpha builds. * * - Copes with plugin_info firing before * * plugin_connect * * * * Version 2.5: * * - Move prominent error messages in log * * * * Version 2.4: * * - Updated for adminmod 2.50.50 * * - Does not return PLUGIN_FAILRE during init * * - Works around bug in calling admin_command bb,,, * * from in a .cfg file saved in DOS format * * * * Version 2.3: * * - Checks values of server.cfg vars during init * * * * Version 2.2: * * - No Changes * * * * Version 2.1: * * - Multilingual * * - Updated for adminmod 2.50.37 * * * * Version 2.0: * * - Playercount() bug from 1.7 was still lurking in * * some situations. Added a rate change in * * plugin_info to correct it * * * * Version 1.9: * * * * - No longer counts bots as players when computing * * rate and doesn't exec commands on them * * - Report can be turned on and off now * * * * Version 1.8: * * * * - sv_minrate and sv_maxrate are now restored if you * * switch from server or full mode to client mode as * * well as off. * * * * - mode is now specified as full/client/server/off * * rather than numeric values * * * * - all commands / vault settings and corresponding * * global variables/ functions have been renamed to * * fit new conventions. * * * * - bbrate_reset and bbrate_report added * * * * Version 1.7: * * * * - Fixed bug in that playercount() was sometimes * * returning one too low during connect() and * * always one too high during disconnect(). * * * * - Logs rate information each time it is changed * * * * Version 1.6: * * - Adjusts cl_rate as well as rate * * - New bb_lan feature to dynamically set local users * * * * Version 1.5: * * - Fixed setting of sv_minrate/sv_maxrate and * * improved player counting. Thanks to ymboc for * * these fixes. * * * * - Returns sv_minrate and sv_maxrate to their * * original values and disables the plugin if you * * set bb_bandwidthmode to 0 (also adapted from code * * by ymboc). * * * * - Registers the right version number ;) * * * * Version 1.4: * * * * - Copes with sv_maxrate and sv_minrate being missing * * from server.cfg. * * * * Version 1.3: * * * * - Removed bb_maxrate and bb_minrate. Plugin now uses * * settings of sv_maxrate and sv_minrate in your * * server.cfg file. * * * * - Plugin now adjusts sv_maxrate and sv_minrate when * * changing users' rates to ensure they don't cheat * * and change their rate back to something high. * * * * Version 1.0 - Initial Release * * * *********************************************************/ #include <core> #include <console> #include <string> #include <admin> #include <adminlib> #include <plugin> #include "settings" #include "ip" #include "clientio" #include "language" #include "connections" new g_Version[]="3.3"; /* Initialisation function */ #define DEFAULT_BANDWIDTH 16384 #define MAX_BANDWIDTH 1048576 #define MIN_BANDWIDTH 2048 #define DEFAULT_MODE 3 #define MAX_MODE 3 #define MIN_MODE 0 #define DEFAULT_LOCAL_USERS 1 #define MAX_LOCAL_USERS 32 #define MIN_LOCAL_USERS 0 #define DEFAULT_IP 0 #define MIN_IP -2147483648 #define MAX_IP 2147483647 #define DEFAULT_REPORT 1 #define MIN_REPORT 0 #define MAX_REPORT 1 #define DEFAULT_MAX_RATE 6144 #define DEFAULT_MIN_RATE 2048 #define SHIFT8 256 #define SHIFT16 65536 #define SHIFT24 16777216 new g_MSG_REPORT_PROMPT[]="Bugblatter Rate Management Configuration:|Configuration du management du rafraichissement Bugblatter:|Bugblatter Rate-Management Konfiguration:"; new g_MSG_RPT_DISABLED[]=" - Rate management is disabled. (bbrate_mode)| - Le management du rafraichissement est desactive. (bbrate_mode)| - Rate-Management ist deaktiviert (bbrate_mode)"; new g_MSG_RPT_SERVER[]=" - Rate management is performed server-side only. (bbrate_mode)| - Le management du rafraichissement est active du cote serveur seulement. (bbrate_mode)| - Rate-Management wird nur auf Server-Seite ausgefuehrt (bbrate_mode)"; new g_MSG_RPT_CLIENT[]=" - Rate management is performed client-side only. (bbrate_mode)| - Le management du rafraichissement est active du cote client seulement. (bbrate_mode)| - Rate-Management wird nur auf Client-Seite ausgefuehrt (bbrate_mode)"; new g_MSG_RPT_BOTH[]=" - Rate management is performed on both the client and server. (bbrate_mode)| - Le management du rafraichissement est active a la fois pour le serveur et les clients. (bbrate_mode)| - Rate-Management wird auf Client- und Server-Seite ausgefuehrt (bbrate_mode)"; new g_MSG_RPT_AVAILABLE[]=" - Available bandwidth is set to %1i / %2iK. (bbrate_bandwidth)| - La bande passante disponible est reglee a %1i / %2iK. (bbrate_bandwidth)| - Verfuegbare Bandbreite ist auf %1i / %2iK gesetzt (bbrate_bandwidth)"; new g_MSG_RPT_MAX[]=" - Maximum rate is %1i. (sv_maxrate in server.cfg)| - Le rafraichissement maximum est %1i. (sv_maxrate dans server.cfg)| - Maximale Rate ist %i. (sv_maxrate in server.cfg)"; new g_MSG_RPT_MIN[]=" - Minimum rate is %1i. (sv_minrate in server.cfg)| - Le rafraichissement minimum est %1i. (sv_minrate dans server.cfg)| - Minimale Rate ist %i. (sv_minrate in server.cfg)"; new g_MSG_RPT_LOCAL[]=" - Fixed places for local users is set to %1i. (bbrate_localusers)| - Le nombre de places fixe pour les utilisateurs locaux est reglee a %1i. (bbrate_localusers)| - Festgelegte Plaetze fuer lokale User ist auf %1i gesetzt"; new g_MSG_RPT_IP[]=" - IP address for local subnet is %1s. (bbrate_lan)| - L'adresse IP du subnet local est %1s. (bbrate_lan)| - IP-Adresse des lokalen Subnets ist %1s (bbrate_lan)"; new g_MSG_RPT_MASK[]=" - Network mask for local subnet is %1s. (bbrate_lan)| - Le masque de sous-reseau du subnet local est %1s. (bbrate_lan)| - Netzwerkmaske des lokalen Subnets ist %1s (bbrate_lan)"; new g_MSG_STATUS_PROMPT[]="Current status:|Status actuel:|Momentaner Status:"; new g_MSG_STATUS_INTERNET[]="Number of Internet players = %1i|Nombre de joueurs d'internet = %1i|Anzahl der Internet-Spieler = %1i"; new g_MSG_STATUS_LAN[]="Number of LAN players = %1i (NOTE: Includes bbrate_localusers count)|Nombre de joueurs en LAN = %1i (NOTE: Inclus le decompte bbrate_localusers)|Anzahl der LAN-Spieler = %1i (Beinhaltet bbrate_localusers)"; new g_MSG_STATUS_BOTS[]="Number of Bots = %1i|Nobre de Bots = %1i|Anzahl an Bots = %1i"; new g_MSG_STATUS_RATE[]="Computed rate = %1i / %2iK|Rafraichissement de l'ordinateur = %1i / %2iK|Berechnete Rate = %1i / %i2K"; /* Config variables */ new g_Bandwidth=DEFAULT_BANDWIDTH; new g_MaxRate=DEFAULT_MAX_RATE; new g_MinRate=DEFAULT_MIN_RATE; new g_LocalUsers=DEFAULT_LOCAL_USERS; new g_Mode=DEFAULT_MODE; new g_LocalIP=0; new g_LocalNetMask=0; new g_Report=DEFAULT_REPORT; /* Status */ new g_UserCount=0; new g_UserLocal=0; new g_Bots=0; new g_Rate=0; new g_ResetMaxRate=0; new g_ResetMinRate=0; new g_Local[MAX_PLAYERS+1]; new g_Registered=0; forward RegisterPlugin(); forward BBRateBandwidth(HLCommand,HLData,HLUserName,UserIndex); forward BBRateMode(HLCommand,HLData,HLUserName,UserIndex); forward BBRateLocalUsers(HLCommand,HLData,HLUserName,UserIndex); forward BBRateLan(HLCommand,HLData,HLUserName,UserIndex); forward BBRateReport(HLCommand,HLData,HLUserName,UserIndex); forward BBRateReset(HLCommand,HLData,HLUserName,UserIndex); forward SetRate(Offset,Force); forward CurrentLocalUsers(); forward ShowConfig(Force,UserIndex); public plugin_init() { plugin_registerinfo("Bugblatter's Rate Management Plugin","Optimises server bandwidth usage and prevents spikes",g_Version); /* Check server is configured properly */ new fOK = checkAllowClientExec(); fOK = checkVaultOK() && fOK; fOK = checkMinRate() && fOK; fOK = checkMaxRate() && fOK; if (fOK == 0) { return PLUGIN_CONTINUE; } /* No need to abort if this one fails */ checkLanguage(); /* Read saved settings from vault */ readvaultnum("bbrate_localusers",g_LocalUsers, DEFAULT_LOCAL_USERS,MIN_LOCAL_USERS,MAX_LOCAL_USERS); readvaultnum("bbrate_bandwidth",g_Bandwidth, DEFAULT_BANDWIDTH,MIN_BANDWIDTH,MAX_BANDWIDTH); readvaultnum("bbrate_mode",g_Mode, DEFAULT_MODE,MIN_MODE,MAX_MODE); readvaultnum("bbrate_report",g_Report,DEFAULT_REPORT,MIN_REPORT,MAX_REPORT); new Buffer[16]=""; get_vaultdata("bbrate_localip",Buffer,16); strtoip(Buffer,g_LocalIP); get_vaultdata("bbrate_localnetmask",Buffer,16); strtoip(Buffer,g_LocalNetMask); g_MaxRate = getvar("sv_maxrate"); if (g_MaxRate == 0) { g_MaxRate = 6144; configError("sv_maxrate must be set in server.cfg for plugin_blatt_rate to work properly."); return PLUGIN_CONTINUE; } else { g_ResetMaxRate = 1; } g_MinRate = getvar("sv_minrate"); if (g_MinRate == 0) { g_MinRate = 2048; configError("sv_minrate must be set in server.cfg for plugin_blatt_rate to work properly."); return PLUGIN_CONTINUE; } else { g_ResetMinRate = 1; } new i=0; for(i=0;i<=MAX_PLAYERS;i++) { g_Local[i]=0; } language_init(); RegisterPlugin(); return PLUGIN_CONTINUE; } RegisterPlugin() { /* Register commands with adminmod */ plugin_registercmd("bbrate_bandwidth","BBRateBandwidth",ACCESS_CONFIG, "bbrate_bandwidth <rate> | <kbps>K: Sets internet connection bandwidth in rate, or Kbps"); plugin_registercmd("bbrate_localusers","BBRateLocalUsers",ACCESS_CONFIG, "bbrate_localusers <n>: Sets number of users connecting from the LAN"); plugin_registercmd("bbrate_mode","BBRateMode",ACCESS_CONFIG, "bbrate_mode < ^"off^" | ^"server^" | ^"client^" | ^"full^">: Turns client and server rate managmenet on/off"); plugin_registercmd("bbrate_lan","BBRateLan",ACCESS_CONFIG, "bbrate_lan <ipaddress> <netmask>: Defines the LAN subnet to enable dynamic counting of local users"); plugin_registercmd("bbrate_report","BBRateReport",ACCESS_CONFIG, "bbrate_report [ ^"on^" | ^"off^" ]: Shows the rate management config, and enables/disable report after every command"); plugin_registercmd("bbrate_reset","BBRateReset",ACCESS_CONFIG, "bbrate_reset: Restores the rate management configuration to the default settings"); g_Registered=1; } /* User conneciton handlers */ public plugin_connect(HLUserName, HLIP, UserIndex) { if (g_Registered ==0) { return PLUGIN_FAILURE; } PlayerConnected(UserIndex); new Data[MAX_DATA_LENGTH]; safe_convert(HLIP,Data,MAX_DATA_LENGTH); g_Local[UserIndex]=0; new IP; if (strtoip(Data,IP)==0) { /* Must be a bot joining, although that's not supposed to cause * a plugin_connect event. Ignore it anyway */ return PLUGIN_CONTINUE; } if (g_LocalIP != 0) { if ((g_LocalIP & g_LocalNetMask) == (IP & g_LocalNetMask)) { g_Local[UserIndex] = 1; } else { g_Local[UserIndex] = 0; } } SetRate(0,0); return PLUGIN_CONTINUE; } public plugin_info(HLOldName, HLNewName, UserIndex) { if (g_Registered ==0) { return PLUGIN_FAILURE; } if (IsPlayerConnected(UserIndex)==0) { return PLUGIN_CONTINUE; } SetRate(0,0); return PLUGIN_CONTINUE; } public plugin_disconnect(HLUserName, UserIndex) { if (g_Registered ==0) { return PLUGIN_FAILURE; } PlayerDisconnected(UserIndex); new UserName[MAX_NAME_LENGTH]; new WONID; safe_convert(HLUserName,UserName,MAX_NAME_LENGTH); g_Local[UserIndex]=0; if (get_userWONID(UserName,WONID)) { if (WONID != 0) { /* -1 because the disconnecting user is still included in the count */ SetRate(-1,0); } } return PLUGIN_CONTINUE; } /* Admin command handlers */ public BBRateBandwidth(HLCommand,HLData,HLUserName,UserIndex) { new Data[MAX_DATA_LENGTH]; safe_convert(HLData,Data,MAX_DATA_LENGTH); g_UserCount=realplayercount(g_Bots); /* Check for data being supplied in Kbps */ new len = strlen(Data); if ( len > 0) { if ((Data[len-1] == 'K') || (Data[len-1] == 'k')) { if (readHLnum(HLData,g_Bandwidth,DEFAULT_BANDWIDTH/128,MIN_BANDWIDTH/128,MAX_BANDWIDTH/128)) { g_Bandwidth = g_Bandwidth * 128; writevaultnum("bbrate_bandwidth",g_Bandwidth); SetRate(0,1); } } else { if (readHLnum(HLData,g_Bandwidth,DEFAULT_BANDWIDTH,MIN_BANDWIDTH,MAX_BANDWIDTH)) { writevaultnum("bbrate_bandwidth",g_Bandwidth); SetRate(0,1); } } } ShowConfig(0,UserIndex); return PLUGIN_HANDLED; } public BBRateMode(HLCommand,HLData,HLUserName,UserIndex) { g_UserCount=realplayercount(g_Bots); new Data[MAX_DATA_LENGTH]; safe_convert(HLData,Data,MAX_DATA_LENGTH); if (streq(Data,"off")) { g_Mode = 0; } else if (streq(Data,"server")) { g_Mode = 1; } else if (streq(Data,"client")) { g_Mode = 2; } else if (streq(Data,"full")) { g_Mode = 3; } else { selfmessage("Usage: bbrate_mode off | client | server | full"); return PLUGIN_HANDLED; } writevaultnum("bbrate_mode",g_Mode); SetRate(0,1); new RateCmd[MAX_TEXT_LENGTH]; if ((g_Mode == 0) || (g_Mode == 2)) { if (g_ResetMaxRate) { snprintf(RateCmd,MAX_TEXT_LENGTH,"sv_maxrate %i",g_MaxRate); exec(RateCmd); } if (g_ResetMinRate) { snprintf(RateCmd,MAX_TEXT_LENGTH,"sv_minrate %i",g_MinRate); exec(RateCmd); } } ShowConfig(0,UserIndex); return PLUGIN_HANDLED; } public BBRateLocalUsers(HLCommand,HLData,HLUserName,UserIndex) { g_UserCount=realplayercount(g_Bots); if (readHLnum(HLData,g_LocalUsers,DEFAULT_LOCAL_USERS,MIN_LOCAL_USERS,MAX_LOCAL_USERS)) { writevaultnum("bbrate_localusers",g_LocalUsers); SetRate(0,1); } ShowConfig(0,UserIndex); return PLUGIN_HANDLED; } public BBRateLan(HLCommand,HLData,HLUserName,UserIndex) { g_UserCount=realplayercount(g_Bots); new Data[MAX_DATA_LENGTH]; safe_convert(HLData,Data,MAX_DATA_LENGTH); new strIP[MAX_DATA_LENGTH]; new strMask[MAX_DATA_LENGTH]; if (strsplit(Data," ",strIP,MAX_DATA_LENGTH,strMask,MAX_DATA_LENGTH) == 2) { if (strtoip(strIP,g_LocalIP) && strtoip(strMask,g_LocalNetMask)) { set_vaultdata("bbrate_localip",strIP); set_vaultdata("bbrate_localnetmask",strMask); ShowConfig(0,UserIndex); return PLUGIN_HANDLED; } } selfmessage("usage: bbrate_lan <ipaddress> <subnetmask>"); return PLUGIN_HANDLED; } public BBRateReport(HLCommand,HLData,HLUserName,UserIndex) { if (readHLonoff(HLData,g_Report,DEFAULT_REPORT,MIN_REPORT,MAX_REPORT)) { writevaultnum("bbrate_report",g_Report); ShowConfig(0,UserIndex); } else { ShowConfig(1,UserIndex); } return PLUGIN_HANDLED; } public BBRateReset(HLCommand,HLData,HLUserName,UserIndex) { g_UserCount=realplayercount(g_Bots); g_Bandwidth = DEFAULT_BANDWIDTH; writevaultnum("bbrate_bandwidth",g_Bandwidth); g_Mode = DEFAULT_MODE; writevaultnum("bbrate_mode",g_Mode); g_LocalUsers=DEFAULT_LOCAL_USERS; writevaultnum("bbrate_localusers",g_LocalUsers); g_LocalIP=0; g_LocalNetMask=0; set_vaultdata("bbrate_localip","0.0.0.0"); set_vaultdata("bbrate_localnetmask","0.0.0.0"); SetRate(0,1); ShowConfig(0,UserIndex); return PLUGIN_HANDLED; } /* Does the real work */ SetRate(Offset,Force) { new RateCmd[MAX_TEXT_LENGTH]; new i = realplayercount(g_Bots)+Offset; if ((i == g_UserCount) && (Force==0)) { /*No need to change rate - number of users hasn't changed */ return 0; } g_UserCount = i; g_UserLocal = g_LocalUsers + CurrentLocalUsers(); new RemoteUsers = max(0,g_UserCount - g_UserLocal); if (RemoteUsers < 1) { RemoteUsers = 1; } g_Rate = g_Bandwidth / RemoteUsers; if (g_Rate>g_MaxRate) { g_Rate = g_MaxRate; } if (g_Rate<g_MinRate) { g_Rate = g_MinRate; } if ((g_Mode & 1) > 0) { snprintf(RateCmd,MAX_TEXT_LENGTH,"sv_maxrate %i",g_Rate); exec(RateCmd); snprintf(RateCmd,MAX_TEXT_LENGTH,"sv_minrate %i",g_Rate); exec(RateCmd); } if ((g_Mode & 2) > 0) { snprintf(RateCmd,MAX_TEXT_LENGTH,"rate %i",g_Rate); safe_execall(RateCmd); snprintf(RateCmd,MAX_TEXT_LENGTH,"cl_rate %i",g_Rate); safe_execall(RateCmd); } new Msg[MAX_TEXT_LENGTH]; snprintf(Msg,MAX_TEXT_LENGTH,"Rate change: %i users, %i local users, %i bots, computed rate %i",g_UserCount,g_UserLocal,g_Bots,g_Rate); log(Msg); return 0; } CurrentLocalUsers() { new i; new count=0; for(i=0;i<=MAX_PLAYERS;i++) { count = count + g_Local[i]; } return count; } ShowConfig(Force,UserIndex) { if ((Force==0) && (g_Report==0)) { return PLUGIN_HANDLED; } language_say(UserIndex,g_MSG_REPORT_PROMPT,print_type:print_console); if (g_Mode == 0) { language_say(UserIndex,g_MSG_RPT_DISABLED,print_type:print_console); } else if (g_Mode == 1) { language_say(UserIndex,g_MSG_RPT_SERVER,print_type:print_console); } else if (g_Mode == 2) { language_say(UserIndex,g_MSG_RPT_CLIENT,print_type:print_console); } else if (g_Mode == 3) { language_say(UserIndex,g_MSG_RPT_BOTH,print_type:print_console); } language_sayf(UserIndex,g_MSG_RPT_AVAILABLE,print_type:print_console,0,0,0,0,g_Bandwidth,g_Bandwidth/128); language_sayf(UserIndex,g_MSG_RPT_MAX,print_type:print_console,0,0,0,0,g_MaxRate); language_sayf(UserIndex,g_MSG_RPT_MIN,print_type:print_console,0,0,0,0,g_MinRate); language_sayf(UserIndex,g_MSG_RPT_LOCAL,print_type:print_console,0,0,0,0,g_LocalUsers); new data[20]; iptostr(g_LocalIP,data); language_sayf(UserIndex,g_MSG_RPT_IP,print_type:print_console,0,0,0,0,data); iptostr(g_LocalNetMask,data); language_sayf(UserIndex,g_MSG_RPT_MASK,print_type:print_console,0,0,0,0,data); language_say(UserIndex,g_MSG_STATUS_PROMPT,print_type:print_console); language_sayf(UserIndex,g_MSG_STATUS_INTERNET,print_type:print_console,0,0,0,0,max(0,g_UserCount-g_UserLocal)); language_sayf(UserIndex,g_MSG_STATUS_LAN,print_type:print_console,0,0,0,0,g_UserLocal); language_sayf(UserIndex,g_MSG_STATUS_BOTS,print_type:print_console,0,0,0,0,g_Bots); language_sayf(UserIndex,g_MSG_STATUS_RATE,print_type:print_console,0,0,0,0,g_Rate,g_Rate/128); return 0; }