1// QFAdmin for QuakeForge 0.5.3+ 2// Copyright (C) 2003 Harry Roberts 3 4// This program is free software; you can redistribute it and/or 5// modify it under the terms of the GNU General Public License 6// as published by the Free Software Foundation; either version 2 7// of the License, or (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12// 13// See the GNU General Public License for more details. 14// 15// You should have received a copy of the GNU General Public License 16// along with this program; if not, write to: 17// 18// Free Software Foundation, Inc. 19// 59 Temple Place - Suite 330 20// Boston, MA 02111-1307, USA 21 22// Installing: 23// Put qfadmin.gib in your server's gamedir (or id1 to be globally available) 24// and put "exec qfadmin.gib" in your server.cfg. 25 26// Configuring: 27// All qfamdin configuration is done via the "qfadmin" command. 28// 29// qfadmin sub-commands: 30// help - Show list of commands & brief description 31// 32// enable <name> - Enable a !function 33// disable <name> - Disable a !function 34// 35// set <name> <value> - Manually set a configuration value 36// unset <name> - Manually unset a configuration value 37// value <name> - Show a configuration value 38// 39// maps [map1 ...] - Show/set the list of maps available for voting 40// maplist <file> - Load the maplist from a file 41// motd [yes/no] - Show the motd upon connect? 42// motdfile <file> - File containing the motd 43// 44// qfadmin configuration values: 45// cheater.action - What do do when somebody is !cheater'd out (kick or ban) 46// If an action is unknown (e.g. no kick/ban) it will default to kick 47// cheater.bantime - How long they should be banned for (if action is ban) 48 49// Notes about the motd file: 50// Special tokens can be embedded in the motd file which are replaced when sent to the client 51// #players# - Current number of players connected to the server 52// #deathmatch# - Current deathmatch mode 53 54// Sample Configuration: 55// This example is taken from my server.cfg 56// 57// exec qfadmin.gib 58// qfadmin maps dm1 dm3 dm5 dm2 59// qfadmin set cheater.action ban 60// qfadmin set cheater.bantime 20 61// qfadmin motd yes 62// qfadmin motdfile welcome.txt 63 64// User commands: 65// All these commands are used by saying !commandname as a regular user. 66// Team talk is ignored. 67// 68// !version - Show the QFAdmin version running 69// !cheater <id> - Vote to kick/ban somebody 70// !map <name> - Vote to change map 71// !maps - Show a list of maps 72 73domain qfadmin 74 75global uservote cmds mapvote config 76//global cvsheader = "$Id$" 77global qfadminversion = "1.17" 78 79// QFAdmin console interface 80function qfadmin { 81 local cmd tmp 82 83 cmd = $args[1] 84 85 // Set a configuration value 86 if $(equal $cmd "set") { 87 tmp = $args[2] 88 config.$tmp = $args[3] 89 90 // Unset a configuration value 91 } else if $(equal $cmd "unset") { 92 tmp = $args[2] 93 94 ifnot $(length $config.tmp) { 95 echo "QFAdmin: value not set" 96 return 97 } 98 99 delete config.${tmp} 100 101 // Echo a configuration value 102 } else if $(equal $cmd "value") { 103 tmp = $args[2] 104 105 ifnot $(length ${config.$tmp}) { 106 echo "QFAdmin: value not set" 107 return 108 } 109 110 echo "QFAdmin: value of ", $tmp, " is \"", ${config.$tmp}, "\"" 111 112 // Enable a command 113 } else if $(equal $cmd "enable") { 114 tmp = $args[2] 115 116 ifnot #cmd.$tmp { 117 echo "QFAdmin: command ", $tmp, " doesnt exist" 118 return 119 } 120 121 config.disable.${tmp} = "yes" 122 123 // Disable a command 124 } else if $(equal $cmd "disable") { 125 tmp = $args[2] 126 127 ifnot #cmd.$tmp { 128 echo "QFAdmin: command ", $tmp, " doesnt exist" 129 return 130 } 131 132 delete config.disable.$tmp 133 134 // View the list of voteable maps 135 } else if $(equal $cmd "maps") { 136 if (#args == 2) { 137 ifnot #config.maps { 138 echo "QFAdmin: no maps available" 139 return 140 } 141 142 echo "QFAdmin: maps available are" @config.maps 143 return 144 } 145 146 config.maps = @args[2:] 147 148 // Load a list of maps from a file 149 } else if $(equal $cmd "maplist") { 150// local line tmplist 151 152 if (#args == 2) { 153 echo "QFAdmin: must specify file to load maplist from" 154 return 155 } 156 157// tmp = $args[2] 158 159// for line in $(split $(file::read $tmp) "\n") { 160// tmplist = $tmplist, " ", $line 161// } 162 163// config.maps = @tmplist 164 config.maps = $(split $(file::read $args[2]) "\n") 165 166 } else if $(equal $cmd "motd") { 167 if (#args == 2) { 168 ifnot $(length ${config.motd}) { 169 config.motd = "no" 170 } 171 172 echo "QFAdmin: motd is set to \"", ${config.motd}, "\"" 173 return 174 } 175 176 ifnot ($(equal $args[2] "yes") || $(equal $args[2] "no")) { 177 echo "QFAdmin: must be set either yes or no" 178 return 179 } 180 181 config.motd = $args[2] 182 183 } else if $(equal $cmd "motdfile") { 184 if (#args == 2) { 185 ifnot $(length ${config.motdfile}) { 186 echo "QFAdmin: no motd file set" 187 return 188 } 189 190 echo "QFAdmin: motd file is \"", ${config.motdfile}, "\"" 191 return 192 } 193 194 ifnot $(count $(file::find $args[2])) { 195 echo "QFAdmin: cannot find motd file!" 196 return 197 } 198 199 config.motdfile = $args[2] 200 201 } else if $(equal $cmd "version") { 202 print "QFAdmin: ", $(qfadmin::getVersion), "\n" 203 204 // Print help information 205 } else if $(equal $cmd "help") { 206 echo "QFAdmin Help:" 207 echo " set - set a config value" 208 echo " unset - unset a config value" 209 echo " value - display a config value" 210 echo " enable - enable a command" 211 echo " disable - disable a command" 212 echo " maps - display/set the list of maps" 213 echo " maplist - load the maplist from a file" 214 echo " motd - show the motd upon connect" 215 echo " motdfile - file to read motd from" 216 echo " version - show qfadmin version" 217 218 } else { 219 echo "QFAdmin: unknown command \"", $cmd, "\"" 220 } 221} 222 223// Initilize QFAdmin Settings 224function qfadmin::init { 225 function::export qfadmin 226 ifnot ${config.cheater.action} { 227 config.cheater.action = "ban" 228 } 229 230 ifnot ${config.cheater.bantime} { 231 config.cheater.bantime = 60 232 } 233} 234 235// Show version information 236function qfadmin::doVersion { 237 say $(qfadmin::getVersion) 238} 239 240// Return the current version 241function qfadmin::getVersion { 242// local tmp tmp2 243 244// tmp = $(split $cvsheader) 245 246// if $(equal $tmp[6] "Exp") { 247// tmp2 = "Beta" 248// } else if $(equal $tmp[6] "Stab") { 249// tmp2 = "Stable" 250// } else if $(equal $tmp[6] "Rel") { 251// tmp2 = "Release" 252// } 253 254// return "QFAdmin v", $tmp[2], " (", $tmp[3], " ", $tmp2, ") by Harry Roberts" 255 return "QFAdmin v", $qfadminversion, " by Harry Roberts" 256} 257 258// Clear uservore & mapvote vars 259function qfadmin::clearVars { 260 delete uservote 261 delete mapvote 262 global uservote 263 global mapvote 264} 265 266// Get the # of clients logged on 267function qfadmin::getClientNum { 268 return $(count $(client::getList)) 269} 270 271// Vote to kick/ban somebody 272function qfadmin::doCheater { 273 local playerid isvalidid voteid lastvoteid 274 local name id 275 276 id = $args[1] 277 name = $args[2] 278 voteid = $args[3] 279 280 // They cant cheater their own id!!! 281 if ($id == $voteid) { 282 tell $id You cant cheater yourself 283 return 284 } 285 286 // Check the player exists on the server 287 for playerid in $(client::getList) { 288 if ($playerid == $voteid) { 289 isvalidid = 1 290 } 291 } 292 if (0$isvalidid != 1) { 293 return 294 } 295 296 lastvoteid = ${uservote.${voteid}.cheater} 297 298 // Cant vote for same ID twice in a row 299 if $(equal $lastvoteid $voteid) { 300 return 301 } 302 303 // Decrease the count for the last person they cheatered 304 if (0${lastvoteid} > 0) { 305 uservote.${lastvoteid}.cheated = (${uservote.${lastvoteid}.cheated} - 1) 306 } 307 308 uservote.${id}.cheater = $voteid 309 uservote.${voteid}.cheated = (0${uservote.${voteid}.cheated} + 1) 310 311 if (0${uservote.${voteid}.cheated} >= ($(qfadmin::getClientNum) / 2)) { 312 say $(client::getInfo $voteid "name"), " has been kicked for cheating" 313 qfadmin::clearVars 314 315 if $(equal ${config.cheater.action} "ban") { 316 ban $voteid ${config.cheater.bantime} 317 } else { 318 kick $voteid 319 } 320 321 return 322 } 323 324 say $name, " voted to ", ${config.cheater.action}, " ", $(client::getInfo $voteid "name"), " - with ", ${uservote.${voteid}.cheated}, " votes" 325} 326 327// Vote to change maps 328function qfadmin::doMap { 329 local map lastmap tmp isvalidmap 330 local name id 331 332 id = $args[1] 333 name = $args[2] 334 map = $args[3] 335 336 // Opps, no map 337 ifnot $(length $map) { 338 return 339 } 340 341 // Check the map exists 342 for tmp in @config.maps { 343 if $(equal ${tmp} ${map}) { 344 isvalidmap = 1 345 } 346 } 347 348 if (0${isvalidmap} != 1) { 349 return 350 } 351 352 lastmap = ${uservote.${id}.map} 353 354 // They cant vote for the same map twice in a row! 355 if $(equal $lastmap $map) { 356 return 357 } 358 359 // Decrease the vote count for the last map they voted for 360 if $(length $lastmap) { 361 mapvote.$lastmap = (${mapvote.$lastmap} - 1) 362 } 363 364 uservote.${id}.map = $map 365 mapvote.$map = (0${mapvote.$map} + 1) 366 367 // Have the majority of the users voted for this map? if so change it 368 if ( 0${mapvote.${map}} >= ( $(qfadmin::getClientNum) / 2 ) ) { 369 say "Switching to ", $map, " - with ", ${mapvote.$map}, " votes" 370 qfadmin::clearVars 371 map $map 372 return 373 } 374 375 say $name, " voted for ", $map, " - with ", ${mapvote.$map} , " votes" 376} 377 378function qfadmin::doMaps { 379 local name id tmp count 380 381 id = $args[1] 382 name = $args[2] 383 384 if (0$(count @config.maps) < 1) { 385 client::print $id "There are no maps available for voting\n" 386 return 387 } 388 389 client::print $id "There are ", $(count @config.maps), " maps available for voting\n" 390 for tmp in @config.maps { 391 client::print $id $tmp, " " 392 393 count = (0${count} + 1) 394 if ($count == 5) { 395 client::print $id "\n" 396 count = 0 397 } 398 } 399 400 client::print $id "\n" 401} 402 403// Perform whatever needs to be done when the client connects 404function qfadmin::connectEvent { 405 local name id 406 407 id = $args[1] 408 name = $args[2] 409 410 // Send them the MOTD 411 if $(equal ${config.motd} "yes") { 412 client::print $id "This server is using ", $(qfadmin::getVersion), "\n" 413 414 if $(length ${config.motdfile}) { 415 if $(count $(file::find ${config.motdfile})) { 416 local motdline 417 418 for motdline in $(split $(file::read ${config.motdfile}) "\n") { 419 motdline = $(regex::replace $motdline "#players#" -- $(qfadmin::getClientNum)) 420 motdline = $(regex::replace $motdline "#deathmatch#" -- $deathmatch) 421 client::print $id $motdline, "\n" 422 } 423 } 424 } 425 } 426} 427 428// Clean up when a person disconnects 429function qfadmin::disconnectEvent { 430 local lastmap lastvoteid 431 local id name 432 433 id = $args[1] 434 name = $args[2] 435 436 lastmap = ${uservote.${id}.map} 437 lastvoteid = ${uservote.${voteid}.cheater} 438 439 if $(length $lastmap) { 440 mapvote.$lastmap = (${mapvote.$lastmap} - 1) 441 } 442 443 if (0${lastvoteid} > 0) { 444 uservote.${lastvoteid}.cheated = (${uservote.${lastvoteid}.cheated} - 1) 445 } 446 447 delete uservote.$id 448} 449 450// Add a user triggerable command 451function qfadmin::addCmd { 452 cmds.$args[1] = $args[2] 453} 454 455// Called whenever somebody talks 456function qfadmin::chatEvent { 457 local cmd cmdarg prefix from 458 459 // Ignore spectator/team messages 460 if $args[3] { 461 return 462 } 463 464 // Check the command starts with a ! 465 prefix = $(slice $args[2] 0 1) 466 ifnot $(equal $prefix "!") { 467 return 468 } 469 470 // Process the command 471 from = $(client::getInfo $args[1] "name") 472 cmd = $(split $(slice $args[2] 1)) 473 474 // Check if the command has been disabled 475 if $(equal ${config.disable.${cmd}} "yes") { 476 return 477 } 478 479 if #{cmds.$cmd} { 480 ${cmds.$cmd} $args[1] $from @cmd[1:]; 481 } 482} 483 484qfadmin::init 485 486event::register chat qfadmin::chatEvent 487event::register client.connect qfadmin::connectEvent 488 489// QFAdmin Commands 490qfadmin::addCmd "version" qfadmin::doVersion 491qfadmin::addCmd "cheater" qfadmin::doCheater 492qfadmin::addCmd "map" qfadmin::doMap 493qfadmin::addCmd "maps" qfadmin::doMaps 494