BF3 RCON Server Administration

By TheImrac on Jan 08, 2012

Python script I made for our clans Knife and pistol server we ran for BF3.

Since we are no longer running the server right now, I decided I would put it up here.

create an admins.txt file with a single in game admin on each line. They will have ingame admin.

Again, this is a Knife and Pistol rule set, you can modified it to your liking to with other weapons sets.

This is no longer in development, and as such, I probably wont update it for a while.

Also, this is kinda advanced

#!/usr/bin/python

#

### BF3 Admin Rcon script
### version 0.1.6 (BETA)
### Author: Imrac
###
### Heavily Modified EA CommandConsole.py script
###

### Weapon Restriction Kicker
### In Game Admin

from struct import *
import md5
import socket
import sys
import shlex
import string
import threading
import os
import time
import Queue
import re
import random
import ast

###############################################################################

# Packet encoding/decoding helper functions

def EncodeHeader(isFromServer, isResponse, sequence):
        header = sequence & 0x3fffffff
        if isFromServer:
                header += 0x80000000
        if isResponse:
                header += 0x40000000
        return pack('<I', header)

def DecodeHeader(data):
        [header] = unpack('<I', data[0 : 4])
        return [header & 0x80000000, header & 0x40000000, header & 0x3fffffff]

def EncodeInt32(size):
        return pack('<I', size)

def DecodeInt32(data):
        return unpack('<I', data[0 : 4])[0]

def EncodeWords(words):
        size = 0
        encodedWords = ''
        for word in words:
                strWord = str(word)
                encodedWords += EncodeInt32(len(strWord))
                encodedWords += strWord
                encodedWords += '\x00'
                size += len(strWord) + 5

        return size, encodedWords

def DecodeWords(size, data):
        numWords = DecodeInt32(data[0:])
        words = []
        offset = 0
        while offset < size:
                wordLen = DecodeInt32(data[offset : offset + 4])
                word = data[offset + 4 : offset + 4 + wordLen]
                words.append(word)
                offset += wordLen + 5

        return words

def EncodePacket(isFromServer, isResponse, sequence, words):
        encodedHeader = EncodeHeader(isFromServer, isResponse, sequence)
        encodedNumWords = EncodeInt32(len(words))
        [wordsSize, encodedWords] = EncodeWords(words)
        encodedSize = EncodeInt32(wordsSize + 12)
        return encodedHeader + encodedSize + encodedNumWords + encodedWords

# Decode a request or response packet
# Return format is:
# [isFromServer, isResponse, sequence, words]
# where
#       isFromServer = the command in this command/response packet pair originated on the server
#   isResponse = True if this is a response, False otherwise
#   sequence = sequence number
#   words = list of words

def DecodePacket(data):
        [isFromServer, isResponse, sequence] = DecodeHeader(data)
        wordsSize = DecodeInt32(data[4:8]) - 12
        words = DecodeWords(wordsSize, data[12:])
        return [isFromServer, isResponse, sequence, words]

###############################################################################

# Encode a request packet

def EncodeClientRequest(words,clientSequenceNr):
        packet = EncodePacket(False, False, clientSequenceNr, words)
        clientSequenceNr = (clientSequenceNr + 1) & 0x3fffffff
        return [packet, clientSequenceNr]

# Encode a response packet

def EncodeClientResponse(sequence, words):
        return EncodePacket(True, True, sequence, words)

###################################################################################
# Display contents of packet in user-friendly format, useful for debugging purposes

def printPacket(packet):

        if (packet[0]):
                print "IsFromServer, ",
        else:
                print "IsFromClient, ",

        if (packet[1]):
                print "Response, ",
        else:
                print "Request, ",

        print "Sequence: " + str(packet[2]),

        if packet[3]:
                print " Words:",
                for word in packet[3]:
                        print "\"" + word + "\"",
        print ""

def printRawPacket(rawpacket):
        printPacket(DecodePacket(rawpacket))

###################################################################################

def generatePasswordHash(salt, password):
        m = md5.new()
        m.update(salt)
        m.update(password)
        return string.upper(m.hexdigest())

###################################################################################

def containsCompletePacket(data):
        if len(data) < 8:
                return False
        if len(data) < DecodeInt32(data[4:8]):
                return False
        return True

# Wait until the local receive buffer contains a full packet (appending data from the network socket),
# then split receive buffer into first packet and remaining buffer data

def responseOK(response):
        try:
                if response[0] == "OK":
                        return True
                else:
                        return False
        except (IndexError, TypeError):
                return False

###################################################################################

#

