Scripts:BF2Admin
This script so far, should read a file for a list of administrators listed by their profileID. This administrator can then use chat commands to kick and ban players.
Last Update: 16:01, 10 Jul 2005 (CST)
Documentation
Can be found in the BF2Admin Docs Page
Changes
- Added sa_add_admin <player> <permissions> which will write new admins to the users.cfg,
- Added pub_id <player> which print the profileID of a player to the requesters console,
- Corrected the playername matching function to ignore case, e.g. "sa_kick dan bad guy" will kick a player with the name like FSR|Danni
- Added sa_rcon <rconcmd> <args> to allow rcon commands to be executed, the results are not reported back.
- Made the permissions work
- Added configuration system
- Added squad/ping kicker
- Added immunity perm
To Do
- Reserved Slot for administrators,
- Rewrite the autobalancer to prioritze team switches,
- Administrator immunity from TKPunish
- Documentation (yeah right =P)
Requests?
- Using key hash instead of player name as auth method. --Wizzler 19:50, 7 Jul 2005 (MDT)
Actually, this method is nicer, as it ties the user back to their GameSpy ID and not to a certain install of BF2.
Bugs?
- ...
- ...
- ...
Files
File: bf2admin.py
# Ingame Administration System (BF2Admin) # # Author: Danni ([email protected]) # Clan: Fallen Soldiers Reborn # # http://www.fsrgaming.com # http://www.animelab.com # # # 100% Copyleft. Use at will but... # If you reuse or modify this code you must credit me and # the clan FSR. OR ELSE! >:D # # WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! # # THIS MODULE IS NOT YET APPROVED FOR USE ON RANKED SERVERS! # WE ARE NOT RESPONSIBLE FOR YOUR SERVER BEING DELISTED! # PLEASE CHECK WITH EA FIRST BEFORE USING THIS MODULE ON A RANKED SERVER! # # WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! # # # Special thanks why? # _________________________________________________________________ # # Greeze Inspiration from SayKick.py # DICE tk_punish.py and other BF2 python sources # (unknown) gui_log.pyw a VERY helpfull tool! # Everyone at BF2TIW http://bf2.fun-o-matic.org/index.php/Main_Page # import string import re import bf2 import bf2.PlayerManager import bf2.Timer import host from bf2 import g_debug import bf2admincmd import bf2adminkickers # Dictionaries. Duh! pdict = { } rcmd = { } pcmd = { } pinfo = { } rinfo = { } config = { } log = None # Logging Levels L_NONE = 0 L_INFO = 1 L_WARNING = 2 L_ERROR = 3 L_DEBUG = 4 class AdminData: def __init__(self): self.admin = 0 self.perms = "" class PlayerData: def __init__(self): self.lastupdate = 0 self.lastupdate = 0 ### PlayerObject Extensions. def getPlayerPerms(self): return self.adminData.perms def isAdmin(self): return self.adminData.admin def sendMessage(self, message): host.sgl_sendTextMessage(self.index, 12, 1, message, 0) bf2.PlayerManager.Player.isAdmin = isAdmin bf2.PlayerManager.Player.getPerms = getPlayerPerms bf2.PlayerManager.Player.sendMessage = sendMessage def addChatCommand(command, function, perm, usage): rcmd[command] = function rinfo[command] = (perm, usage) def addPublicChatCommand(command, function, usage): pcmd[command] = function pinfo[command] = usage def setConfig(var, val): config[var] = val def getConfig(var): if config.has_key(var): return config[var] else: return False def out(level, string): global log LOGLEVEL = ('[NONE]', '[INFO]', '[WARN]', '[ERROR]', '[DEBUG]') if not config.has_key('logging'): config['logging'] = 2 if not config.has_key('loglevel'): config['loglevel'] = 3 string = LOGLEVEL[level] + ' ' + string if level <= config['loglevel']: if config['logging'] >= 1: print string if config['logging'] >= 2: sendAdminMessage(string) if config['logging'] >= 3: log.write(string + "\n") def loadConfig(): fn = 'admin/bf2admin.cfg' try: cfg = open(fn, 'r') lineNo = 0 p = re.compile('(.*?):\s(.*?)', re.IGNORECASE) for line in cfg: lineNo += 1 if line.strip() != '' and line.strip() != '\n': m = p.match(line) if m: config[m.group(1)] = m.group(2) except IOError, detail: out (L_WARNING, 'couldn\'t read "%s": %s' % (fn, detail)) def saveConfig(): fn = 'admin/bf2admin.cfg' try: cfg = open(fn, 'w') lineNo = 0 keys = config.keys() keys.sort() for key in keys: cfg.write(str(key) + ': ' + str(config[key]) + '\n') except IOError, detail: out(L_WARNING, 'couldn\'t write "%s": %s' % (fn, detail)) def sendAdminMessage(message): for tp in bf2.playerManager.getPlayers(): if tp.adminData.admin: host.sgl_sendTextMessage(playerId, 12, 1, message, 0) def findPlayerFromString(playpart): for tp in bf2.playerManager.getPlayers(): name = tp.getName() playpart = playpart.lower() name = name.lower() if name.find(playpart) != -1: return tp return def findPlayerNameFromString(playpart): for tp in bf2.playerManager.getPlayers(): name = tp.getName() playpart = playpart.lower() name = name.lower() if name.find(playpart) != -1: return tp.getName() return def init(): global log out(L_INFO, 'initializing BF2Admin script') loadConfig() parseUsers() host.registerHandler('PlayerConnect', onPlayerConnect, 1) host.registerHandler('PlayerDisconnect', onPlayerDisconnect, 1) host.registerHandler('ChatMessage', onChatMessage, 1) fn = 'admin/logs/bf2admin.log' try: log = open(fn, 'a') except IOError, detail: out(L_WARNING, 'couldn\'t open "%s": %s' % (fn, detail)) bf2admincmd.init() bf2adminkickers.init() def stripmessage(text): text = text.replace("HUD_TEXT_CHAT_TEAM", "") text = text.replace("HUD_TEXT_CHAT_SQUAD", "") text = text.replace("HUD_CHAT_DEADPREFIX", "") return text def onChatMessage(playerid, text, channel, flags): player = bf2.playerManager.getPlayerByIndex(playerid) text = stripmessage(text) cmdList = text.split(' ') if len(cmdList) > 1 and playerid != -1: cmd = cmdList[0] cmdList[0:1] = [] args = string.join(cmdList,' ') try: if player.adminData.admin and rinfo[cmd]: if player.adminData.perms.find(rinfo[cmd][0]) == -1: player.sendMessage(player.index, 'BF2Admin: You have no access to that command') else: rcmd[cmd](player, args) except Exception, detail: out(L_DEBUG, 'Run-time error:' + detail) try: if pcmd[cmd] and pinfo[cmd]: pcmd[cmd](player, args) except Exception, detail: out(L_DEBUG, 'Run-time error:' + detail) def onPlayerConnect(player): player.adminData = AdminData() if pdict[str(player.getProfileId())]: player.adminData.admin = 1 player.adminData.perms = str(pdict[str(player.getProfileId())]) # This is just in case a playerslot is reused and not initalized correctly. # and yes I have seen it happen in other games =P def onPlayerDisconnect(player): player.adminData = AdminData() # Parses the config file, if it's there def parseUsers(): def boolFromString (str): if str in ['True', 'true', '1']: return True elif value in ['False', 'false', '0']: return False else: raise ValueError fn = 'admin/users.cfg' try: # users.cfg format # Note: playername is purly so the maintainer can tell who a line is for # # # profileID "playername" "permissions" "reserved" "reserved" // Comment # cfg = open(fn, 'r') lineNo = 0 # and now for some of that RegEx magic. ^_^ # profileid name perms resv resv p = re.compile('\s*?([0-9]*?)\s\"(.*?)\"\s"(.*?)\"\s"(.*?)\"\s"(.*?)\"', re.IGNORECASE) for line in cfg: lineNo += 1 if line.strip() != '' and line.strip() != '\n': m = p.match(line) if m: pdict[m.group(1)] = m.group(3) except IOError, detail: out(L_WARNING, 'couldn\'t read "%s": %s' % (fn, detail))
File: bf2admincmd.py
# Ingame Administration System (BF2Admin) # # Author: Danni ([email protected]) # Clan: Fallen Soldiers Reborn # # http://www.fsrgaming.com # http://www.animelab.com # # # 100% Copyleft. Use at will but... # If you reuse or modify this code you must credit me and # the clan FSR. OR ELSE! >:D # # WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! # # THIS MODULE IS NOT YET APPROVED FOR USE ON RANKED SERVERS! # WE ARE NOT RESPONSIBLE FOR YOUR SERVER BEING DELISTED! # PLEASE CHECK WITH EA FIRST BEFORE USING THIS MODULE ON A RANKED SERVER! # # WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! # # # Special thanks why? # _________________________________________________________________ # # Greeze Inspiration from SayKick.py # DICE tk_punish.py and other BF2 python sources # (unknown) gui_log.pyw a VERY helpfull tool! # Everyone at BF2TIW http://bf2.fun-o-matic.org/index.php/Main_Page # import string import re import bf2 import host import bf2.PlayerManager import bf2admin from bf2 import g_debug # Logging Levels L_NONE = 0 L_INFO = 1 L_WARNING = 2 L_ERROR = 3 L_DEBUG = 4 def init(): bf2admin.out(L_INFO, 'initializing BF2AdminCmd script') bf2admin.addChatCommand('sa_kick', sa_kick, 'k', 'sa_kick <player> <reason> - Kick a player') bf2admin.addChatCommand('sa_ban', sa_ban, 'b', 'sa_ban <player> <length> <reason> - Ban a player') bf2admin.addChatCommand('sa_bankey', sa_bankey, 'b', 'sa_bankey <player> <length> <reason> - Ban a player by CD-Key') bf2admin.addChatCommand('sa_rcon', sa_rcon, 'r', 'sa_rcon <command> <args> ... - Send and rcon command') bf2admin.addChatCommand('sa_add_admin', sa_add_admin, 'f', 'sa_add_admin <player> <permissions> ... - Add an administrator') bf2admin.addChatCommand('sa_save', sa_save, 'f', 'sa_save <config> - Save the configuration') bf2admin.addChatCommand('sa_set', sa_set, 'f', 'sa_set <key> <value> - Change a configuration option') bf2admin.addChatCommand('sa_get', sa_get, 'f', 'sa_get <key> - Print a configuration option') bf2admin.addPublicChatCommand('pub_id', pub_id, 'pub_id <player> - Retreave a players ProfileId') def sa_kick(issuer, args): argv = args.split(' ') playername = bf2admin.findPlayerNameFromString(argv[0]) player = bf2admin.findPlayerFromString(argv[0]) argv[0:1] = [] reason = string.join(argv, ' ') if playername: if player.getPerms().find('i') != -1: issuer.sendMessage('BF2Admin: ' + playername + ' is immune from that command') else: host.rcon_invoke('game.sayAll "BF2Admin: ' + playername + ' was kicked: ' + reason + '"') host.rcon_invoke('admin.kickPlayer "' + playername + '"') def sa_ban(issuer, args): argv = args.split(' ') if not argv[2]: issuer.sendMessage("usage: sa_ban <player> <length> <reason>") return playername = bf2admin.findPlayerFromString(argv[0]) player = bf2admin.findPlayerFromString(argv[0]) length = int(argv[1]) argv[0:2] = [] reason = string.join(argv, ' ') if playername: if player.getPerms().find('i') != -1: issuer.sendMessage('BF2Admin: ' + playername + ' is immune from that command') else: host.rcon_invoke('game.sayAll "BF2Admin: ' + playername + ' was banned: ' + reason + '"') host.rcon_invoke('admin.banPlayer ' + player.index + ' ' + length) def sa_bankey(issuer, args): argv = args.split(' ') if not argv[2]: issuer.sendMessage("usage: sa_bankey <player> <length> <reason>") return playername = bf2admin.findPlayerFromString(argv[0]) player = bf2admin.findPlayerFromString(argv[0]) length = int(argv[1]) argv[0:2] = [] reason = string.join(argv, ' ') if playername: if player.getPerms().find('i') != -1: issuer.sendMessage('BF2Admin: ' + playername + ' is immune from that command') else: host.rcon_invoke('game.sayAll "BF2Admin: ' + playername + '\'s CD-KEY was banned: ' + reason + '"') host.rcon_invoke('admin.banPlayerKey ' + player.index + ' ' + length) def sa_save(issuer, args): bf2admin.saveConfig() issuer.sendMessage('BF2Admin: Configuration Saved') def sa_set(issuer, args): argv = args.split(' ') bf2admin.setConfig(argv[0], argv[1]) def sa_get(issuer, args): issuer.sendMessage('BF2Admin: ' + str(args) + ': ' + str(bf2admin.getConfig(args))) def sa_add_admin(issuer, args): # sa_add_admin playerName permissions argv = args.split(' ') playername = bf2admin.findPlayerNameFromString(argv[0]) player = bf2admin.findPlayerFromString(argv[0]) profileId = player.getProfileId() if player.getPerms(): issuer.sendMessage('BF2Admin: ' + playername + ' is already an administrator. Please edit the users.cfg file manualy to change permissions') else: file = open('admin/users.cfg', 'a') file.write(' ' + str(profileId) + ' "' + playername + '" "' + argv[1] +'" "" ""\n') file.close() issuer.sendMessage('BF2Admin: ' + playername + ' added as an administrator.') def sa_rcon(issuer, args): argv = args.split(' ') argv[0:1] = [] reason = string.join(argv, ' ') res = host.rcon_invoke(args) issuer.sendMessage('BF2Admin: rcon command issued') for line in res.split('\n'): issuer.sendMessage(line) def pub_id(issuer, args): argv = args.split(' ') tp = bf2admin.findPlayerFromString(argv[0]) if tp: issuer.sendMessage('BF2Admin: Name: ' + str(tp.getName()) + ' ProfileId: ' + str(tp.getProfileId())) else: issuer.sendMessage('BF2Admin: Error: Could not find a player with that name') def pub_help(issuer, args): argv = args.split(' ') tp = bf2admin.findPlayerFromString(argv[0]) if tp: issuer.sendMessage('BF2Admin: Name: ' + str(tp.getName()) + ' ProfileId: ' + str(tp.getProfileId())) else: issuer.sendMessage('BF2Admin: Error: Could not find a player with that name')
File: bf2adminkickers.py
# Ingame Administration System (BF2Admin) # # Author: Danni ([email protected]) # Clan: Fallen Soldiers Reborn # # http://www.fsrgaming.com # http://www.animelab.com # # # 100% Copyleft. Use at will but... # If you reuse or modify this code you must credit me and # the clan FSR. OR ELSE! >:D # # WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! # # THIS MODULE IS NOT YET APPROVED FOR USE ON RANKED SERVERS! # WE ARE NOT RESPONSIBLE FOR YOUR SERVER BEING DELISTED! # PLEASE CHECK WITH EA FIRST BEFORE USING THIS MODULE ON A RANKED SERVER! # # WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! # # # Special thanks why? # _________________________________________________________________ # # Greeze Inspiration from SayKick.py # DICE tk_punish.py and other BF2 python sources # (unknown) gui_log.pyw a VERY helpfull tool! # Everyone at BF2TIW http://bf2.fun-o-matic.org/index.php/Main_Page # import string import re import bf2 import bf2.PlayerManager import bf2.Timer import host from bf2 import g_debug import bf2admin gamestatus = None ten_secs = None sixty_secs = None bf2.PlayerManager.Player.pingWarnings = 0 bf2.PlayerManager.Player.squadWarnings = 0 bf2.PlayerManager.Player.detectedPing = [] bf2.PlayerManager.Player.pingSamples = 0 bf2.PlayerManager.Player.actuallyPlaying = False try: def resetPlayer(p): p.pingWarnings = 0 p.squadWarnings = 0 p.detectedPing = [] p.pingSamples = 0 p.actuallyPlaying = False def init(): # defaults if not bf2admin.getConfig('pk_enabled'): bf2admin.setConfig('pk_enabled', 1) if not bf2admin.getConfig('sk_enabled'): bf2admin.setConfig('sk_enabled', 1) if not bf2admin.getConfig('pk_samples'): bf2admin.setConfig('pk_samples', 12) # two minuites of samples if not bf2admin.getConfig('pk_warnings'): bf2admin.setConfig('pk_warnings', 3) if not bf2admin.getConfig('pk_maxping'): bf2admin.setConfig('pk_maxping', 1) if not bf2admin.getConfig('sk_warnings'): bf2admin.setConfig('sk_warnings', 3) host.registerHandler('PlayerConnect', onPlayerConnect) host.registerHandler('PlayerDisconnect', onPlayerDisconnect) host.registerHandler('PlayerSpawn', onPlayerSpawn) host.registerHandler('PlayerDeath', onPlayerSpawn) host.registerGameStatusHandler(onGameStatusChanged) enableTimers() def enableTimers(): global ten_secs global sixty_secs if not ten_secs: ten_secs = bf2.Timer(ten_seconds, 10, 1) ten_secs.setRecurring(10) if not sixty_secs: sixty_secs = bf2.Timer(sixty_seconds, 60, 1) sixty_secs.setRecurring(60) def ten_seconds(data): # ping kick enableTimers() def sixty_seconds(data): enableTimers() for tp in bf2.playerManager.getPlayers(): if bf2admin.getConfig('pk_enabled') and tp.actuallyPlaying: if tp.getPing() > bf2admin.getConfig('pk_maxping'): if tp.pingWarnings < bf2admin.getConfig('pk_warnings'): tp.pingWarnings += 1 tp.sendMessage('BF2Admin: WARNING ' + str(tp.pingWarnings) + '/' + str(bf2admin.getConfig('pk_warnings')) +'! YOUR PING IS TOO HIGH! YOU WILL BE REMOVED IF IT DOES NOT FALL BELOW ' + str(bf2admin.getConfig('pk_maxping')) + '!') else: host.rcon_invoke('game.sayAll "BF2Admin: ' + tp.getName() + ' was kicked due to high ping!') host.rcon_invoke('admin.kickPlayer "' + tp.getName() + '"') else: tp.pingWarnings = 0 if bf2admin.getConfig('sk_enabled') and tp.actuallyPlaying: if not tp.isCommander() and tp.getSquadId() == 0: if tp.squadWarnings < bf2admin.getConfig('sk_warnings'): tp.squadWarnings += 1 tp.sendMessage('BF2Admin: WARNING ' + str(tp.squadWarnings) + '/' + str(bf2admin.getConfig('sk_warnings')) +'! JOIN OR CREATE A SQUAD OR YOU WILL BE KICKED!') else: host.rcon_invoke('game.sayAll "BF2Admin: ' + tp.getName() + ' was kicked for not joining a squad!') host.rcon_invoke('admin.kickPlayer "' + tp.getName() + '"') def onPlayerSpawn(p, vehicle): enableTimers() p.actuallyPlaying = 1 def onPlayerDeath(p, vehicle): p.actuallyPlaying = 1 def onPlayerConnect(player): enableTimers() resetPlayer(player) def onPlayerDisconnect(player): enableTimers() resetPlayer(player) def onGameStatusChanged(status): gamestatus = status if gamestatus == bf2.GameStatus.EndGame: for tp in bf2.playerManager.getPlayers(): tp.actuallyPlaying = 0 except Exception, detail: print 'Error! ' + detail
File: users.cfg
This file should be placed in the ./admin/ directory in the main BF2 directory.
# users.cfg # Administrator configuration file # users.cfg format # Note: playername is purly so the maintainer can tell who a line is for # # profileID "playername" "permissions" "reserved" "reserved" // Comment 44773626 "FSR|Danni" "abcdefghijklmnopqrstuvwxyz1234567890" "" "" // Main Admin