Scripts:BF2Admin
From BF2 Technical Information Wiki
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)
Contents |
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 (webmaster@animelab.com)
# 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 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):
return config.get(var, False)
def out(level, string):
global log
LOGLEVEL = ('[NONE]', '[INFO]', '[WARN]', '[ERROR]', '[DEBUG]')
if 'logging' not in config:
config['logging'] = 2
if 'loglevel' not in config:
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 = ' '.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 (webmaster@animelab.com)
# 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 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 = ' '.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 = ' '.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 = ' '.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 = ' '.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 (webmaster@animelab.com)
# 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 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