class rconError(Exception):
        def __init__(self,args):
                self.args = args
        def __str__(self):
                return repr(self.args)

class rconBF3(object):

        def __init__(self,name,ip,port,password,disconnectEvent):

                import logging

                # setup our logger

                self.logger = logging.getLogger('rconBF3-%s:%d' % (ip, port))
                self.hdlr = logging.FileHandler('%s-%s-%d.log' % (name,ip,port))
                self.formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
                self.hdlr.setFormatter(self.formatter)
                self.logger.addHandler(self.hdlr)
                self.logger.setLevel(logging.INFO)

                self.logger.info('************* Initializing *************')
                # Set Name/ip/portpassword
                self.name = name
                self.ip = ip
                self.port = port
                self.password = password

                # Set our event to wait for a response from our request
                self.responseWait = threading.Event()
                self.disconnectEvent = disconnectEvent
                self.returnedResponse = None

                # Set our Run flag to true
                self.running = True

        """ ------------- MAIN method ----------------"""
        # Clean Up the Object and Connections
        def disconnect(self,exceptions=[]):
                try:
                        self.running = False
                        self.eventHandler.join()
                        self.receiver.join()
                        self.sendHandler.join()
                        self.serverSock.close()
                        '[%s] %s Socket Closed' % (self.name,time.asctime())
                except RuntimeError, detail:
                        if str(detail) == 'cannot join current thread':
                                pass
                        else:
                                raise
                except AttributeError:
                        pass
                if len(exceptions) > 0:
                        raise rconError(exceptions)
                self.logger.info('Disconnected')
                self.logger.removeHandler(self.hdlr)

        def connect(self):

                try:
                        # Connect to
                        print '[%s] %s Connecting to Server. (%s:%d)' % (self.name,time.asctime(),self.ip,self.port)
                        self.logger.info('Connecting to Server %s:%d' % (self.ip,self.port))

                        self.serverSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                        self.serverSock.connect( (self.ip, self.port) )
                        self.serverSock.setblocking(1)

                        #Set Our Sequence Number
                        self.clientSequenceNr = 0

                        #setup request queue
                        print '[%s] %s Loading Queue.' % (self.name,time.asctime())
                        self.inside_queue = Queue.Queue()

                        #start event thread
                        print '[%s] %s Starting Event Handler.' % (self.name,time.asctime())
                        self.eventHandler = eventHandler(self)
                        self.eventHandler.start()

                        #start socket reader
                        print '[%s] %s Starting Socket Reciver' % (self.name,time.asctime())
                        self.receiver = receivePacket(self)
                        self.receiver.start()

                        #start our send handler
                        print '[%s] %s Starting recieve Reciver' % (self.name,time.asctime())
                        self.sendHandler = sendHandler(self)
                        self.sendHandler.start()

                        # Try and Login

                        #send Login Request
                        print '[%s] %s Sending Login Request.' % (self.name,time.asctime())
                        response = self.sendRequest(['login.hashed'])
                        if not responseOK(response):
                                self.logger.error('Server Doesn\'t know login command, aborting.')
                                print '[%s] %s Server Doesn\'t know login command, aborting.' % (self.name,time.asctime())
                                raise rconError(['Connect Failed','Bad Login Response'])

                        # Has our password
                        print '[%s] %s Sending Password' % (self.name,time.asctime())
                        salt = response[1].decode('hex')
                        passwordHash = generatePasswordHash(salt, self.password)

                        #send login request
                        checkpassword = self.sendRequest(['login.hashed',passwordHash])
                        if not responseOK(checkpassword):
                                self.logger.error('Bad Password, aborting connect')
                                print '[%s] %s Bad Password Returning!' % (self.name,time.asctime())
                                raise rconError(['Connect Failed','Bad Password'])

                        eventsEnabled = self.sendRequest(['admin.eventsEnabled','true'])
                        if not responseOK(eventsEnabled):
                                self.logger.error('Couldn\'t start events, aborting connect')
                                print '[%s] %s Coulnd\'t Start Events!' % (self.name,time.asctime())
                                raise rconError(['Connect Failed','Events Failed'])

                        print '[%s] %s Events Sucessfully Enabled' % (self.name,time.asctime())

                # Throw Exceptions
                except socket.error:
                        self.logger.error('sock.error when connecting')
                        raise rconError(['sock.error','When Connecting'])
                else:
                        return True

        def sendRequest(self,words):
                waiting = threading.Event()
                self.sendHandler.sendQueue.put([waiting,words])

                while self.running:
                        didWait = waiting.wait(.5)
                        if (didWait):
                                response = self.returnedResponse[1]
                                waiting.clear()
                                self.responseWait.set()
                                return response
                        else:
                                continue

        def sendCommand(self,command,*args):
                response = self.sendRequest([command] + args)
                return responseOK(response), response

        def sendResponse(self,sequence,words):
                # Send our reponse to server after getting request
                # usually used to send 'OK'
                try:
                        packet = EncodeClientResponse(sequence,words)
                        self.serverSock.send(packet)
                except (socket.error):
                        raise rconError(['sock.error','sendRepsonse'])

        def registerEvent(self,event,callBack):
                # set event name and function and give it too the reciver block
                print '[%s] %s Regsitering Event %s' % (self.name,time.asctime(),event)
                self.logger.info('Registering Event %s to call %s' % (event,str(callBack)) )
                self.receiver.registeredEvent[event] = callBack

        """ ------------- END MAIN Methods ----------------"""

        """ ------------- Admin Methods --------------------"""
        def getPlayerList(self,subplayers):
                response = self.sendRequest(['admin.listPlayers'] + subplayers.split())
                if responseOK(response):
                        n = int(response[1])
                        attributes = response[2: 2 + n]
                        unSplitPlayer = response[3 + n:]
                        players = [ ]
                        offset = 0
                        for i in range(0,len(unSplitPlayer),n):
                                player = unSplitPlayer[i:i+n]
                                playerAtr = {}
                                for x in range(len(attributes)):
                                        playerAtr[attributes[x]] = player[x]
                                players += [playerAtr]
                        return True, players
                else:
                        return False, response

        def getBanList(self):
                response = self.sendRequest(['banList.list'])
                banList = []
                if responseOK(response):
                        numOfBans = len(response)
                        if numOfBans == '0':
                                pass
                        else:
                                for i in range(1,numOfBans,6):
                                        banList += [response[i:i+6]]
                        return True, banList
                else:
                        return False, response

        def adminMove(self,offender,teamId,squadId='0',forcekill='false'):
                self.logger.info('adminMove: %s' % (offender))
                response = self.sendRequest(['admin.movePlayer',offender,teamId,squadId,forcekill])
                return responseOK(response), response
        # kick a player
        def adminKick(self,offender,reason=''):
                self.logger.info('adminKick: %s - %s' % (offender,reason))
                response = self.sendRequest(['admin.kickPlayer',offender,reason])
                return responseOK(response), response

        #kill player
        def adminKill(self,offender):
                self.logger.info('adminKill: %s' % (offender))
                response = self.sendRequest(['admin.killPlayer',offender])
                return responseOK(response), response

        # temp ban a player by seconds
        def adminTBan(self,offender,banTime,reason=''):
                self.logger.info('adminTban: %s Until: %s GMT - %s' % (offender,time.asctime(time.gmtime(time.time() + banTime)),reason))
                response = self.sendRequest(['banList.add','name',offender,'seconds', banTime,reason])
                if responseOK(response):
                        response = self.sendRequest(['banList.save'])
                        return responseOK(response), response
                else:
                        return False, response
        # perm ban a player
        def adminBan(self,offender,reason=''):
                self.logger.info('adminBan: %s Perm - %s' % (offender,reason))
                response = self.sendRequest(['banList.add','name',offender,'perm',reason])
                if responseOK(response):
                        response = self.sendRequest(['banList.save'])
                        return responseOK(response), response
                else:
                        return False, response

        # chat to the server
        def adminSay(self,target,string):
                response = self.sendRequest(['admin.Say',string,target])
                return responseOK(response), response

class receivePacket(threading.Thread):
        def __init__(self,mainClass):
                threading.Thread.__init__(self)
                # Set our Variables
                self.mainClass = mainClass
                self.serverSock = mainClass.serverSock
                # queue
                self.outside_queue = mainClass.inside_queue
                # event
                self.responseWait = mainClass.responseWait
                # Change our timeout
                self.serverSock.settimeout(0.5)
                # sync running
                # setup our dict for events
                self.registeredEvent = {}

        def run(self):
                receiveBuffer = ''
                # Make sure we are still allowed to run
                while self.mainClass.running:
                                # make sure we have total packet
                        while not containsCompletePacket(receiveBuffer) and self.mainClass.running:
                                try:
                                        receiveBuffer += self.serverSock.recv(4096)
                                except socket.timeout:
                                        continue
                                except IOError:
                                        self.mainClass.disconnect()
                                except:
                                        raise

                        if self.mainClass.running is False:
                                break
                        packetSize = DecodeInt32(receiveBuffer[4:8])
                        packet = receiveBuffer[0:packetSize]
                        receiveBuffer = receiveBuffer[packetSize:len(receiveBuffer)]
                        #printRawPacket(packet)

                        # decode the packet
                        [isFromServer, isResponse, sequence, words] = DecodePacket(packet)
                        # now we have total packet and decoded it reset the receiveBuffer

                        if isFromServer:
                                if (isResponse):
                                        #unexpected response from server... Ignoring
                                        pass

                                else:
                                        self.mainClass.sendResponse(sequence,['OK'])
                                        #fire events
                                        if words[0] == 'player.onChat':
                                                if words[1] != 'Server':
                                                        self.logger.info('Chat: %s Said - %s' % (words[1],words[2]))
                                        if words[0] in self.registeredEvent:
                                                self.outside_queue.put([ self.registeredEvent[words[0]], words[1:]])

                        else:
                                if (isResponse):
                                        #pass response to our request thread
                                        self.mainClass.returnedResponse = [sequence, words]
                                        self.responseWait.set()

                                else:
                                        # unexpected request from client??... Ignoring
                                        pass
                print '[%s] %s recivePacket Thread Stopped' % (self.mainClass.name,time.asctime())
                return

        # Stop ourselfs from going out of control!
        def stop(self):
                self.mainClass.running = False
                self.join()

class eventHandler(threading.Thread):
        def __init__(self,mainClass):
                threading.Thread.__init__(self)
                self.mainClass = mainClass
                self.out_queue = mainClass.inside_queue

        def run(self):
                # Make sure we can still run!
                while self.mainClass.running:
                        # Try to get stuff from queue
                        try:
                                q = self.out_queue.get(True,0.5)

                        # Queue timed out, continue gracefully
                        except Queue.Empty:
                                continue
                        try:
                                # run the function in queue
                                func = q[0]
                                args = q[1]
                                func(*args)

                                # Take task out of queue
                                self.out_queue.task_done()
                        except rconError, details:
                                self.mainClass.disconnect()
                        #except:
                               #self.mainClass.disconnect()

                print '[%s] %s eventHandler Thread Stopped' % (self.mainClass.name,time.asctime())
                return

        def stop(self):
                self.mainClass.running = False
                self.join()

class sendHandler(threading.Thread):
        def __init__(self,mainClass):
                threading.Thread.__init__(self)
                self.mainClass = mainClass
                self.sendQueue = Queue.Queue()
                self.clientSequenceNr = 0
        def run(self):

                # While our main thread is running
                while self.mainClass.running:
                        #Try to get queue, time out after .5 seconds to fail gracefully
                        try:
                                q = self.sendQueue.get(True,0.5)
                        except Queue.Empty:
                                continue

                        # Set our respondBack event and words
                        respondBack = q[0]
                        words = q[1]                        

                        try:
                                #Encode and send our packet!
                                packet, self.clientSequenceNr = EncodeClientRequest(words,self.clientSequenceNr)
                                self.mainClass.returnedResponse = None
                                #printRawPacket(packet)
                                sent = self.mainClass.serverSock.send(packet)

                                # Loop while we haven't received the packet and that we are still running
                                while self.mainClass.running and self.mainClass.returnedResponse is None:

                                        # Set Timeout period on wait to gracefully stop
                                        eventFired = self.mainClass.responseWait.wait(0.5)

                                        if (eventFired):
                                                # We got our repsonse, lets do something about it
                                                self.mainClass.responseWait.clear()
                                                responseNum = self.mainClass.returnedResponse[0] + 1
                                                # Make sure the sequence number is the same as what we sent
                                                if  responseNum == self.clientSequenceNr:
                                                        respondBack.set()
                                                        while not self.mainClass.responseWait.wait(0.5) and self.mainClass.running:
                                                                pass
                                                        self.mainClass.responseWait.clear()
                                                        break
                                                # if its less, our squence is out of wack.. but continue to wait for next response
                                                elif responseNum < self.clientSequenceNr:
                                                        continue
                                                else:
                                                        # We received a response larger then our current client sequence number
                                                        self.mainClass.logger.error('sock.error Sequence Recoved > Sequence Sent')
                                                        raise rconError(['socket.error','Sequence recived > sequence sent'])
                                                self.sendQueue.task_done()
                                        else:
                                                continue

                        # Throw Exceptions
                        except socket.error:
                                raise rconError(['sock.error','sendRequest'])
                print '[%s] %s sendHandler Thread Stopped' % (self.mainClass.name,time.asctime())
                return

        def stop(self):
                self.mainClass.running = False
                self.join()

""" --------------------------------------------------------------------------------------------------------- """
""" Example Program """

class knifeAndPistol(object):
        def __init__(self,name,ip,port,password):

                self.name = name
                self.ip = ip
                self.port = port
                self.password = password

                self.adminList = { }
                self.weaponTypes = { }
                self.tBanTime = 604800

                try:
                        self.adminFile = open('admins.txt', 'r')
                        for admin in self.adminFile:
                                self.adminList[admin.rstrip()] = { }
                except IOError:
                        print '[MainThread] %s Unabled To Load admin.txt File!' % time.asctime()
                        pass

                #setup our Main Running Thread
                self.running = True

                self.offenderList = { }
                self.weaponTypes = {
                        'knife':[ 'Damagearea', 'Suicide', 'Death', 'Melee', 'Weapons/Knife/Knife', 'Repair Tool', 'Medkit', 'RoadKill', 'Defib', 'SoldierCollision' ],
                        'pistol':[ 'Weapons/MP443/MP443', 'M93R', 'Glock18', 'Taurus .44', 'M1911', 'M9','Weapons/MP412Rex/MP412REX' ],
                        'shotgun':[ '870MCS', 'Siaga20k', 'USAS-12', 'DAO-12', 'M1014' ],
                        'sniper':[ 'Mk11', 'SVD', 'M40A5', 'SV98', 'Model98B', 'M39', 'SKS' ],
                        'rocket':[ 'RPG-7', 'SMAW', 'FGM-148', 'FIM92', 'Weapons/Sa18IGLA/Sa18IGLA' ],
                        #explosive':[ 'M67', 'Weapons/Gadgets/C4/C4', 'M320']
                }

                # Main loop
                while self.running:
                        try:
                                self.disconnectEvent = threading.Event()
                                self.myBF3Server = None
                                self.myBF3Server = rconBF3(self.name,self.ip,self.port,self.password,self.disconnectEvent)
                                self.myBF3Server.connect()
                                self.ruleStatus = True
                                self.weaponRestriction = 'knife pistol'
                                self.myBF3Server.registerEvent('player.onKill',self.eventPlayerKill)
                                self.myBF3Server.registerEvent('player.onChat',self.eventPlayerChat)
                                self.myBF3Server.registerEvent('server.onLevelLoaded',self.eventLevelLoaded)
                                self.roundCount = 0
                                self.startTime = time.time()

                                #creat our timers
                                self.timers = [
                                        #[ offset, interval, [function,args], optional:count],
                                        [10,300,[self.updBanList]],
                                        [0,60,[self.spamMessage,'roundtype']],
                                        [5,60,[self.spamMessage,'rule 1']],
                                        [10,60,[self.spamMessage,'rule 2']],
                                        [15,60,[self.spamMessage,'rule 3']],
                                        [20,60,[self.spamMessage,'rule 4']],
                                        [25,60,[self.spamMessage,'recruit']],
                                        ]
                                # set our offsets
                                for i in self.timers:
                                        i[0] = i[0] + self.startTime

                                # Waiting Loop

                                while self.myBF3Server.running:
                                        finished = self.disconnectEvent.wait(1.0)
                                        if (finished):
                                                self.disconnectEvent.clear()
                                                continue
                                        else:
                                                for i in self.timers:
                                                        offset = i[0]
                                                        interval = i[1]
                                                        curtime = time.time()
                                                        if round(curtime - offset,0) % interval == 0:
                                                                func = i[2][0]
                                                                args = i[2][1:]
                                                                func(*args)
                                                                if 4 in i:
                                                                        i[4] -= 1
                                                                        if i[4] < 1:
                                                                                del i

                        # Shut down gracefully on keyboard interupt
                        except KeyboardInterrupt:
                                self.myBF3Server.disconnect()
                                self.running = False
                                break

                        # if we got a rconError that has to do with the socket closing, start new iteration of main loop, else raise
                        except rconError, detail:
                                print '[MainThread] %s Socket Error, attempting to reconnect in 10 seconds.' % time.asctime()
                                self.myBF3Server.disconnect()
                                del self.myBF3Server
                                time.sleep(10)
                                continue
                        except:
                                self.myBF3Server.disconnect()
                                raise
                        print '[MainThread] %s connection closed, attempting to reconnect in 10 seconds.' % time.asctime()
                        time.sleep(10)
        # update our local ban text file
        def updBanList(self):
                [isTrue, banList] = self.myBF3Server.getBanList()
                if isTrue:
                        f = open('banlist_%s-%s.txt' % (self.ip,self.port),'w')
                        f.write('%-20s %-34s %s\n' % ('PlayerName','Banned Until','Reason'))
                        for ban in banList:
                                if ban[2] == 'seconds':
                                        banType = '%s GMT' % time.asctime(time.gmtime(time.time() + int(ban[3])))
                                else:
                                        banType = ban[2]
                                f.write('%-20s %-34s %s\n' % (ban[1],banType,ban[5]))
                        f.close()
                return

        # Our Spam Function that has dynamic changes
        def spamMessage(self,message):
                if message == 'roundtype':
                        if self.ruleStatus:
                                if self.weaponRestriction == 'knife pistol' or self.weaponRestriction == 'pistol knife':
                                        say = '***Current Round Type: %s***' % self.weaponRestriction
                                else:
                                        say = '!!!!!BONUS ROUND: %s!!!!!' % self.weaponRestriction
                        else:
                                say = '***No Weapon Restrictions!***'
                elif message == 'time':
                        say = 'Current Time: %s' % time.asctime()
                elif message == 'rule 1':
                        say = 'Rule 1: No Tactlights OR Lasers (Press T to Turn OFF)'
                elif message == 'rule 2':
                        say = 'Rule 2: RU Gets Flag A, US Gets Flag C, Fight For B'
                elif message == 'rule 3':
                        say = 'Rule 3: US Do NOT Pass the Turnstiles (Gates) at B'
                elif message == 'rule 4':
                        say = 'Rule 4: RU Do NOT Go Down Escaltors OR Second Set of Stairs'
                elif message == 'recruit':
                        say = '***We are Recruiting Mature Players. www.TexasGaming.org***'
                else:
                        return

                self.myBF3Server.adminSay('all',say)

        # weapon list helper function, parses weapon type to concatinate a weapnonlist
        def getWeaponList(self,weaponType):
                x = weaponType.split()
                if 'knife' not in x:
                      x += ['knife']
                result = []
                for i in x:
                        if i in self.weaponTypes:
                                result += self.weaponTypes[i]
                return result

        # Kicking tracker that kicks 3 times and temp bans the fourth
        def myKicker(self,playerSubSet,reason,admin='AutoKicker',tban=False,ban=False):
                # If the offender is not in our list yet, add some default values
                offender = playerSubSet['name']
                if offender not in self.offenderList:
                        self.offenderList[offender] = { 'count':0, 'time':0 }
                # local vars
                count = self.offenderList[offender]['count']
                expiretime = time.time() - 86400

                # reset count after 24 hours of non-abuse
                if self.offenderList[offender]['time'] < expiretime:
                        count = 0
                reason = '%s (count #%d)[%s]' % (reason, count + 1,admin)
                if count < 2 and not tban and not ban:
                        self.myBF3Server.adminSay('all','Kicking %s for %s' % (offender,reason))
                        print '[%s] %s Kicking %s for %s' % (self.myBF3Server.name,time.asctime(),offender,reason)
                        result = self.myBF3Server.adminKick(offender,reason)
                elif not ban:
                        self.myBF3Server.adminSay('all','TBan (1 Week) %s for %s' % (offender,reason))
                        print '[%s] %s TBaning (1 Week) %s for %s' % (self.myBF3Server.name,time.asctime(),offender,reason)
                        result = self.myBF3Server.adminTBan(offender,self.tBanTime,reason)
                else:
                        self.myBF3Server.adminSay('all','Permanently Banning %s for %s' % (offender,reason))
                        print '[%s] %s Permanently Banning %s for %s' % (self.myBF3Server.name,time.asctime(),offender,reason)
                        result = self.myBF3Server.adminBan(offender,reason)

                self.offenderList[offender]['count'] += 1
                self.offenderList[offender]['time'] = time.time()

                #return result

        def verifyPlayer(self,searchStr,who,outCommand):
                isTrue, players = self.playerSearch('all',searchStr)
                if len(players) > 0:
                        replacedOutCommand = [ ]
                        for i in outCommand:
                                if i is None:
                                        i = players[0]
                                replacedOutCommand += [i]
                        name = players[0]['name']

                if len(players) > 1:
                        self.myBF3Server.adminSay('all','Did you mean %s?' % players[0]['name'])
                        self.adminList[who]['yes/no'] = replacedOutCommand
                elif len(players) == 1:
                        percentOfName = len(searchStr) / len(players[0]['name'])
                        if (percentOfName > 0.33) and (len(searchStr) > 3):
                                func = replacedOutCommand[0]
                                args = replacedOutCommand[1:]
                                func(*args)
                                if 'yes/no' in self.adminList[who]:
                                        del self.adminList[who]['yes/no']

                        else:
                                self.myBF3Server.adminSay('all','Did you mean %s?' % players[0]['name'])
                                self.adminList[who]['yes/no'] = replacedOutCommand
                else:
                        self.myBF3Server.adminSay('all','No Matches Found for: %s' % searchStr)

        def playerSearch(self,playerSubSet,searchStr):
                isTrue, players = self.myBF3Server.getPlayerList(playerSubSet)
                if players is False:
                        return False, []
                prog = re.compile(re.escape(searchStr),re.I)
                result = []
                for i in players:
                        if prog.search(i['name']):
                                result += [i]
                return True, result

        def teamSwitch(self,playerSubSet,forcekill='false'):
                player = playerSubSet['name']
                if playerSubSet['teamId'] == '1':
                        newTeam = 2
                else:
                        newTeam = 1
                self.myBF3Server.adminMove(player,newTeam,'0',forcekill)

        def nukePlayers(self,playerSubSet='all'):

                isTrue, players = self.myBF3Server.getPlayerList(playerSubSet)
                if players is False:
                        return False, []
                for i in players:
                        self.myBF3Server.adminKill(i['name'])

        def setBonusRound(self,newRoundType):
                self.weaponRestriction = newRoundType
                self.myBF3Server.adminSay('all','Setting Current Round To: %s' % newRoundType)
                return
        def killPlayer(self,playerFull,reason='[No Reason Given]'):
                self.myBF3Server.adminSay('all','Killing %s for %s' % (playerFull['name'],reason))
                self.myBF3Server.adminKill(playerFull['name'])

# --------------------------------- EVENTS -----------------------------------------------------------------------------------------
        # our Kill Event,
        def eventPlayerKill(self,killingPlayer,kiledPlayer,weapon,headshot):
                        #check to make sure we have a killing player and our weapon restriction is on
                        if killingPlayer != '' and self.ruleStatus:
                                okWeapons = self.getWeaponList(self.weaponRestriction)
                                # check if the weapon they used is not in our Accept list
                                if weapon not in okWeapons:
                                        self.myKicker({'name':killingPlayer},'Using %s During %s Round' % (weapon.split('/')[-1],self.weaponRestriction))
                        return
        def eventLevelLoaded(self, *args):
                self.roundCount += 1

                if self.roundCount % 3 == 0:
                        roundType = random.choice(self.weaponTypes.keys())
                        if roundType == 'knife':
                                roundType = 'knife'
                        else:
                                roundType = 'knife pistol %s' % roundType
                else:
                        roundType = 'knife pistol'

                self.setBonusRound(roundType)
                self.ruleStatus = True

        def eventPlayerChat(self,who,message):
                match = re.match('/?([$])([^ ]+) ?(.*)$',message,re.I)
                if who in self.adminList and match:
                        prefix = match.group(1)
                        inCommand = match.group(2).lower()
                        parameters = match.group(3)

                        if inCommand == 'bounds':
                                if len(parameters) > 0:
                                        outCommand = [self.myKicker, None, 'Being Out of Bounds!',who]
                                        self.verifyPlayer(parameters,who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %sbounds <playername>' % prefix)
                        elif inCommand == 'tact':
                                if len(parameters) > 0:
                                        outCommand = [self.myKicker, None, 'Using a Tact Light!',who]
                                        self.verifyPlayer(parameters,who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %stact <playername>' % prefix)
                        elif inCommand == 'laser':
                                if len(parameters) > 0:
                                        outCommand = [self.myKicker, None, 'Using a Laser!',who]
                                        self.verifyPlayer(parameters,who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %stact <playername>' % prefix)
                        elif inCommand == 'weapon':
                                if len(parameters) > 0:
                                        outCommand = [self.myKicker, None, 'Using an Illegal Weapon!',who]
                                        self.verifyPlayer(parameters,who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %sweapon <playername>' % prefix)
                        elif inCommand == 'disrupt':
                                if len(parameters) > 0:
                                        outCommand = [self.myKicker, None, 'Disruptive GamePlay!',who]
                                        self.verifyPlayer(parameters,who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %sdisrupt <playername>' % prefix) 
                        elif inCommand == 'move':
                                if len(parameters) > 0:
                                        outCommand = [self.teamSwitch,None]
                                        self.verifyPlayer(parameters,who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %smove <playername>' % prefix)
                        elif inCommand == 'fmove':
                                if len(parameters) > 0:
                                        outCommand = [self.teamSwitch,None,'true']
                                        self.verifyPlayer(parameters,who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %sfmove <playername>' % prefix)
                        elif inCommand == 'kick':
                                if len(parameters) > 0:
                                        player = parameters.split()
                                        if len(player) == 1:
                                                reason = '[No Reason Given]'
                                        else:
                                                reason = ' '.join(player[1:])
                                        outCommand = [self.myKicker, None, reason,who]
                                        self.verifyPlayer(player[0],who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %skick <playername> [reason]' % prefix)
                        elif inCommand == 'tban':
                                if len(parameters) > 0:
                                        player = parameters.split()
                                        if len(player) == 1:
                                                reason = '[No Reason Given]'
                                        else:
                                                reason = ' '.join(player[1:])
                                        outCommand = [self.myKicker, None, reason,who,True]
                                        self.verifyPlayer(player[0],who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %stban <playername> [reason]' % prefix)
                        elif inCommand == 'ban':
                                if len(parameters) > 0:
                                        player = parameters.split()
                                        if len(player) == 1:
                                                reason = '[No Reason Given]'
                                        else:
                                                reason = ' '.join(player[1:])
                                        outCommand = [self.myKicker, None, reason,who,False,True]
                                        self.verifyPlayer(player[0],who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %sban <playername> [reason]' % prefix)

                        elif inCommand == 'nuke':
                                if len(parameters) == 0:
                                        self.myBF3Server.adminSay('all','Are you Sure you want to nuke the entire Server?')
                                        self.adminList[who]['yes/no'] = [self.nukePlayers]
                                else:
                                        if parameters.lower() == 'us':
                                                self.myBF3Server.adminSay('all','Are you Sure you want to nuke the US Team?')
                                                self.adminList[who]['yes/no'] = [self.nukePlayers, 'team 1']
                                        elif parameters.lower() == 'ru':
                                                self.myBF3Server.adminSay('all','Are you Sure you want to nuke the RU Team?')
                                                self.adminList[who]['yes/no'] = [self.nukePlayers, 'team 2']
                                        else:
                                                self.myBF3Server.adminSay('all','Invalid Team. Valid Teams: US or RU')
                        elif inCommand == 'kill':
                                if len(parameters) > 0:
                                        player = parameters.split()
                                        if len(player) == 1:
                                                reason = '[No Reason Given]'
                                        else:
                                                reason = ' '.join(player[1:])
                                        outCommand = [self.killPlayer, None,reason]
                                        self.verifyPlayer(player[0],who,outCommand)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %skill <playername> [reason]' % prefix)

                        elif inCommand == 'bonus':
                                        if parameters == '':
                                                self.myBF3Server.adminSay('all','Bonus Types: %s' % ', '.join(self.weaponTypes))
                                        else:
                                                x = parameters.lower()
                                                x = x.split()
                                                if 'knife' not in x:
                                                      x += ['knife']
                                                result = []
                                                for i in x:
                                                        if i in self.weaponTypes:
                                                                result += [i]
                                                result = ' '.join(result)
                                                self.myBF3Server.adminSay('all','Set Bonus Round to %s?' % result)
                                                self.adminList[who]['yes/no'] = [self.setBonusRound,result]

                        elif inCommand == 'restrict':
                                if parameters == 'on':
                                        if self.ruleStatus:
                                                self.myBF3Server.adminSay('all','Weapon Restriction is Already On!')
                                        else:
                                                self.ruleStatus = True
                                                self.myBF3Server.adminSay('all','Turning Weapon Retriction On!')
                                                self.spamMessage('roundtype')
                                else:
                                        if self.ruleStatus:
                                                self.ruleStatus = False
                                                self.myBF3Server.adminSay('all','Turning Weapon Retriction Off!')
                                        else:
                                                self.myBF3Server.adminSay('all','Weapon Restriction is Already Off!')

                        elif inCommand == 'say':
                                if len(parameters) > 0:
                                        self.myBF3Server.adminSay('all',parameters)
                                else:
                                        self.myBF3Server.adminSay('all','Usage %ssay <something>' % prefix)

                        elif inCommand == 'yes':
                                if 'yes/no' in self.adminList[who]:
                                        func = self.adminList[who]['yes/no'][0]
                                        args = self.adminList[who]['yes/no'][1:]
                                        func(*args)
                                        del self.adminList[who]['yes/no']

                        elif inCommand == 'no':
                                if 'yes/no' in self.adminList[who]:
                                        del self.adminList[who]['yes/no']
                        elif inCommand == 'updbanlist':
                                self.updBanList()
                                self.myBF3Server.adminSay('all','BanList Updated!')
                        else:
                                return
                else:
                        return

if __name__ == '__main__':
        knpServer = knifeAndPistol('knp-64','xxxxxxxxx', 25200,'xxxxxxx')

Comments

Sign in to comment.
Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.