class helper(ConsolePlugin): VERSION = "0.0.1" playerlist = [] helperlist = [] PHASE = 0 CONFIG = None def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level' : value}) pass def reload_config(self): self.helperlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level' : value}) def onStartServer(self, *args, **kwargs): self.playerlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'active' : False,\ 'helper' : False,\ 'level' : 0}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) client = self.getPlayerByClientNum(cli) client['sf'] = sf client['level'] = level client['active'] = True client['helper'] = False if client['level'] <= 10: self.helperNotify(client, **kwargs) for each in self.helperlist: if client['name'].lower() == each['name']: client['helper'] = True def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False if (phase == 6): #fetch helper list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/helper.ini') helperlist = response.read() f = open(self.CONFIG, 'w') f.write(helperlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() def helperNotify(self, client, **kwargs): activehelpers = [] for player in self.playerlist: if player['helper'] and player['active']: activehelpers.append(player['name']) activestring = ', '.join(activehelpers) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rATTENTION: ^cAs a new player it so good to get help from more experienced players. The following players on this server have \ indicated their willingness to help newer players: ^y%s. ^cYou can contact them by using chat (^wCTRL+ENTER^c) and whispering them (^y/w playername^c with your message)." % (client['clinum'], activestring)) def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class pug(ConsolePlugin): VERSION = "0.0.1" ms = None PHASE = 0 STARTSTAMP = 0 STARTED = False PICKING = False playerlist = [] startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} TIME = 0 def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) ''' for (name, value) in ini.items('var'): if (name == "clan1"): self.CLAN1 = value if (name == "clan2"): self.CLAN2 = value ''' pass def onStartServer(self, *args, **kwargs): self.PHASE = 0 self.playerlist = [] self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'ip' : ip,\ 'sf' : 0,\ 'name' : 'X',\ 'active' : False,\ 'team' : 0,\ 'ping' : 0,\ 'clan' : 'X'}) kwargs['Broadcast'].broadcast("SendMessage %s ^cTo toggle your PUG availability send the chat message ^rpug noplay" % (id)) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"") if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 1\"") def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername client ['play'] = True def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) exp = int(stats['exp']) time = int(stats['secs']) time = time/60 sf = int(exp/time) clan = stats['clan_tag'] client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['active'] = True client ['clan'] = clan client ['newteam'] = 0 def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team def onGameStart (self, *args, **kwargs): self.STARTSTAMP = args[1] def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if phase == 5: self.STARTSTAMP = args[1] self.STARTED = True if phase == 6: self.PICKING = False self.STARTED = False self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set Pet_Shaman_Prerequisite 1;\ set sv_setupTimeCommander 600000000;\ Set sv_maxteamdifference 30;") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput") if phase == 7: for each in self.playerlist: each['newteam'] = 0 def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) noplay = re.match("pug noplay", message, flags=re.IGNORECASE) if noplay: self.togglePlay(client, **kwargs) def togglePlay(self, client, playing=None, **kwargs): color = '^g' if self.PICKING: kwargs['Broadcast'].broadcast("SendMessage %s ^rYou cannot toggle your status once picking has begun." % (client['clinum'])) return if not playing: if client['play']: client['play'] = False color = '^r' else: client['play'] = True else: client['play'] = playing if not client['play']: color = '^r' kwargs['Broadcast'].broadcast("SendMessage %s ^cYour Playing Status: %s%s" % (client['clinum'], color, client['play'])) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] info = self.startinfo #Captain select if event == 'Captain': if caller == info['b_captain'] or caller == info['h_captain']: return if value == 'beasts': info['b_captain'] = caller kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 0\"; SendMessage -1 ^r%s^w is Captain of the Beasts!" % (client['name'])) if not info['h_captain']: info['h_first'] = True else: self.beginpicking(**kwargs) if value == 'humans': info['h_captain'] = caller kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 0\"; SendMessage -1 ^r%s^w is Captain of the Humans!" % (client['name'])) if not info['b_captain']: info['b_first'] = True else: self.beginpicking(**kwargs) print info #Toggle player availability if event == 'Toggle': playing = False if value == 'true': playing = True self.togglePlay(client, playing, **kwargs) #Player select if event == 'Select': player = self.getPlayerByName(value) if caller == info['h_captain']: if not player['play']: kwargs['Broadcast'].broadcast("SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 1 client['newteam'] = 1 kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Humans!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (player['clinum'])) kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (info['b_captain'], info['b_captain'])) if caller == info['b_captain']: if not player['play']: kwargs['Broadcast'].broadcast("SendMessage %s ^rThat player has requested to not play in this match." % (client['name'])) return player['newteam'] = 2 client['newteam'] = 2 kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Beasts!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (player['clinum'])) kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (info['h_captain'],info['h_captain'] )) #Ready if event == 'Ready': #TODO:only make the button do something if the minimum number of players are reached if self.STARTED: return if caller == info['h_captain']: info['h_ready'] = True kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has indicated that Humans are ready!" % (client['name'])) if caller == info['b_captain']: info['b_ready'] = True kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has indicated that Beasts are ready!" % (client['name'])) #Start the game if both captains say they are ready if info['h_ready'] and info['b_ready']: kwargs['Broadcast'].broadcast("set State_ImpPoisoned_Name \"trigger UpdateSpeed 0\"") self.populate(**kwargs) def beginpicking(self, **kwargs): self.PICKING = True #start by making the teams unjoinable: doesn't seem to work kwargs['Broadcast'].broadcast("set sv_maxteamdifference 1; set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 0\";") #move everyone to spectator, but move captains to the appropriate team for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['clinum'])) if each['clinum'] == self.startinfo['h_captain']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (each['clinum'])) if each['clinum'] == self.startinfo['b_captain']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (each['clinum'])) #Set variables to get the first captain to start picking if self.startinfo['h_first']: kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'], self.startinfo['h_captain'])) else: kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain'])) def populate(self, **kwargs): for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['clinum'], each['newteam'])) #Send to the next phase kwargs['Broadcast'].broadcast("NextPhase; set sv_setupTimeCommander 60000; PrevPhase") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] try: client = self.getPlayerByName(name) except: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class sendstats(ConsolePlugin): base = None sent = None playerlist = [] login = None lpass = None broadcast = 0 serverid = 0 loaded = False sending = False def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('paths'): if (name == "base"): self.base = value if (name == "sent"): self.sent = value def getPlayerByName(self, name): client = None for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) if not self.loaded: kwargs['Broadcast'].broadcast("echo SERVERVAR: svr_login is #svr_login#") kwargs['Broadcast'].broadcast("echo SERVERVAR: svr_pass is #svr_pass#") kwargs['Broadcast'].broadcast("echo SERVERVAR: svr_broadcast is #svr_broadcast#") self.loaded = True #Everytime we start a game, start a new thread to send all the stats to eaxs' script, and replays to stony if (phase == 6): uploadthread = thread.start_new_thread(self.uploadstats, ()) #eventthread = thread.start_new_thread(self.uploadevent, ()) def uploadstats(self): print 'starting uploadstats' self.ss = StatsServers () home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) for infile in glob.glob( os.path.join(home, self.base,'*.stats') ): print "Sending stat file: " + infile statstring_raw = open(infile, 'r') datastat = statstring_raw.readlines() statstring = datastat[1] replayname = os.path.splitext(os.path.basename(infile))[0] try: replaysize = os.path.getsize(os.path.join(home, self.base, replayname+'.s2r')) except: replaysize = 100000 statstring_replay = statstring + ("&file_name=%s.s2r&file_size=%s" % (replayname,replaysize)) try: self.ss.s2gstats(statstring_replay) except Exception as e: print e.message print 'upload failed. no stats sent' continue try: shutil.copy(infile,sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue #if not self.sending: #self.uploadreplay() def uploadevent(self): self.ss = StatsServers () home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) for infile in glob.glob( os.path.join(home, self.base,'*.event') ): match = os.path.splitext(os.path.basename(infile))[0] s2pfile = infile statstring = open(infile, 'r').read() decoded = urllib.quote(statstring) stats = ("event%s=%s" % (match,decoded)) try: self.ss.s2pstats(stats) except: print 'upload failed. no stats sent' return try: shutil.copy(infile,sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue def getServerVar(self, *args, **kwargs): var = args[0] if var == 'svr_login': self.login = args[1] if var == 'svr_pass': self.lpass = args[1] if var == 'svr_broadcast': self.broadcast = int(args[1]) self.ms = MasterServer () if self.broadcast > 0: server = self.ms.getServer(self.login, self.lpass, self.broadcast) self.serverid = server['svr_id'] print self.serverid def uploadreplay(self): print 'starting uploadreplay' self.sending = True self.ss = StatsServers () home = os.environ['HOME'] sentdir = os.path.join(home, self.sent) time.sleep(1) for infile in glob.glob( os.path.join(home, self.base,'*.s2r') ): print "Sending replay file: " + infile with open(infile, 'rb') as f: data = f.read() encoded = base64.b64decode(data) replay = {'id':infile, 'login':self.login, 'pass':self.lpass, 'content':encoded} replayjson = json.dumps(replay) try: self.ss.replays(replayjson) except: print 'upload failed. replay not sent' continue print 'Sent replay' try: shutil.copy(infile,sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue self.sending = False def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] self.playerlist.append ({'clinum' : id, 'acctid' : 0,'name' : 'X', 'ip' : ip}) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def onAccountId(self, *args, **kwargs): self.ss = StatsServers () cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) name = client ['name'] ip = client['ip'] server = self.serverid playerinfo = ("sync_user=1&username=%s&acc=%s&ip=%s&svr=%s" % (name, id, ip, server)) #Send info to PS2 self.ss.salvagestats(playerinfo) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) acct = client['acctid'] name = client['name'] server = self.serverid playerinfo = ("sync_user=2&username=%s&acc=%s&svr=%s" % (name, id, server)) #Send info to PS2 self.ss.salvagestats(playerinfo) def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class admin(ConsolePlugin): VERSION = "1.6.4" playerlist = [] adminlist = [] banlist = [] fullbanlist = [] ipban = [] itemlist = [] PHASE = 0 CONFIG = None UPDATE = True NEEDRELOAD = False LASTMESSAGE = {'client' : None, 'firsttime' : 0, 'lasttime' : 0, 'repeat' : 0} DLL = '2f4827b8' norunes = 0 def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(config) + "/ban.ini" banini.read (banconfig) ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ipban'): self.ipban.append(name) pass def reload_config(self): self.adminlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(self.CONFIG) + "/ban.ini" banini.read (banconfig) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ban'): self.fullbanlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ipban'): self.ipban.append(name) def reload_plugins(self): config = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../s2wrapper.ini") ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'admin': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): kwargs['Broadcast'].broadcast("Set norunes 0") kwargs['Broadcast'].broadcast("exec patch.cfg") self.playerlist = [] self.banlist = [] def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput") #these are for identifying bought and sold items kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem") if self.norunes == 1: kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _buyindex #GetIndexFromClientNum(|#_client|#)#;\ set _none \"\"; set _item #GetScriptParam(itemname)#;\ if #StringEquals(|#_item|#,|#_none|#)# TakeItem #_buyindex# #GetScriptParam(slot)#;\ if #StringEquals(|#_item|#,|#_none|#)# SendMessage #GetScriptParam(clientid)# ^yYou cannot equip persistent items on this server;\ echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") else: kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#;\ echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") kwargs['Broadcast'].broadcast("set con_showerr false; set con_showwarn false;") kwargs['Broadcast'].broadcast("Set Entity_NpcController_Name \"S2WRAPPER\"") #kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set kid #GetScriptParam(clientid)#; set kcheck _karmaflag#kid#; if [kcheck > 0] clientexecscript clientdo #kid# cmd \\\"set voice_disabled true\\\"; echo\" spawn") def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByAcctId(self, acctid): for client in self.playerlist: if (client['acctid'] == acctid): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for each in self.ipban: if each == ip: reason = "You are banned from this server." kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"SetSave host_onload true; SetSave host_created 1; WriteConfigScript ~/startup.cfg\"" % (id)) kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"quit\"" % (id)) kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (id, reason)) return reason = "An administrator has removed you from this server. You may rejoin the server after the current game ends." for each in self.banlist: if each == ip: kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (id, reason)) for client in self.playerlist: if (client['clinum'] == id): client['ip'] = ip return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'ip' : ip,\ 'team' : 0,\ 'sf' : 0,\ 'active' : False,\ 'level' : 0,\ 'admin' : False,\ 'value' : 0,\ 'karma' : 0,\ 'commander' : False,\ 'req' : 0,\ 'flood' : None,\ 'f_req' : 0,\ 'l_req' : 0,\ 'msgsum' : None}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] if playername == "": reason = "You dont seem to have a name, thats odd." kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, reason)) client = self.getPlayerByClientNum(cli) client ['name'] = playername def getAccountInfo(self, *args, **kwargs): client = self.getPlayerByClientNum(args[0]) stats = self.ms.getStatistics (client['acctid']).get ('all_stats').get (client['acctid']) level = int(stats['level']) sf = int(stats['sf']) karma = int(stats['karma']) client['sf'] = sf client['level'] = level client['karma'] = karma client['active'] = True #kwargs['Broadcast'].broadcast(\ #"clientexecscript %s clientdo cmd \"set _vr #StringLength(|#GetCheckSum(cgame.dll)|#)#; if [_vr > 0] \\\"SendScriptInput what DLL value #getchecksum(cgame.dll)#\\\"; Else \\\"SendScriptInput what DLL value NONE\\\"\"" % (client['clinum'])) if karma < 0: kwargs['Broadcast'].broadcast(\ "set _karmaflag%s 1" % (client['clinum'])) #If client has disconnected, give them their gold back self.giveGold(False, client, **kwargs) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) statthread = threading.Thread(target=self.getAccountInfo, args=(cli,None), kwargs=kwargs) statthread.start() if self.isBanned(client, **kwargs): kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"SetSave cl_packetSendFPS 1\"" % (cli)) if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as an administrator. Use ^radmin <command>^c to execute commands through chat.^c You can get help by sending ^radmin help ^cto chat." % (cli)) client['admin'] = True if self.isSuperuser(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as superuser on this server. You can send console commands with chat message: ^rsudo <command>." % (cli)) def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each['name']: admin = True return admin def isSuperuser(self, client, **kwargs): superuser = False for each in self.adminlist: if client['name'].lower() == each['name']: if each['level'] == 'super': superuser = True return superuser def isBanned(self, client, **kwargs): banned = False for each in self.fullbanlist: if client['name'].lower() == each['name']: if each['level'] == 'banned': banned = True return banned def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) clinum = client['clinum'] admin = self.isAdmin(client, **kwargs) superuser = self.isSuperuser(client, **kwargs) # --- # MORE THEN FLOOD REPEATS(3)=4 A SEC(1) = kick FLOOD_REPEATS = 2 FLOOD_A_SEC = 0.5 if not client['flood']: client['flood'] = { 'time' : 0, 'count' : 0 } flood = client['flood'] print "flood: %s - %f - %f = %f" % (flood['count'], time.time (), flood['time'], (time.time ()-flood['time'])) # Sickened2: spam-check based on message length and checksum msglen = len(list(message)) if msglen > 100: # this should be a lookup table for checksums of typical spam messages spam1chksum = "ec10ca635bb6b956959830f4e652369d" m = hashlib.md5() m.update(message[:100]) chksum = m.hexdigest() if chksum == spam1chksum: reason = "Attention! Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) elif not client['msgsum']: client['msgsum'] = chksum #print "Checksum" #print client['msgsum'] elif client['msgsum'] == chksum: reason = "Attention! Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) else: client['msgsum'] = chksum # Sickened2: the following method is not as effective because # 1) for large messages (e.g. > 250 bytes) part of the message is returned. For the same message length the # size could vary. So we can't use the message length reliably # 2) if 2 chat packets are sent to the server and the 1st one arrives with delay but in the correct order, # the difference between the time of arrival between the two packets is shorter than the difference # between the departure time of the two packets ## Sickened2: additional spam check; user is not capable of manually typing more than ## MAX_TYPING_SPEED characters per second (avg) #MAX_TYPING_SPEED = 212; # chars/sec #msglen = len(list(message)) #print "msglen = %d" % msglen #timediff = time.time () - flood['time'] #print "timediff = %f" % timediff ##print("len(list(message)) / timediff ={0}".format(len(list(message)) / timediff)) #if msglen / timediff > MAX_TYPING_SPEED: # reason = "Sigh. Spamming results in automatic kicking." # kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) if (time.time () - flood['time']) < FLOOD_A_SEC: flood['count'] += 1 if flood['count'] > FLOOD_REPEATS: reason = "Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) else: flood['count'] = 0 flood['time'] = time.time () #ignore everything else if it isn't from admin if not admin: return if superuser: self.superCommand(message, **kwargs) #Matches for normal admins restart = re.match("admin restart", message, flags=re.IGNORECASE) shuffle = re.match("admin shuffle", message, flags=re.IGNORECASE) kick = re.match("admin kick (\S+)", message, flags=re.IGNORECASE) ban = re.match("admin ban (\S+)", message, flags=re.IGNORECASE) timeout = re.match("admin timeout (\S+)", message, flags=re.IGNORECASE) slap = re.match("admin slap (\S+)", message, flags=re.IGNORECASE) micoff = re.match("admin micoff (\S+)", message, flags=re.IGNORECASE) micon = re.match("admin micon (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("admin changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("admin help", message, flags=re.IGNORECASE) balance = re.match("admin balance", message, flags=re.IGNORECASE) getbalance = re.match("admin get balance", message, flags=re.IGNORECASE) reportbal = re.match("admin report balance", message, flags=re.IGNORECASE) swap = re.match("admin swap (\S+)", message, flags=re.IGNORECASE) setteam = re.match("admin setteam (\S+) (\S+)", message, flags=re.IGNORECASE) if restart: #restarts server if something catastrophically bad has happened kwargs['Broadcast'].broadcast("restart") if shuffle: #artificial shuffle vote if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot shuffle until the game has started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has shuffled the game." % (name)) self.listClients(**kwargs) shufflethread = threading.Thread(target=self.onShuffle, args=(clinum,None), kwargs=kwargs) shufflethread.start() if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\""\ % (kickclient['clinum'], reason)) if timeout: reason = "An administrator has banned you from the server. You are banned till this game is over." kickclient = self.getPlayerByName(timeout.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) self.banlist.append(kickclient['ip']) if ban: #kicks a player from the server and temporarily bans that player's IP till the game is over reason = "An administrator has banned you from the server." kickclient = self.getPlayerByName(ban.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(self.CONFIG) + "/ban.ini" banini.read (banconfig) banini.set ('ipban', kickclient['ip'], kickclient['name']) banini.write (open(banconfig, 'wb')) self.ipban.append(kickclient['ip']) if slap: #slap will move a player x+100, y+200 to get them off of a structure if self.PHASE != 5: return slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists"\ % (slapclient['clinum'], slapclient['clinum'])) if micoff: #Turns off players mic with clientdo offclient = self.getPlayerByName(micoff.group(1)) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"set voice_disabled true\"" % (offclient['clinum'])) if micon: #Turns on players mic with clientdo onclient = self.getPlayerByName(micon.group(1)) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"set voice_disabled false\"" % (onclient['clinum'])) if changeworld: #change the map kwargs['Broadcast'].broadcast(\ "changeworld %s"\ % (changeworld.group(1))) if balance: if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot balance if the game has not started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has balanced the game." % (name)) self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,True,False), kwargs=kwargs) balancethread.start() if getbalance: self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,False,False), kwargs=kwargs) balancethread.start() if reportbal: self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,False,True), kwargs=kwargs) balancethread.start() if swap: #swap a player to a different team swapplayer = self.getPlayerByName(swap.group(1)) newteam = 0 team = swapplayer['team'] if team == 1: newteam = 2 if team == 2: newteam = 1 if newteam == 0: return kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (swapplayer['clinum'], newteam)) if setteam: #swap a player to x team setplayer = self.getPlayerByName(setteam.group(2)) newteam = setteam.group(1) kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (setplayer['clinum'], newteam)) self.logCommand(client['name'],message) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. All commands are logged to prevent you from abusing them.The following are commands and a short description of what they do."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin restart ^whard reset of the server. ONLY use in weird cases."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin shuffle ^wwill shuffle the game and set to previous phase."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin kick playername ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin timeout playername ^wwill remove a player for one game."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin ban playername ^wwill remove a player from the server and ban that IP address permenantly."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin micoff playername ^wwill turn the players mic off. Use on mic spammers."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin micon playername ^wwill turn the players mic on."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin swap playername ^wwill move a specific player to another team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin balance ^wwill move two players to achieve balance."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin get balance ^wwill report avg. and median SF values for the teams as well as a stack value."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin report balance ^wwill send a message to ALL players that has the avg. and median SF values."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin setteam x playername ^wwill set players team to x."\ % (client['clinum'])) def superCommand(self, message, **kwargs): supercommand = re.match("sudo (.*)", str(message), flags=re.IGNORECASE) if supercommand: kwargs['Broadcast'].broadcast("%s" % (supercommand.group(1))) def doBalance(self, admin, doBalance=False, doReport=False, **kwargs): clinum = admin for each in self.playerlist: each['team'] = 0 time.sleep(1) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) startstack = abs(self.evaluateBalance(teamone, teamtwo)) if doReport: kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s.^y Stack value: ^r%s" \ % (teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'], 1), round(teamtwostats['median'],1), abs(stack))) return kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s. ^yStack value: ^r%s" \ % (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) #Find the players to swap lowest = -1 pick1 = None pick2 = None for player1 in teamone: if player1['commander']: continue for player2 in teamtwo: if player2['commander']: continue #sort of inefficient to send the teamlist each time ltarget = abs(self.evaluateBalance(teamone, teamtwo, player1, player2, True)) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 #If the stack isn't improved, abort it if (lowest >= startstack): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yUnproductive balance. No swapping scenario would improve the balance over its current state." % (admin)) return kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Balance will swap ^r%s ^yand ^r%s" \ % (clinum, pick1['name'], pick2['name'])) if not doBalance: index1 = map(itemgetter('clinum'), teamone).index(pick1['clinum']) index2 = map(itemgetter('clinum'), teamtwo).index(pick2['clinum']) teamone[index1]['team'] = 2 teamtwo[index2]['team'] = 1 teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) #kwargs['Broadcast'].broadcast(\ #"SendMessage %s ^cProposed change: ^y Team One (%s players) Avg. SF: ^r%s^y median SF: ^r%s^y, Team Two (%s players) Avg. SF: ^r%s^y median SF: ^r%s. ^yStack value: ^r%s" \ #% (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) return if doBalance: #Do the switch kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 2;\ set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 1"\ % (pick1['clinum'], pick2['clinum'])) #Give them gold if needed self.giveGold(True, pick1, **kwargs) self.giveGold(True, pick2, **kwargs) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^yAfter balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s"\ % (teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase kwargs['Broadcast'].broadcast("echo SERVERVAR: norunes is #norunes#") if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False each['value'] = 0 if (phase == 6): if self.UPDATE: #fetch admin list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() #check if server is empty after 2 minutes pluginthread = threading.Thread(target=self.pluginreload, args=(), kwargs=kwargs) pluginthread.start() self.RegisterScripts(**kwargs) self.ItemList() if (phase == 4): kwargs['Broadcast'].broadcast("listclients") def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/admin.ini') adminlist = response.read() f = open(self.CONFIG, 'w') f.write(adminlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() if self.NEEDRELOAD: self.pluginreload(**kwargs) return #Update the wrapper try: gitpath = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../.git") command = ["git","--git-dir",gitpath,"pull"] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate() result = output[0].split("\n")[0] print 'result is %s' % result #TODO: make sure these work on all servers? notneeded = re.match("Already up-to-date.", result) needed = re.match("Updating .*", result) except: print 'error getting git update' return if notneeded: print 'update not needed' self.NEEDRELOAD = False return if needed: print 'update needed' self.NEEDRELOAD = True self.pluginreload(**kwargs) return def pluginreload(self, **kwargs): print 'pluginreload called' #Wait a couple minutes to allow clients to connect time.sleep(120) #Figure out how many clients are present kwargs['Broadcast'].broadcast("serverstatus") def onServerStatusResponse(self, *args, **kwargs): if self.NEEDRELOAD: gamemap = args[0] active = int(args[2]) if active == 0: self.reload_plugins() kwargs['Broadcast'].broadcast("NextPhase; PrevPhase") self.NEEDRELOAD = False def logCommand(self, client, message, **kwargs): localtime = time.localtime(time.time()) date = ("%s-%s-%s, %s:%s:%s" % (localtime[1], localtime[2], localtime[0], localtime[3], localtime[4], localtime[5])) f = open('admin.log', 'a') f.write("Timestamp: \"%s\", Admin: %s, Command: %s\n" % (date, client, message)) f.close def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team self.requestTracker(cli, **kwargs) def onShuffle (self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 each['value'] = 0 clinum = args[0] time.sleep(2) shufflelist = [] #Put all the active players in a list for each in self.playerlist: if not each['active']: continue if each['team'] > 0: shufflelist.append(each) #sort shufflelists based on SF shufflelist = sorted(shufflelist, key=itemgetter('sf', 'level', 'clinum'), reverse=True) #randomly choose if we begin with human or beast r = random.randint(1,2) #Assign new teams, just like the K2 way, but Ino won't always be on humans for each in shufflelist: #TODO: is there a cleaner, more pythonic way to do this? each['team'] = r if r == 1: r += 1 elif r == 2: r -=1 #Now actually do the shuffling for each in shufflelist: kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (each['clinum'], each['team'])) #Finish it off by going forward a phase kwargs['Broadcast'].broadcast(\ "nextphase") kwargs['Broadcast'].broadcast(\ "SendMessage %s You have shuffled the game." % (clinum)) #Run balancer to get it nice and even #self.onBalance(clinum, **kwargs) kwargs['Broadcast'].broadcast("Startgame") def getTeamInfo(self, teamlist, **kwargs): teamsf = [] combteamsf = float(0) #figure out current averages and set some commonly used variables: for each in teamlist: combteamsf += each['sf'] teamsf.append(each['sf']) sizeteam = len(teamlist) avgteam = combteamsf/sizeteam med = median(teamsf) teaminfo = {'size' : sizeteam, 'avg' : avgteam, 'total' : combteamsf, 'median' : med} return teaminfo def evaluateBalance(self, team1, team2, pick1=None, pick2=None, swap=False, **kwargs): #This function will swap out the picked players in a temporary list if swap is true and report the stack percent #If swap is false, it will just report the balance #First, make new lists that we can modify: teamone = list(team1) teamtwo = list(team2) if swap: #Remove those players from the lists... for each in teamone: if each['clinum'] == pick1['clinum']: teamone.remove(each) for each in teamtwo: if each['clinum'] == pick2['clinum']: teamtwo.remove(each) #Add to the lists teamone.append(pick2) teamtwo.append(pick1) #Get the new team stats... teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #Evaluate team balance teamoneshare = teamonestats['total']/(teamonestats['total'] + teamtwostats['total']) diffmedone = teamonestats['median']/(teamonestats['median'] + teamtwostats['median']) stack = teamoneshare + diffmedone #positive if team one is stacked, negative if team two is stacked return (stack - 1) * 100 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) client['commander'] = False def onUnitChange(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) self.requestTracker(cli, **kwargs) if args[1] != "Player_Commander": return client['commander'] = True def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = int(args[0]) name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #usually used when reloading plugin during a game acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights' : 700, 'Ammo Pack' : 500, 'Ammo Satchel' : 200, 'Chainmail' : 300, 'Gust of Wind' : 450, 'Magic Amplifier' : 700, 'Brain of Maliken' : 750, 'Heart of Maliken' : 950, 'Lungs of Maliken' : 1000, 'Mana Crystal' : 500, 'Mana Stone' : 200, 'Platemail' : 650, 'Power Absorption' : 350, 'Shield of Wisdom' : 650, 'Stone Hide' : 650, 'Tough Skin' : 300, 'Trinket of Restoration' : 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) self.requestTracker(cli, **kwargs) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def giveGold(self, balance, client, **kwargs): if client['value'] == 0: return gold = round(client['value']/2, 0) if balance: gold = client['value'] kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou have been compensated %s gold for your lost items.; GiveGold %s %s"\ % (client['clinum'], gold, client['clinum'], gold)) client['value'] = 0 def getMatchID(self, *args, **kwargs): matchid = args[0] kwargs['Broadcast'].broadcast("Set Entity_NpcController_Description %s" % (matchid)) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] self.requestTracker(caller, **kwargs) if event == 'DLL': if value == 'NONE': return if value != self.DLL: banthread = threading.Thread(target=self.banclient, args=(caller, None), kwargs=kwargs) banthread.start() def banclient(self, *args, **kwargs): clinum = args[0] kwargs['Broadcast'].broadcast(\ "ClientExecScript %s clientdo cmd \"UICall game_options \\\"HTTPGetFile(\'http://masterserver.savage2.s2games.com/create.php?phrase=1\', \'~/null\');\\\"\"" % (clinum)) time.sleep(1) kwargs['Broadcast'].broadcast(\ "ClientExecScript %s clientdo cmd \"quit\"" % (clinum)) def getServerVar(self, *args, **kwargs): var = args[0] if var == 'norunes': self.norunes = args[1] def requestTracker (self, cli, **kwargs): tm = time.time() client = self.getPlayerByClientNum(cli) #If player requests item purchase, team join, unit select more than 12 times in 1 second, boot them if (tm - client['f_req']) > 1: client['req'] = 0 client['f_req'] = tm return client['req'] += 1 if client['req'] > 10: reason = "Spamming server requests results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (client['clinum'], reason))
class admin(ConsolePlugin): VERSION = "1.3.6" playerlist = [] adminlist = [] banlist = [] ipban = [] itemlist = [] PHASE = 0 CONFIG = None UPDATE = True NEEDRELOAD = False LASTMESSAGE = {'client': None, 'firsttime': 0, 'lasttime': 0, 'repeat': 0} def onPluginLoad(self, config): self.ms = MasterServer() self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level': value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) pass def reload_config(self): self.adminlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level': value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) def reload_plugins(self): config = os.path.realpath( os.path.dirname(os.path.realpath(__file__)) + "/../s2wrapper.ini") print config ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'admin': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): self.playerlist = [] self.banlist = [] def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here #these are for identifying bought and sold items kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem" ) kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem" ) def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for each in self.ipban: if each == ip: reason = "You are banned from this server." kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (id, reason)) return reason = "An administrator has removed you from this server. You may rejoin the server after the current game ends." for each in self.banlist: if each == ip: kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (id, reason)) for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'ip' : ip,\ 'team' : 0,\ 'sf' : 0,\ 'active' : False,\ 'level' : 0,\ 'admin' : False,\ 'value' : 0,\ 'commander' : False}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername def getAccountInfo(self, *args, **kwargs): client = self.getPlayerByClientNum(args[0]) stats = self.ms.getStatistics(client['acctid']).get('all_stats').get( client['acctid']) level = int(stats['level']) sf = int(stats['sf']) client['sf'] = sf client['level'] = level client['active'] = True #If client has disconnected, give them their gold back self.giveGold(False, client, **kwargs) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) statthread = threading.Thread(target=self.getAccountInfo, args=(cli, None), kwargs=kwargs) statthread.start() if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as an administrator. Send the chat message: ^rhelp ^cto see what commands you can perform."\ % (cli)) client['admin'] = True if self.isSuperuser(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as superuser on this server. You can send console commands with chat message: ^rsudo <command>."\ % (cli)) def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each['name']: admin = True return admin def isSuperuser(self, client, **kwargs): superuser = False for each in self.adminlist: if client['name'].lower() == each['name']: if each['level'] == 'super': superuser = True return superuser def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) clinum = client['clinum'] admin = self.isAdmin(client, **kwargs) superuser = self.isSuperuser(client, **kwargs) #ADDED: more than 5 message in 1 second = kick tm = time.time() last = self.LASTMESSAGE['lasttime'] first = self.LASTMESSAGE['firsttime'] if (self.LASTMESSAGE['client'] == name): self.LASTMESSAGE['lasttime'] = tm #commanders are immune if not client['commander']: self.LASTMESSAGE['repeat'] += 1 print 'repeat' else: self.LASTMESSAGE['client'] = name self.LASTMESSAGE['firsttime'] = tm self.LASTMESSAGE['repeat'] = 0 if self.LASTMESSAGE['repeat'] > 4: if ((last - first) < 1): reason = "Spamming chat results in automatic kicking." kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (clinum, reason)) self.LASTMESSAGE['client'] = None self.LASTMESSAGE['repeat'] = 0 self.LASTMESSAGE['firsttime'] = 0 self.LASTMESSAGE['lasttime'] = 0 else: self.LASTMESSAGE['repeat'] = 0 self.LASTMESSAGE['client'] = None self.LASTMESSAGE['firsttime'] = 0 self.LASTMESSAGE['lasttime'] = 0 request = re.match("request admin", message, flags=re.IGNORECASE) if request: for each in self.playerlist: if each['active'] and each['admin']: kwargs['Broadcast'].broadcast( "SendMessage %s Admin present: ^y%s" % (client['clinum'], each['name'])) #ignore everything else if it isn't from admin if not admin: return #Pass to superCommand if the player is a superuser if superuser: self.superCommand(message, **kwargs) #Matches for normal admins restart = re.match("admin restart", message, flags=re.IGNORECASE) shuffle = re.match("admin shuffle", message, flags=re.IGNORECASE) kick = re.match("admin kick (\S+)", message, flags=re.IGNORECASE) ban = re.match("admin ban (\S+)", message, flags=re.IGNORECASE) slap = re.match("admin slap (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("admin changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("help", message, flags=re.IGNORECASE) balance = re.match("admin balance", message, flags=re.IGNORECASE) getbalance = re.match("admin get balance", message, flags=re.IGNORECASE) reportbal = re.match("admin report balance", message, flags=re.IGNORECASE) if restart: #restarts server if something catastrophically bad has happened kwargs['Broadcast'].broadcast("restart") if shuffle: #artificial shuffle vote if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot shuffle until the game has started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast( "SendMessage -1 %s has shuffled the game." % (name)) self.listClients(**kwargs) shufflethread = threading.Thread(target=self.onShuffle, args=(clinum, None), kwargs=kwargs) shufflethread.start() if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\""\ % (kickclient['clinum'], reason)) if ban: #kicks a player from the server and temporarily bans that player's IP till the game is over reason = "An administrator has banned you from the server. You are banned till this game is over." kickclient = self.getPlayerByName(ban.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) self.banlist.append(kickclient['ip']) if slap: #slap will move a player x+100, y+200 to get them off of a structure slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists" \ % (slapclient['clinum'], slapclient['clinum'])) if changeworld: #change the map kwargs['Broadcast'].broadcast(\ "changeworld %s"\ % (changeworld.group(1))) if balance: if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot balance if the game has not started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast( "SendMessage -1 %s has balanced the game." % (name)) self.listClients(**kwargs) balancethread = threading.Thread(target=self.onBalance, args=(clinum, None), kwargs=kwargs) balancethread.start() if getbalance: self.listClients(**kwargs) balancethread = threading.Thread(target=self.getBalance, args=(clinum, None), kwargs=kwargs) balancethread.start() if reportbal: self.listClients(**kwargs) balancethread = threading.Thread(target=self.reportBalance, args=(), kwargs=kwargs) balancethread.start() self.logCommand(client['name'], message) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. All commands are logged to prevent you from abusing them.The following are commands and a short description of what they do."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin restart ^whard reset of the server. ONLY use in weird cases."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin shuffle ^wwill shuffle the game and set to previous phase."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmi kick playername ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin ban playername ^wwill remove a player from the server and ban that IP address till the end of the game."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin slap playername ^wwill move the player. Use to get them off of structures if they are exploiting."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin balance ^wwill move two players to achieve balance."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin get balance ^wwill report avg. and median SF values for the teams as well as a stack value."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin report balance ^wwill send a message to ALL players that has the avg. and median SF values."\ % (client['clinum'])) def getBalance(self, *args, **kwargs): clinum = args[0] for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo), 1) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s. ^yStack value: ^r%s" \ % (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) def reportBalance(self, **kwargs): for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo), 1) kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s.^y Stack value: ^r%s" \ % (teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'], 1), round(teamtwostats['median'],1), abs(stack))) def superCommand(self, message, **kwargs): #This allows superuser to issue any console command supercommand = re.match("sudo (.*)", message, flags=re.IGNORECASE) if supercommand: kwargs['Broadcast'].broadcast("%s" % (supercommand.group(1))) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False each['value'] = 0 if (phase == 6): if self.UPDATE: #fetch admin list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() #check if server is empty after 2 minutes pluginthread = threading.Thread(target=self.pluginreload, args=(), kwargs=kwargs) pluginthread.start() self.RegisterScripts(**kwargs) self.ItemList() if (phase == 4): kwargs['Broadcast'].broadcast("listclients") def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/admin.ini') adminlist = response.read() f = open(self.CONFIG, 'w') f.write(adminlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() if self.NEEDRELOAD: self.pluginreload(**kwargs) return #Update the wrapper try: gitpath = os.path.realpath( os.path.dirname(os.path.realpath(__file__)) + "/../.git") command = ["git", "--git-dir", gitpath, "pull"] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate() result = output[0].split("\n")[0] print 'result is %s' % result #TODO: make sure these work on all servers? notneeded = re.match("Already up-to-date.", result) needed = re.match("Updating .*", result) except: print 'error getting git update' return if notneeded: print 'update not needed' self.NEEDRELOAD = False return if needed: print 'update needed' self.NEEDRELOAD = True self.pluginreload(**kwargs) return def pluginreload(self, **kwargs): print 'pluginreload called' #Wait a couple minutes to allow clients to connect time.sleep(120) #Figure out how many clients are present kwargs['Broadcast'].broadcast("serverstatus") def onServerStatusResponse(self, *args, **kwargs): if self.NEEDRELOAD: gamemap = args[0] active = int(args[2]) if active == 0: self.reload_plugins() kwargs['Broadcast'].broadcast("NextPhase; PrevPhase") self.NEEDRELOAD = False def logCommand(self, client, message, **kwargs): localtime = time.localtime(time.time()) date = ("%s-%s-%s, %s:%s:%s" % (localtime[1], localtime[2], localtime[0], localtime[3], localtime[4], localtime[5])) f = open('admin.log', 'a') f.write("Timestamp: \"%s\", Admin: %s, Command: %s\n" % (date, client, message)) f.close def onTeamChange(self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team def onShuffle(self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 each['value'] = 0 clinum = args[0] time.sleep(2) shufflelist = [] #Put all the active players in a list for each in self.playerlist: if not each['active']: continue if each['team'] > 0: shufflelist.append(each) #sort shufflelists based on SF shufflelist = sorted(shufflelist, key=itemgetter('sf', 'level', 'clinum'), reverse=True) #randomly choose if we begin with human or beast r = random.randint(1, 2) #Assign new teams, just like the K2 way, but Ino won't always be on humans for each in shufflelist: #TODO: is there a cleaner, more pythonic way to do this? each['team'] = r if r == 1: r += 1 elif r == 2: r -= 1 #Now actually do the shuffling for each in shufflelist: kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (each['clinum'], each['team'])) #Finish it off by going forward a phase kwargs['Broadcast'].broadcast(\ "nextphase") kwargs['Broadcast'].broadcast(\ "SendMessage %s You have shuffled the game." % (clinum)) #Run balancer to get it nice and even self.onBalance(clinum, **kwargs) def onBalance(self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) #Get Information about the teams teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) startstack = self.evaluateBalance(teamone, teamtwo) #Send message to admin that called the shuffle/balance kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yPrior to balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s" \ % (args[0], teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) #Find the players to swap lowest = -1 pick1 = None pick2 = None for player1 in teamone: if player1['commander']: continue for player2 in teamtwo: if player2['commander']: continue #sort of inefficient to send the teamlist each time ltarget = self.evaluateBalance(teamone, teamtwo, player1, player2, True) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 #If the stack isn't improved, abort it if (lowest >= startstack): print 'unproductive balance. terminate' kwargs['Broadcast'].broadcast(\ "echo unproductive balance") return #Do the switch kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 2;\ set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 1" \ % (pick1['clinum'], pick2['clinum'])) #Give them gold if needed self.giveGold(True, pick1, **kwargs) self.giveGold(True, pick2, **kwargs) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #kwargs['Broadcast'].broadcast(\ # "SendMessage %s ^yAfter balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s"\ # % (clinum, teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) def getTeamInfo(self, teamlist, **kwargs): teamsf = [] combteamsf = float(0) #figure out current averages and set some commonly used variables: for each in teamlist: combteamsf += each['sf'] teamsf.append(each['sf']) sizeteam = len(teamlist) avgteam = combteamsf / sizeteam med = median(teamsf) teaminfo = { 'size': sizeteam, 'avg': avgteam, 'total': combteamsf, 'median': med } return teaminfo def evaluateBalance(self, team1, team2, pick1=None, pick2=None, swap=False, **kwargs): #This function will swap out the picked players in a temporary list if swap is true and report the stack percent #If swap is false, it will just report the balance #First, make new lists that we can modify: teamone = list(team1) teamtwo = list(team2) if swap: #Remove those players from the lists... for each in teamone: if each['clinum'] == pick1['clinum']: teamone.remove(each) for each in teamtwo: if each['clinum'] == pick2['clinum']: teamtwo.remove(each) #Add to the lists teamone.append(pick2) teamtwo.append(pick1) #Get the new team stats... teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #Evaluate team balance teamoneshare = teamonestats['total'] / (teamonestats['total'] + teamtwostats['total']) diffmedone = teamonestats['median'] / (teamonestats['median'] + teamtwostats['median']) stack = teamoneshare + diffmedone #positive if team one is stacked, negative if team two is stacked return (stack - 1) * 100 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) client['commander'] = False def onUnitChange(self, *args, **kwargs): if args[1] != "Player_Commander": return cli = args[0] client = self.getPlayerByClientNum(cli) client['commander'] = True def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #TODO: listclients clinum is always double diget (00, 01, etc.) so this might be a problem acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights': 700, 'Ammo Pack': 500, 'Ammo Satchel': 200, 'Chainmail': 300, 'Gust of Wind': 450, 'Magic Amplifier': 700, 'Brain of Maliken': 750, 'Heart of Maliken': 950, 'Lungs of Maliken': 800, 'Mana Crystal': 500, 'Mana Stone': 200, 'Platemail': 650, 'Power Absorption': 350, 'Shield of Wisdom': 650, 'Stone Hide': 650, 'Tough Skin': 300, 'Trinket of Restoration': 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def giveGold(self, balance, client, **kwargs): if client['value'] == 0: return gold = round(client['value'] / 2, 0) if balance: gold = client['value'] kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou have been compensated %s gold for your lost items.; GiveGold %s %s"\ % (client['clinum'], gold, client['clinum'], gold)) client['value'] = 0
class sendstats(ConsolePlugin): base = None sent = None playerlist = [] login = None lpass = None broadcast = 0 serverid = 0 loaded = False def onPluginLoad(self, config): ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('paths'): if (name == "base"): self.base = value if (name == "sent"): self.sent = value def getPlayerByName(self, name): client = None for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) #Everytime we start a game, start a new thread to send all the stats to eaxs' script, and replays to stony if (phase == 6): uploadthread = thread.start_new_thread(self.uploadstats, ()) eventthread = thread.start_new_thread(self.uploadevent, ()) replaythread = thread.start_new_thread(self.uploadreplay, ()) if not self.loaded: kwargs['Broadcast'].broadcast( "echo SERVERVAR: svr_login is #svr_login#") kwargs['Broadcast'].broadcast( "echo SERVERVAR: svr_pass is #svr_pass#") kwargs['Broadcast'].broadcast( "echo SERVERVAR: svr_broadcast is #svr_broadcast#") self.loaded = True def uploadstats(self): print 'starting uploadstats' self.ss = StatsServers() home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) for infile in glob.glob(os.path.join(home, self.base, '*.stats')): print "Sending stat file: " + infile s2pfile = infile statstring = open(infile, 'r').read() decoded = urllib.quote(statstring) stats = ("stats=%s" % (decoded)) try: self.ss.s2gstats(statstring) self.ss.salvagestats(stats) self.ss.s2pstats(statstring) except: print 'upload failed. no stats sent' return try: shutil.copy(infile, sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue def uploadevent(self): self.ss = StatsServers() home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) for infile in glob.glob(os.path.join(home, self.base, '*.event')): match = os.path.splitext(os.path.basename(infile))[0] s2pfile = infile statstring = open(infile, 'r').read() decoded = urllib.quote(statstring) stats = ("event%s=%s" % (match, decoded)) try: self.ss.s2pstats(stats) except: print 'upload failed. no stats sent' return try: shutil.copy(infile, sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue def getServerVar(self, *args, **kwargs): var = args[0] if var == 'svr_login': self.login = args[1] if var == 'svr_pass': self.lpass = args[1] if var == 'svr_broadcast': self.broadcast = int(args[1]) self.ms = MasterServer() if self.broadcast > 0: server = self.ms.getServer(self.login, self.lpass, self.broadcast) self.serverid = server['svr_id'] print self.serverid def uploadreplay(self): print 'starting uploadreplay' self.ss = StatsServers() home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) remotehost = '188.40.92.72' remotefile = 'incoming' port = 22522 for infile in glob.glob(os.path.join(home, self.base, '*.s2r')): print "Sending replay file: " + infile try: #self.ss.sendreplay(infile) os.system('scp -P "%s" "%s" scponly@"%s:%s"' % (port, infile, remotehost, remotefile)) except: print 'upload failed. replay not sent' continue print 'Sent replay' try: shutil.copy(infile, sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] self.playerlist.append({ 'clinum': id, 'acctid': 0, 'name': 'X', 'ip': ip }) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername def onAccountId(self, *args, **kwargs): self.ss = StatsServers() cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) name = client['name'] ip = client['ip'] server = self.serverid playerinfo = ("sync_user=1&username=%s&acc=%s&ip=%s&svr=%s" % (name, id, ip, server)) #Send info to PS2 self.ss.salvagestats(playerinfo) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) acct = client['acctid'] name = client['name'] server = self.serverid playerinfo = ("sync_user=2&username=%s&acc=%s&svr=%s" % (name, id, server)) #Send info to PS2 self.ss.salvagestats(playerinfo) def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class extras(ConsolePlugin): VERSION = "1.2.2" ms = None CHAT_INTERVAL = 10 CHAT_STAMP = 0 playerlist = [] itemlist = [] followlist = [] FOLLOWERS = 4 MAPSIZE = 0 MAPSIZESET = False buildingprotect = False def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) pass def RegisterScripts(self, **kwargs): #Setup everything for following self.followlist = [] followers = 1 framestring = "" while followers <= self.FOLLOWERS: followstring = ("\ RegisterGlobalScript -1 \"set _follower{0} #GetIndexFromClientNum(|#_f{0}|#)#;\ set _followed{0} #GetIndexFromClientNum(|#_fd{0}|#)#;\ set _fx{0} #GetPosX(|#_followed{0}|#)#;\ set _fy{0} #GetPosY(|#_followed{0}|#)#;\ set _x{0} #GetPosX(|#_follower{0}|#)#;\ set _y{0} #GetPosY(|#_follower{0}|#)#;\ set _z{0} #GetPosZ(|#_follower{0}|#)#;\ set _zs{0} #_x{0}#, #_y{0}#;\ set _zt{0} #GetTerrainHeight(|#_zs{0}|#)#;\ if [_z{0} < _zt{0}] set _z{0} [_zt{0} + 50];\ set _followX{0} 200;\ set _followY{0} 200;\ SetPosition #_follower{0}# [_fx{0} + _followX{0}] [_fy{0} + _followY{0}] [_z{0}]\" follow{0}").format(followers) framestring += (";if [_f{0} >= 0] ExecScript follow{0}").format(followers) kwargs['Broadcast'].broadcast("%s" % (followstring)) f = "_f{0}".format(followers) fd = "_fd{0}".format(followers) kwargs['Broadcast'].broadcast("set %s -1; set %s -1" % (f, fd)) self.followlist.append({'follower' : -1, 'followed' : -1, 'f' : f, 'fd' : fd}) followers += 1 kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _ii 0%s\" frame" % (framestring)) def getPlayerByClientNum(self, cli): client = None for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): client = None for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) if phase == 5: self.RegisterScripts(**kwargs) if phase == 6: self.RegisterScripts(**kwargs) #remove stuck for players for each in self.playerlist: each['stuck'] = False #set buildig protect scripts #TODO: make sure the place it moves them is a valid position if self.buildingprotect: kwargs['Broadcast'].broadcast("\ RegisterGlobalScript -1 \"RegisterEntityScript #GetScriptParam(index)# death \\\"Set _dead\ #GetScriptParam(index)#; ExecScript Death\\\";\ set _index #GetScriptParam(index)#; set _mz 350;\ set _type #GetScriptParam(type)#; echo #_type#; if #StringEquals(|#_type|#,Building_HumanHellShrine)#\ set _mz 2000; if #StringEquals(|#_type|#,Building_ArrowTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_CannonTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_ChlorophilicSpire)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_EntangleSpire)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_ShieldTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_StrataSpire)# set _mz 2000;\ set _x #GetPosX(|#_index|#)#;\ set _y #GetPosY(|#_index|#)#;\ set _z #GetPosZ(|#_index|#)#;\ SpawnEntityatEntity #_index# Trigger_Proximity model /core/null/null.mdf name DeathTrigger#_index# triggeronplayer 1 triggerradius\ 250 triggerenter\ \\\"set _domove 1; set _xindex #GetScriptParam(index)#;\ set _xtype #GetType(|#_xindex|#)#;\ if #StringEquals(|#_xtype|#,Player_Behemoth)# set _domove 0;\ if #StringEquals(|#_xtype|#,Player_Malphas)# set _domove 0;\ if #StringEquals(|#_xtype|#,Player_Devourer)# set _domove 0;\ set _xx #GetPosX(|#_xindex|#)#;\ set _xy #GetPosY(|#_xindex|#)#;\ set _xz #GetPosZ(|#_xindex|#)#;\ if [_domove == 1] SetPosition #_xindex# [_xx + 300] [_xy - 300] #_xz#\\\";\ SetPosition #GetIndexFromName(DeathTrigger|#_index|#)# #_x# #_y# [_z + _mz];\ echo\" buildingplaced") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"RemoveEntity #GetIndexFromName(DeathTrigger|#_dead|#)#; echo\" Death"); #get the map size #removing this for now as it is not used. Old55 2/10/12 #mapthread = threading.Thread(target=self.getMapSize, args=(), kwargs=kwargs) #mapthread.start() if phase == 7: for each in self.playerlist: each['team'] = 0 self.MAPSIZESET = False def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({ 'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'sf' : 0,\ 'lf' : 0,\ 'name' : 'X',\ 'team' : 0,\ 'stuck' : False,\ 'index' : 0,\ 'exp' : 2,\ 'value' : 150,\ 'prevent' : 0,\ 'active' : False,\ 'gamelevel' : 1}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False for each in self.followlist: if each ['follower'] == client['clinum'] or each['followed'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername mapmessage = "^cSpectators on this server can follow individual players. Send the message: ^rfollow playername. ^cTo stop following: ^rstop follow.\ ^cIf you get stuck on the map you can send the message: ^rstuck^c to nudge you out of your spot. This can be used once a game." kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) lf = int(stats['lf']) exp = int(stats['exp']) time = int(stats['secs']) client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['lf'] = lf client ['exp'] = exp client ['active'] = True def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team for each in self.followlist: if each ['follower'] == client['clinum'] or each['followed'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) #Various chat matches followed = re.match("follow (\S+)", message, flags=re.IGNORECASE) stopfollow = re.match("stop follow", message, flags=re.IGNORECASE) stuck = re.match("stuck", message, flags=re.IGNORECASE) if followed: action = 'start' followed_player = self.getPlayerByName(followed.group(1)) if followed_player == None: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cCould not find a player by that name." % (client['clinum'])) return if (followed_player ['team'] > 0) and (client ['team'] == 0): self.followaction(action, client, followed_player, **kwargs) if stopfollow: action = 'stop' self.followaction(action, client, followed_player=None, **kwargs) if stuck: if client['stuck']: return kwargs['Broadcast'].broadcast(\ "set _stuckindex #GetIndexFromClientNum(%s)#;\ set _X [rand*100]; echo #_X#;\ set _Y [rand*100]; echo #_Y#;\ set _stuckx #GetPosX(|#_stuckindex|#)#;\ set _stucky #GetPosY(|#_stuckindex|#)#;\ set _stuckz #GetPosZ(|#_stuckindex|#)#;\ SetPosition #_stuckindex# [_stuckx + _X] [_stucky + _Y] [_stuckz + 40]" % (client['clinum'])) client['stuck'] = True def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] if event == 'Follow': #Determine if it is follow or stop if value == 'stop': action = value self.followaction(action, client, followed_player=None, **kwargs) return else: action = 'start' followed_player = self.getPlayerByName(value) if (followed_player ['team'] > 0) and (client ['team'] == 0): self.followaction(action, client, followed_player, **kwargs) return #if event == 'SetMapPosition': # if client['team'] != 0: # return # maxcoord = ((self.MAPSIZE - 1) * 64 * 64) # print maxcoord # location = re.match("(0\.\d+)_(0.\d+)", value) # print location.group(1), location.group(2) # coordx = float(location.group(1))*maxcoord # coordy = float(location.group(2))*maxcoord # print coordx, coordy # kwargs['Broadcast'].broadcast(\ # "SetPosition #GetIndexFromClientNum(%s)# %s %s #GetPosZ(|#GetIndexFromClientNum(%s)|#)#" % (client['clinum'], coordx, coordy, client['clinum'])) def followaction(self, action, client, followed_player, **kwargs): if action == 'start': for each in self.followlist: #first check if they are already a follower if each ['follower'] == client['clinum']: each ['followed'] = followed_player['clinum'] self.follow(**kwargs) return for each in self.followlist: #if not already follower, grab the first available spot if each['follower'] == -1: each ['follower'] = client['clinum'] each ['followed'] = followed_player['clinum'] self.follow(**kwargs) return #If all the spots are filled, report it kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cThe follow list is full!" % (client['clinum'])) return if action == 'stop': for each in self.followlist: if each['follower'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def follow(self, **kwargs): for each in self.followlist: kwargs['Broadcast'].broadcast(\ "set %s %s; set %s %s" % (each['f'], each['follower'], each['fd'], each['followed'])) def getMapSize(self,**kwargs): checkdimension = 131071 self.MAPSIZE = 10 while not self.MAPSIZESET: time.sleep(0.5) self.MAPSIZESET = True checkdimension = checkdimension/2 kwargs['Broadcast'].broadcast("echo #GetTerrainHeight(%s,0)#" % (checkdimension)) print 'Map Size =', self.MAPSIZE time.sleep(1) def mapDimensions(self, *args, **kwargs): if self.MAPSIZE > 0: print 'made it to MAP DIMENSONS' self.MAPSIZE -= 1 self.MAPSIZESET = False def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class admin(ConsolePlugin): VERSION = "1.3.6" playerlist = [] adminlist = [] banlist = [] ipban = [] itemlist = [] PHASE = 0 CONFIG = None UPDATE = True NEEDRELOAD = False LASTMESSAGE = {'client' : None, 'firsttime' : 0, 'lasttime' : 0, 'repeat' : 0} def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) pass def reload_config(self): self.adminlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) def reload_plugins(self): config = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../s2wrapper.ini") print config ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'admin': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): self.playerlist = [] self.banlist = [] def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here #these are for identifying bought and sold items kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for each in self.ipban: if each == ip: reason = "You are banned from this server." kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (id, reason)) return reason = "An administrator has removed you from this server. You may rejoin the server after the current game ends." for each in self.banlist: if each == ip: kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (id, reason)) for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'ip' : ip,\ 'team' : 0,\ 'sf' : 0,\ 'active' : False,\ 'level' : 0,\ 'admin' : False,\ 'value' : 0,\ 'commander' : False}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def getAccountInfo(self, *args, **kwargs): client = self.getPlayerByClientNum(args[0]) stats = self.ms.getStatistics (client['acctid']).get ('all_stats').get (client['acctid']) level = int(stats['level']) sf = int(stats['sf']) client['sf'] = sf client['level'] = level client['active'] = True #If client has disconnected, give them their gold back self.giveGold(False, client, **kwargs) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) statthread = threading.Thread(target=self.getAccountInfo, args=(cli,None), kwargs=kwargs) statthread.start() if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as an administrator. Send the chat message: ^rhelp ^cto see what commands you can perform."\ % (cli)) client['admin'] = True if self.isSuperuser(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as superuser on this server. You can send console commands with chat message: ^rsudo <command>."\ % (cli)) def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each['name']: admin = True return admin def isSuperuser(self, client, **kwargs): superuser = False for each in self.adminlist: if client['name'].lower() == each['name']: if each['level'] == 'super': superuser = True return superuser def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) clinum = client['clinum'] admin = self.isAdmin(client, **kwargs) superuser = self.isSuperuser(client, **kwargs) #ADDED: more than 5 message in 1 second = kick tm = time.time() last = self.LASTMESSAGE['lasttime'] first = self.LASTMESSAGE['firsttime'] if (self.LASTMESSAGE['client'] == name): self.LASTMESSAGE['lasttime'] = tm #commanders are immune if not client['commander']: self.LASTMESSAGE['repeat'] += 1 print 'repeat' else: self.LASTMESSAGE['client'] = name self.LASTMESSAGE['firsttime'] = tm self.LASTMESSAGE['repeat'] = 0 if self.LASTMESSAGE['repeat'] > 4: if ((last - first) < 1): reason = "Spamming chat results in automatic kicking." kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (clinum, reason)) self.LASTMESSAGE['client'] = None self.LASTMESSAGE['repeat'] = 0 self.LASTMESSAGE['firsttime'] = 0 self.LASTMESSAGE['lasttime'] = 0 else: self.LASTMESSAGE['repeat'] = 0 self.LASTMESSAGE['client'] = None self.LASTMESSAGE['firsttime'] = 0 self.LASTMESSAGE['lasttime'] = 0 request = re.match("request admin", message, flags=re.IGNORECASE) if request: for each in self.playerlist: if each['active'] and each['admin']: kwargs['Broadcast'].broadcast("SendMessage %s Admin present: ^y%s" % (client['clinum'], each['name'])) #ignore everything else if it isn't from admin if not admin: return #Pass to superCommand if the player is a superuser if superuser: self.superCommand(message, **kwargs) #Matches for normal admins restart = re.match("admin restart", message, flags=re.IGNORECASE) shuffle = re.match("admin shuffle", message, flags=re.IGNORECASE) kick = re.match("admin kick (\S+)", message, flags=re.IGNORECASE) ban = re.match("admin ban (\S+)", message, flags=re.IGNORECASE) slap = re.match("admin slap (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("admin changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("help", message, flags=re.IGNORECASE) balance = re.match("admin balance", message, flags=re.IGNORECASE) getbalance = re.match("admin get balance", message, flags=re.IGNORECASE) reportbal = re.match("admin report balance", message, flags=re.IGNORECASE) if restart: #restarts server if something catastrophically bad has happened kwargs['Broadcast'].broadcast("restart") if shuffle: #artificial shuffle vote if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot shuffle until the game has started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has shuffled the game." % (name)) self.listClients(**kwargs) shufflethread = threading.Thread(target=self.onShuffle, args=(clinum,None), kwargs=kwargs) shufflethread.start() if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\""\ % (kickclient['clinum'], reason)) if ban: #kicks a player from the server and temporarily bans that player's IP till the game is over reason = "An administrator has banned you from the server. You are banned till this game is over." kickclient = self.getPlayerByName(ban.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) self.banlist.append(kickclient['ip']) if slap: #slap will move a player x+100, y+200 to get them off of a structure slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists"\ % (slapclient['clinum'], slapclient['clinum'])) if changeworld: #change the map kwargs['Broadcast'].broadcast(\ "changeworld %s"\ % (changeworld.group(1))) if balance: if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot balance if the game has not started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has balanced the game." % (name)) self.listClients(**kwargs) balancethread = threading.Thread(target=self.onBalance, args=(clinum, None), kwargs=kwargs) balancethread.start() if getbalance: self.listClients(**kwargs) balancethread = threading.Thread(target=self.getBalance, args=(clinum, None), kwargs=kwargs) balancethread.start() if reportbal: self.listClients(**kwargs) balancethread = threading.Thread(target=self.reportBalance, args=(), kwargs=kwargs) balancethread.start() self.logCommand(client['name'],message) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. All commands are logged to prevent you from abusing them.The following are commands and a short description of what they do."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin restart ^whard reset of the server. ONLY use in weird cases."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin shuffle ^wwill shuffle the game and set to previous phase."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmi kick playername ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin ban playername ^wwill remove a player from the server and ban that IP address till the end of the game."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin slap playername ^wwill move the player. Use to get them off of structures if they are exploiting."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin balance ^wwill move two players to achieve balance."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin get balance ^wwill report avg. and median SF values for the teams as well as a stack value."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin report balance ^wwill send a message to ALL players that has the avg. and median SF values."\ % (client['clinum'])) def getBalance(self, *args, **kwargs): clinum = args[0] for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s. ^yStack value: ^r%s" \ % (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) def reportBalance(self, **kwargs): for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo), 1) kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s.^y Stack value: ^r%s" \ % (teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'], 1), round(teamtwostats['median'],1), abs(stack))) def superCommand(self, message, **kwargs): #This allows superuser to issue any console command supercommand = re.match("sudo (.*)", message, flags=re.IGNORECASE) if supercommand: kwargs['Broadcast'].broadcast("%s" % (supercommand.group(1))) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False each['value'] = 0 if (phase == 6): if self.UPDATE: #fetch admin list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() #check if server is empty after 2 minutes pluginthread = threading.Thread(target=self.pluginreload, args=(), kwargs=kwargs) pluginthread.start() self.RegisterScripts(**kwargs) self.ItemList() if (phase == 4): kwargs['Broadcast'].broadcast("listclients") def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/admin.ini') adminlist = response.read() f = open(self.CONFIG, 'w') f.write(adminlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() if self.NEEDRELOAD: self.pluginreload(**kwargs) return #Update the wrapper try: gitpath = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../.git") command = ["git","--git-dir",gitpath,"pull"] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate() result = output[0].split("\n")[0] print 'result is %s' % result #TODO: make sure these work on all servers? notneeded = re.match("Already up-to-date.", result) needed = re.match("Updating .*", result) except: print 'error getting git update' return if notneeded: print 'update not needed' self.NEEDRELOAD = False return if needed: print 'update needed' self.NEEDRELOAD = True self.pluginreload(**kwargs) return def pluginreload(self, **kwargs): print 'pluginreload called' #Wait a couple minutes to allow clients to connect time.sleep(120) #Figure out how many clients are present kwargs['Broadcast'].broadcast("serverstatus") def onServerStatusResponse(self, *args, **kwargs): if self.NEEDRELOAD: gamemap = args[0] active = int(args[2]) if active == 0: self.reload_plugins() kwargs['Broadcast'].broadcast("NextPhase; PrevPhase") self.NEEDRELOAD = False def logCommand(self, client, message, **kwargs): localtime = time.localtime(time.time()) date = ("%s-%s-%s, %s:%s:%s" % (localtime[1], localtime[2], localtime[0], localtime[3], localtime[4], localtime[5])) f = open('admin.log', 'a') f.write("Timestamp: \"%s\", Admin: %s, Command: %s\n" % (date, client, message)) f.close def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team def onShuffle (self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 each['value'] = 0 clinum = args[0] time.sleep(2) shufflelist = [] #Put all the active players in a list for each in self.playerlist: if not each['active']: continue if each['team'] > 0: shufflelist.append(each) #sort shufflelists based on SF shufflelist = sorted(shufflelist, key=itemgetter('sf', 'level', 'clinum'), reverse=True) #randomly choose if we begin with human or beast r = random.randint(1,2) #Assign new teams, just like the K2 way, but Ino won't always be on humans for each in shufflelist: #TODO: is there a cleaner, more pythonic way to do this? each['team'] = r if r == 1: r += 1 elif r == 2: r -=1 #Now actually do the shuffling for each in shufflelist: kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (each['clinum'], each['team'])) #Finish it off by going forward a phase kwargs['Broadcast'].broadcast(\ "nextphase") kwargs['Broadcast'].broadcast(\ "SendMessage %s You have shuffled the game." % (clinum)) #Run balancer to get it nice and even self.onBalance(clinum, **kwargs) def onBalance(self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) #Get Information about the teams teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) startstack = self.evaluateBalance(teamone, teamtwo) #Send message to admin that called the shuffle/balance kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yPrior to balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s" \ % (args[0], teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) #Find the players to swap lowest = -1 pick1 = None pick2 = None for player1 in teamone: if player1['commander']: continue for player2 in teamtwo: if player2['commander']: continue #sort of inefficient to send the teamlist each time ltarget = self.evaluateBalance(teamone, teamtwo, player1, player2, True) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 #If the stack isn't improved, abort it if (lowest >= startstack): print 'unproductive balance. terminate' kwargs['Broadcast'].broadcast(\ "echo unproductive balance") return #Do the switch kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 2;\ set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 1"\ % (pick1['clinum'], pick2['clinum'])) #Give them gold if needed self.giveGold(True, pick1, **kwargs) self.giveGold(True, pick2, **kwargs) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #kwargs['Broadcast'].broadcast(\ # "SendMessage %s ^yAfter balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s"\ # % (clinum, teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) def getTeamInfo(self, teamlist, **kwargs): teamsf = [] combteamsf = float(0) #figure out current averages and set some commonly used variables: for each in teamlist: combteamsf += each['sf'] teamsf.append(each['sf']) sizeteam = len(teamlist) avgteam = combteamsf/sizeteam med = median(teamsf) teaminfo = {'size' : sizeteam, 'avg' : avgteam, 'total' : combteamsf, 'median' : med} return teaminfo def evaluateBalance(self, team1, team2, pick1=None, pick2=None, swap=False, **kwargs): #This function will swap out the picked players in a temporary list if swap is true and report the stack percent #If swap is false, it will just report the balance #First, make new lists that we can modify: teamone = list(team1) teamtwo = list(team2) if swap: #Remove those players from the lists... for each in teamone: if each['clinum'] == pick1['clinum']: teamone.remove(each) for each in teamtwo: if each['clinum'] == pick2['clinum']: teamtwo.remove(each) #Add to the lists teamone.append(pick2) teamtwo.append(pick1) #Get the new team stats... teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #Evaluate team balance teamoneshare = teamonestats['total']/(teamonestats['total'] + teamtwostats['total']) diffmedone = teamonestats['median']/(teamonestats['median'] + teamtwostats['median']) stack = teamoneshare + diffmedone #positive if team one is stacked, negative if team two is stacked return (stack - 1) * 100 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) client['commander'] = False def onUnitChange(self, *args, **kwargs): if args[1] != "Player_Commander": return cli = args[0] client = self.getPlayerByClientNum(cli) client['commander'] = True def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #TODO: listclients clinum is always double diget (00, 01, etc.) so this might be a problem acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights' : 700, 'Ammo Pack' : 500, 'Ammo Satchel' : 200, 'Chainmail' : 300, 'Gust of Wind' : 450, 'Magic Amplifier' : 700, 'Brain of Maliken' : 750, 'Heart of Maliken' : 950, 'Lungs of Maliken' : 800, 'Mana Crystal' : 500, 'Mana Stone' : 200, 'Platemail' : 650, 'Power Absorption' : 350, 'Shield of Wisdom' : 650, 'Stone Hide' : 650, 'Tough Skin' : 300, 'Trinket of Restoration' : 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def giveGold(self, balance, client, **kwargs): if client['value'] == 0: return gold = round(client['value']/2, 0) if balance: gold = client['value'] kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou have been compensated %s gold for your lost items.; GiveGold %s %s"\ % (client['clinum'], gold, client['clinum'], gold)) client['value'] = 0
class pug(ConsolePlugin): VERSION = "1.0.1" ms = None PHASE = 0 STARTSTAMP = 0 STARTED = False PICKING = False HUMANPICK = False playerlist = [] startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} teamlist = []; TIME = 0 def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) ''' for (name, value) in ini.items('var'): if (name == "clan1"): self.CLAN1 = value if (name == "clan2"): self.CLAN2 = value ''' pass def onStartServer(self, *args, **kwargs): self.PHASE = 0 self.playerlist = [] self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'ip' : ip,\ 'sf' : 0,\ 'name' : 'X',\ 'active' : False,\ 'team' : 0,\ 'ping' : 0,\ 'clan' : 'X'}) #kwargs['Broadcast'].broadcast("SendMessage %s ^cTo toggle your PUG availability send the chat message ^rpug noplay" % (id)) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"; set Pet_HumanWorker_Inventory9 \"\";") if self.PICKING: resetall(**kwargs) if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 1\"; set Pet_BeastWorker_Inventory9 \"\";") if self.PICKING: resetall(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername client ['play'] = True kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"showwidget pug_button\"" % (cli)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) exp = int(stats['exp']) time = int(stats['secs']) time = time/60 #sf = int(exp/time) clan = stats['clan_tag'] client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['active'] = True client ['clan'] = clan client ['newteam'] = 0 kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"showwidget pug_button\"" % (cli)) if self.PICKING: kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"hidewidget team_button0; hidewidget team_button1\"" % (cli)) def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team if self.PICKING: for each in self.teamlist: if (each['player'] == cli) and (team != each['team']): #don't let them switch kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['player'],each['team'])) return #kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['player'])) def onGameStart (self, *args, **kwargs): self.STARTSTAMP = args[1] def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if phase == 5: self.STARTSTAMP = args[1] self.STARTED = True self.PICKING = False if phase == 6: self.PICKING = False self.teamlist = [] self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set sv_maxteamdifference 10;\ set Pet_Shaman_Prerequisite 1;\ set Pet_HumanWorker_Inventory9 \"\";\ set Pet_BeastWorker_Inventory9 \"\";") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput") kwargs['Broadcast'].broadcast("ClientExecScript -1 clientdo cmd \"showwidget team_button0; showwidget team_button1\"") if phase == 7: for each in self.playerlist: each['newteam'] = 0 self.PICKING = False self.STARTED = False resetall(**kwargs) def togglePlay(self, client, playing=None, **kwargs): color = '^g' if self.PICKING: kwargs['Broadcast'].broadcast("SendMessage %s ^rYou cannot toggle your status once picking has begun." % (client['clinum'])) return if not playing: if client['play']: client['play'] = False color = '^r' else: client['play'] = True else: client['play'] = playing if not client['play']: color = '^r' #kwargs['Broadcast'].broadcast("SendMessage %s ^cYour Playing Status: %s%s" % (client['clinum'], color, client['play'])) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] #info = self.startinfo #Captain initiated if event == 'Captain': #If they are already captain, do nothing if caller == self.startinfo['b_captain'] or caller == self.startinfo['h_captain']: return #Beasts, set captain if value == 'beasts': self.startinfo['b_captain'] = caller kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 0\"; set Pet_BeastWorker_Inventory9 \"%s\"" % (client['name'])) if not self.startinfo['h_captain']: self.startinfo['h_first'] = True #Humans, set captain if value == 'humans': self.startinfo['h_captain'] = caller kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 0\"; set Pet_HumanWorker_Inventory9 \"%s\"" % (client['name'])) if not self.startinfo['b_captain']: self.startinfo['b_first'] = True #Check if picking is initiated, if so determine who gets the next picking if self.PICKING: self.setpicking(**kwargs) return #Start picking process through the normal mechanism if self.startinfo['h_captain'] and self.startinfo['b_captain']: self.beginpicking(**kwargs) #Toggle player availability if event == 'Toggle': playing = False if value == 'true': playing = True self.togglePlay(client, playing, **kwargs) #Player select if event == 'Select': player = self.getPlayerByName(value) #switch everything to ingame_picking function if the game is already started if self.PHASE == 5: #pickthread = threading.Thread(target=self.ingame_picking, args=(caller, client, player, None), kwargs=kwargs) #pickthread.start() #self.ingame_picking(caller, client, player, **kwargs) print 'Will go to ingame picking' if caller == self.startinfo['h_captain']: #check players status if not player['play']: kwargs['Broadcast'].broadcast("SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 1 client['newteam'] = 1 self.teamlist.append({"player" : player["clinum"], "team" : 1}); kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Humans!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (player['clinum'])) kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain'])) self.HUMANPICK = False if caller == self.startinfo['b_captain']: if not player['play']: kwargs['Broadcast'].broadcast("SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 2 client['newteam'] = 2 self.teamlist.append({"player" : player["clinum"], "team" : 2}); kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Beasts!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (player['clinum'])) kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'],self.startinfo['h_captain'] )) self.HUMANPICK = True if self.PICKING: self.setpicking(**kwargs) #Ready if event == 'Ready': if self.STARTED: return if caller == self.startinfo['h_captain']: if self.startinfo['h_ready']: return self.startinfo['h_ready'] = True kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has indicated that Humans are ready!" % (client['name'])) if caller == self.startinfo['b_captain']: if self.startinfo['b_ready']: return self.startinfo['b_ready'] = True kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has indicated that Beasts are ready!" % (client['name'])) #Start the game if both captains say they are ready if self.startinfo['h_ready'] and self.startinfo['b_ready']: kwargs['Broadcast'].broadcast("set State_ImpPoisoned_Name \"trigger UpdateSpeed 0\"") self.populate(**kwargs) if event == 'Resign': #if pick has begun and a captain resigns, just reset the whole damn thing if self.PICKING: self.resetall(**kwargs); if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"; set Pet_HumanWorker_Inventory9 \"\";") if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 1\"; set Pet_BeastWorker_Inventory9 \"\";") #self.setpicking(**kwargs) def resetall(self, **kwargs): self.PICKING = False self.teamlist = [] self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set sv_maxteamdifference 10;\ set Pet_Shaman_Prerequisite 1;\ set Pet_HumanWorker_Inventory9 \"\";\ set Pet_BeastWorker_Inventory9 \"\";") kwargs['Broadcast'].broadcast("ClientExecScript -1 clientdo cmd \"showwidget team_button0; showwidget team_button1\"") for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0; SendMessage -1 ^yTeams are reset after captain resignation." % (each['clinum'])) def RegisterStart(self, **kwargs): self.PICKING = True def beginpicking(self, **kwargs): #move everyone to spec for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['clinum'])) self.teamlist = []; #start by making the teams unjoinable kwargs['Broadcast'].broadcast("set sv_setupTimeCommander 600000000; set sv_maxteamdifference 1; set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 0\";") kwargs['Broadcast'].broadcast("ClientExecScript -1 clientdo cmd \"hidewidget team_button0; hidewidget team_button1\"") #move captains to the appropriate team and have them switch back to lobby for each in self.playerlist: if each['clinum'] == self.startinfo['h_captain']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (each['clinum'])) if each['clinum'] == self.startinfo['b_captain']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (each['clinum'])) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"Action ToggleLobby\"" % (self.startinfo['h_captain'])) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"Action ToggleLobby\"" % (self.startinfo['b_captain'])) self.teamlist.append({"player" : self.startinfo['h_captain'], "team" : 1}); self.teamlist.append({"player" : self.startinfo['b_captain'], "team" : 2}); #Set variables to get the first captain to start picking if self.startinfo['h_first']: self.HUMANPICK = True self.setpicking(**kwargs) else: self.HUMANPICK = False self.setpicking(**kwargs) kwargs['Broadcast'].broadcast("echo STARTTOURNEY") def populate(self, **kwargs): for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['clinum'], each['newteam'])) #Send to the next phase kwargs['Broadcast'].broadcast("NextPhase; set sv_setupTimeCommander 60000; PrevPhase") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] try: client = self.getPlayerByName(name) except: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) def onServerStatus(self, *args, **kwargs): if self.STARTED != 1: return pickthread = threading.Thread(target=self.ingame_picking, args=(), kwargs=kwargs) pickthread.start() def ingame_picking(self, *args, **kwargs): self.listClients(self, **kwargs) teamone = [] teamtwo = [] time.sleep(1) #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) #figure out who gets the pick team1 = len(teamone) team2 = len(teamtwo) if team1 > team2: self.HUMANPICK = False self.setpicking(**kwargs) if team2 > team1: self.HUMANPICK = True self.setpicking(**kwargs) if team1 == team2: return def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #TODO: listclients clinum is always double diget (00, 01, etc.) so this might be a problem acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def setpicking(self, **kwargs): if self.HUMANPICK: kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'],self.startinfo['h_captain'] )) else: kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain']))
class helper(ConsolePlugin): VERSION = "0.0.1" playerlist = [] helperlist = [] PHASE = 0 CONFIG = None def onPluginLoad(self, config): self.ms = MasterServer() self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level': value}) pass def reload_config(self): self.helperlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level': value}) def onStartServer(self, *args, **kwargs): self.playerlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'active' : False,\ 'helper' : False,\ 'level' : 0}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics(id).get('all_stats').get(int(id)) level = int(stats['level']) sf = int(stats['sf']) client = self.getPlayerByClientNum(cli) client['sf'] = sf client['level'] = level client['active'] = True client['helper'] = False if client['level'] <= 10: self.helperNotify(client, **kwargs) for each in self.helperlist: if client['name'].lower() == each['name']: client['helper'] = True def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False if (phase == 6): #fetch helper list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/helper.ini') helperlist = response.read() f = open(self.CONFIG, 'w') f.write(helperlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() def helperNotify(self, client, **kwargs): activehelpers = [] for player in self.playerlist: if player['helper'] and player['active']: activehelpers.append(player['name']) activestring = ', '.join(activehelpers) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rATTENTION: ^cAs a new player it so good to get help from more experienced players. The following players on this server have \ indicated their willingness to help newer players: ^y%s. ^cYou can contact them by using chat (^wCTRL+ENTER^c) and whispering them (^y/w playername^c with your message)." % (client['clinum'], activestring)) def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class extras(ConsolePlugin): VERSION = "1.2.2" ms = None CHAT_INTERVAL = 10 CHAT_STAMP = 0 playerlist = [] itemlist = [] followlist = [] FOLLOWERS = 4 MAPSIZE = 0 MAPSIZESET = False buildingprotect = False def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) pass def RegisterScripts(self, **kwargs): #Setup everything for following self.followlist = [] followers = 1 framestring = "" while followers <= self.FOLLOWERS: followstring = ("\ RegisterGlobalScript -1 \"set _follower{0} #GetIndexFromClientNum(|#_f{0}|#)#;\ set _followed{0} #GetIndexFromClientNum(|#_fd{0}|#)#;\ set _fx{0} #GetPosX(|#_followed{0}|#)#;\ set _fy{0} #GetPosY(|#_followed{0}|#)#;\ set _x{0} #GetPosX(|#_follower{0}|#)#;\ set _y{0} #GetPosY(|#_follower{0}|#)#;\ set _z{0} #GetPosZ(|#_follower{0}|#)#;\ set _zs{0} #_x{0}#, #_y{0}#;\ set _zt{0} #GetTerrainHeight(|#_zs{0}|#)#;\ if [_z{0} < _zt{0}] set _z{0} [_zt{0} + 50];\ set _followX{0} 200;\ set _followY{0} 200;\ SetPosition #_follower{0}# [_fx{0} + _followX{0}] [_fy{0} + _followY{0}] [_z{0}]\" follow{0}" ).format(followers) framestring += ( ";if [_f{0} >= 0] ExecScript follow{0}").format(followers) kwargs['Broadcast'].broadcast("%s" % (followstring)) f = "_f{0}".format(followers) fd = "_fd{0}".format(followers) kwargs['Broadcast'].broadcast("set %s -1; set %s -1" % (f, fd)) self.followlist.append({ 'follower': -1, 'followed': -1, 'f': f, 'fd': fd }) followers += 1 kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"set _ii 0%s\" frame" % (framestring)) def getPlayerByClientNum(self, cli): client = None for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): client = None for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) if phase == 5: self.RegisterScripts(**kwargs) if phase == 6: self.RegisterScripts(**kwargs) #remove stuck for players for each in self.playerlist: each['stuck'] = False #set buildig protect scripts #TODO: make sure the place it moves them is a valid position if self.buildingprotect: kwargs['Broadcast'].broadcast("\ RegisterGlobalScript -1 \"RegisterEntityScript #GetScriptParam(index)# death \\\"Set _dead\ #GetScriptParam(index)#; ExecScript Death\\\";\ set _index #GetScriptParam(index)#; set _mz 350;\ set _type #GetScriptParam(type)#; echo #_type#; if #StringEquals(|#_type|#,Building_HumanHellShrine)#\ set _mz 2000; if #StringEquals(|#_type|#,Building_ArrowTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_CannonTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_ChlorophilicSpire)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_EntangleSpire)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_ShieldTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_StrataSpire)# set _mz 2000;\ set _x #GetPosX(|#_index|#)#;\ set _y #GetPosY(|#_index|#)#;\ set _z #GetPosZ(|#_index|#)#;\ SpawnEntityatEntity #_index# Trigger_Proximity model /core/null/null.mdf name DeathTrigger#_index# triggeronplayer 1 triggerradius\ 250 triggerenter\ \\\"set _domove 1; set _xindex #GetScriptParam(index)#;\ set _xtype #GetType(|#_xindex|#)#;\ if #StringEquals(|#_xtype|#,Player_Behemoth)# set _domove 0;\ if #StringEquals(|#_xtype|#,Player_Malphas)# set _domove 0;\ if #StringEquals(|#_xtype|#,Player_Devourer)# set _domove 0;\ set _xx #GetPosX(|#_xindex|#)#;\ set _xy #GetPosY(|#_xindex|#)#;\ set _xz #GetPosZ(|#_xindex|#)#;\ if [_domove == 1] SetPosition #_xindex# [_xx + 300] [_xy - 300] #_xz#\\\";\ SetPosition #GetIndexFromName(DeathTrigger|#_index|#)# #_x# #_y# [_z + _mz];\ echo\" buildingplaced") kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"RemoveEntity #GetIndexFromName(DeathTrigger|#_dead|#)#; echo\" Death" ) #get the map size #removing this for now as it is not used. Old55 2/10/12 #mapthread = threading.Thread(target=self.getMapSize, args=(), kwargs=kwargs) #mapthread.start() if phase == 7: for each in self.playerlist: each['team'] = 0 self.MAPSIZESET = False def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({ 'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'sf' : 0,\ 'lf' : 0,\ 'name' : 'X',\ 'team' : 0,\ 'stuck' : False,\ 'index' : 0,\ 'exp' : 2,\ 'value' : 150,\ 'prevent' : 0,\ 'active' : False,\ 'gamelevel' : 1}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client['active'] = False for each in self.followlist: if each['follower'] == client['clinum'] or each[ 'followed'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername mapmessage = "^cSpectators on this server can follow individual players. Send the message: ^rfollow playername. ^cTo stop following: ^rstop follow.\ ^cIf you get stuck on the map you can send the message: ^rstuck^c to nudge you out of your spot. This can be used once a game." kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics(id).get('all_stats').get(int(id)) level = int(stats['level']) sf = int(stats['sf']) lf = int(stats['lf']) exp = int(stats['exp']) time = int(stats['secs']) client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) client['level'] = level client['sf'] = sf client['lf'] = lf client['exp'] = exp client['active'] = True def onTeamChange(self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team for each in self.followlist: if each['follower'] == client['clinum'] or each[ 'followed'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) #Various chat matches followed = re.match("follow (\S+)", message, flags=re.IGNORECASE) stopfollow = re.match("stop follow", message, flags=re.IGNORECASE) stuck = re.match("stuck", message, flags=re.IGNORECASE) if followed: action = 'start' followed_player = self.getPlayerByName(followed.group(1)) if followed_player == None: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cCould not find a player by that name." % (client['clinum'])) return if (followed_player['team'] > 0) and (client['team'] == 0): self.followaction(action, client, followed_player, **kwargs) if stopfollow: action = 'stop' self.followaction(action, client, followed_player=None, **kwargs) if stuck: if client['stuck']: return kwargs['Broadcast'].broadcast(\ "set _stuckindex #GetIndexFromClientNum(%s)#;\ set _X [rand*100]; echo #_X#;\ set _Y [rand*100]; echo #_Y#;\ set _stuckx #GetPosX(|#_stuckindex|#)#;\ set _stucky #GetPosY(|#_stuckindex|#)#;\ set _stuckz #GetPosZ(|#_stuckindex|#)#;\ SetPosition #_stuckindex# [_stuckx + _X] [_stucky + _Y] [_stuckz + 40]" % (client['clinum'])) client['stuck'] = True def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] if event == 'Follow': #Determine if it is follow or stop if value == 'stop': action = value self.followaction(action, client, followed_player=None, **kwargs) return else: action = 'start' followed_player = self.getPlayerByName(value) if (followed_player['team'] > 0) and (client['team'] == 0): self.followaction(action, client, followed_player, **kwargs) return #if event == 'SetMapPosition': # if client['team'] != 0: # return # maxcoord = ((self.MAPSIZE - 1) * 64 * 64) # print maxcoord # location = re.match("(0\.\d+)_(0.\d+)", value) # print location.group(1), location.group(2) # coordx = float(location.group(1))*maxcoord # coordy = float(location.group(2))*maxcoord # print coordx, coordy # kwargs['Broadcast'].broadcast(\ # "SetPosition #GetIndexFromClientNum(%s)# %s %s #GetPosZ(|#GetIndexFromClientNum(%s)|#)#" % (client['clinum'], coordx, coordy, client['clinum'])) def followaction(self, action, client, followed_player, **kwargs): if action == 'start': for each in self.followlist: #first check if they are already a follower if each['follower'] == client['clinum']: each['followed'] = followed_player['clinum'] self.follow(**kwargs) return for each in self.followlist: #if not already follower, grab the first available spot if each['follower'] == -1: each['follower'] = client['clinum'] each['followed'] = followed_player['clinum'] self.follow(**kwargs) return #If all the spots are filled, report it kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cThe follow list is full!" % (client['clinum'])) return if action == 'stop': for each in self.followlist: if each['follower'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def follow(self, **kwargs): for each in self.followlist: kwargs['Broadcast'].broadcast(\ "set %s %s; set %s %s" % (each['f'], each['follower'], each['fd'], each['followed'])) def getMapSize(self, **kwargs): checkdimension = 131071 self.MAPSIZE = 10 while not self.MAPSIZESET: time.sleep(0.5) self.MAPSIZESET = True checkdimension = checkdimension / 2 kwargs['Broadcast'].broadcast("echo #GetTerrainHeight(%s,0)#" % (checkdimension)) print 'Map Size =', self.MAPSIZE time.sleep(1) def mapDimensions(self, *args, **kwargs): if self.MAPSIZE > 0: print 'made it to MAP DIMENSONS' self.MAPSIZE -= 1 self.MAPSIZESET = False def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class admin(ConsolePlugin): VERSION = "1.6.3" playerlist = [] adminlist = [] banlist = [] fullbanlist = [] ipban = [] itemlist = [] PHASE = 0 CONFIG = None UPDATE = True NEEDRELOAD = False LASTMESSAGE = {'client' : None, 'firsttime' : 0, 'lasttime' : 0, 'repeat' : 0} DLL = '2f4827b8' norunes = 0 def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(config) + "/ban.ini" banini.read (banconfig) ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ipban'): self.ipban.append(name) pass def reload_config(self): self.adminlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(self.CONFIG) + "/ban.ini" banini.read (banconfig) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ban'): self.fullbanlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ipban'): self.ipban.append(name) def reload_plugins(self): config = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../s2wrapper.ini") ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'admin': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): kwargs['Broadcast'].broadcast("Set norunes 0") kwargs['Broadcast'].broadcast("exec patch.cfg") self.playerlist = [] self.banlist = [] def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput") #these are for identifying bought and sold items kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem") if self.norunes == 1: kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _buyindex #GetIndexFromClientNum(|#_client|#)#;\ set _none \"\"; set _item #GetScriptParam(itemname)#;\ if #StringEquals(|#_item|#,|#_none|#)# TakeItem #_buyindex# #GetScriptParam(slot)#;\ if #StringEquals(|#_item|#,|#_none|#)# SendMessage #GetScriptParam(clientid)# ^yYou cannot equip persistent items on this server;\ echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") else: kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#;\ echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") kwargs['Broadcast'].broadcast("set con_showerr false; set con_showwarn false;") kwargs['Broadcast'].broadcast("Set Entity_NpcController_Name \"S2WRAPPER\"") #kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set kid #GetScriptParam(clientid)#; set kcheck _karmaflag#kid#; if [kcheck > 0] clientexecscript clientdo #kid# cmd \\\"set voice_disabled true\\\"; echo\" spawn") def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for each in self.ipban: if each == ip: reason = "You are banned from this server." kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"SetSave host_onload true; SetSave host_created 1; WriteConfigScript ~/startup.cfg\"" % (id)) kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"quit\"" % (id)) kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (id, reason)) return reason = "An administrator has removed you from this server. You may rejoin the server after the current game ends." for each in self.banlist: if each == ip: kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (id, reason)) for client in self.playerlist: if (client['clinum'] == id): client['ip'] = ip return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'ip' : ip,\ 'team' : 0,\ 'sf' : 0,\ 'active' : False,\ 'level' : 0,\ 'admin' : False,\ 'value' : 0,\ 'karma' : 0,\ 'commander' : False,\ 'req' : 0,\ 'flood' : None,\ 'f_req' : 0,\ 'l_req' : 0,\ 'msgsum' : None}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] if playername == "": reason = "You dont seem to have a name, thats odd." kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, reason)) client = self.getPlayerByClientNum(cli) client ['name'] = playername def getAccountInfo(self, *args, **kwargs): client = self.getPlayerByClientNum(args[0]) stats = self.ms.getStatistics (client['acctid']).get ('all_stats').get (client['acctid']) level = int(stats['level']) sf = int(stats['sf']) karma = int(stats['karma']) client['sf'] = sf client['level'] = level client['karma'] = karma client['active'] = True #kwargs['Broadcast'].broadcast(\ #"clientexecscript %s clientdo cmd \"set _vr #StringLength(|#GetCheckSum(cgame.dll)|#)#; if [_vr > 0] \\\"SendScriptInput what DLL value #getchecksum(cgame.dll)#\\\"; Else \\\"SendScriptInput what DLL value NONE\\\"\"" % (client['clinum'])) if karma < 0: kwargs['Broadcast'].broadcast(\ "set _karmaflag%s 1" % (client['clinum'])) #If client has disconnected, give them their gold back self.giveGold(False, client, **kwargs) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) statthread = threading.Thread(target=self.getAccountInfo, args=(cli,None), kwargs=kwargs) statthread.start() if self.isBanned(client, **kwargs): kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"SetSave cl_packetSendFPS 1\"" % (cli)) if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as an administrator. Use ^radmin <command>^c to execute commands through chat.^c You can get help by sending ^radmin help ^cto chat." % (cli)) client['admin'] = True if self.isSuperuser(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as superuser on this server. You can send console commands with chat message: ^rsudo <command>." % (cli)) def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each['name']: admin = True return admin def isSuperuser(self, client, **kwargs): superuser = False for each in self.adminlist: if client['name'].lower() == each['name']: if each['level'] == 'super': superuser = True return superuser def isBanned(self, client, **kwargs): banned = False for each in self.fullbanlist: if client['name'].lower() == each['name']: if each['level'] == 'banned': banned = True return banned def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) clinum = client['clinum'] admin = self.isAdmin(client, **kwargs) superuser = self.isSuperuser(client, **kwargs) # --- # MORE THEN FLOOD REPEATS(3)=4 A SEC(1) = kick FLOOD_REPEATS = 2 FLOOD_A_SEC = 0.5 if not client['flood']: client['flood'] = { 'time' : 0, 'count' : 0 } flood = client['flood'] print "flood: %s - %f - %f = %f" % (flood['count'], time.time (), flood['time'], (time.time ()-flood['time'])) # Sickened2: spam-check based on message length and checksum msglen = len(list(message)) if msglen > 100: # this should be a lookup table for checksums of typical spam messages spam1chksum = "ec10ca635bb6b956959830f4e652369d" m = hashlib.md5() m.update(message[:100]) chksum = m.hexdigest() if chksum == spam1chksum: reason = "Attention! Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) elif not client['msgsum']: client['msgsum'] = chksum #print "Checksum" #print client['msgsum'] elif client['msgsum'] == chksum: reason = "Attention! Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) else: client['msgsum'] = chksum # Sickened2: the following method is not as effective because # 1) for large messages (e.g. > 250 bytes) part of the message is returned. For the same message length the # size could vary. So we can't use the message length reliably # 2) if 2 chat packets are sent to the server and the 1st one arrives with delay but in the correct order, # the difference between the time of arrival between the two packets is shorter than the difference # between the departure time of the two packets ## Sickened2: additional spam check; user is not capable of manually typing more than ## MAX_TYPING_SPEED characters per second (avg) #MAX_TYPING_SPEED = 212; # chars/sec #msglen = len(list(message)) #print "msglen = %d" % msglen #timediff = time.time () - flood['time'] #print "timediff = %f" % timediff ##print("len(list(message)) / timediff ={0}".format(len(list(message)) / timediff)) #if msglen / timediff > MAX_TYPING_SPEED: # reason = "Sigh. Spamming results in automatic kicking." # kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) if (time.time () - flood['time']) < FLOOD_A_SEC: flood['count'] += 1 if flood['count'] > FLOOD_REPEATS: reason = "Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) else: flood['count'] = 0 flood['time'] = time.time () request = re.match("request admin", message, flags=re.IGNORECASE) if request: for each in self.playerlist: if each['active'] and each['admin']: kwargs['Broadcast'].broadcast("SendMessage %s Admin present: ^y%s" % (client['clinum'], each['name'])) #ignore everything else if it isn't from admin if not admin: return if superuser: self.superCommand(message, **kwargs) #Matches for normal admins restart = re.match("admin restart", message, flags=re.IGNORECASE) shuffle = re.match("admin shuffle", message, flags=re.IGNORECASE) kick = re.match("admin kick (\S+)", message, flags=re.IGNORECASE) ban = re.match("admin ban (\S+)", message, flags=re.IGNORECASE) timeout = re.match("admin timeout (\S+)", message, flags=re.IGNORECASE) slap = re.match("admin slap (\S+)", message, flags=re.IGNORECASE) micoff = re.match("admin micoff (\S+)", message, flags=re.IGNORECASE) micon = re.match("admin micon (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("admin changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("admin help", message, flags=re.IGNORECASE) balance = re.match("admin balance", message, flags=re.IGNORECASE) getbalance = re.match("admin get balance", message, flags=re.IGNORECASE) reportbal = re.match("admin report balance", message, flags=re.IGNORECASE) swap = re.match("admin swap (\S+)", message, flags=re.IGNORECASE) setteam = re.match("admin setteam (\S+) (\S+)", message, flags=re.IGNORECASE) if restart: #restarts server if something catastrophically bad has happened kwargs['Broadcast'].broadcast("restart") if shuffle: #artificial shuffle vote if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot shuffle until the game has started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has shuffled the game." % (name)) self.listClients(**kwargs) shufflethread = threading.Thread(target=self.onShuffle, args=(clinum,None), kwargs=kwargs) shufflethread.start() if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\""\ % (kickclient['clinum'], reason)) if timeout: reason = "An administrator has banned you from the server. You are banned till this game is over." kickclient = self.getPlayerByName(timeout.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) self.banlist.append(kickclient['ip']) if ban: #kicks a player from the server and temporarily bans that player's IP till the game is over reason = "An administrator has banned you from the server." kickclient = self.getPlayerByName(ban.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(self.CONFIG) + "/ban.ini" banini.read (banconfig) banini.set ('ipban', kickclient['ip'], kickclient['name']) banini.write (open(banconfig, 'wb')) self.ipban.append(kickclient['ip']) if slap: #slap will move a player x+100, y+200 to get them off of a structure if self.PHASE != 5: return slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists"\ % (slapclient['clinum'], slapclient['clinum'])) if micoff: #Turns off players mic with clientdo offclient = self.getPlayerByName(micoff.group(1)) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"set voice_disabled true\"" % (offclient['clinum'])) if micon: #Turns on players mic with clientdo onclient = self.getPlayerByName(micon.group(1)) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"set voice_disabled false\"" % (onclient['clinum'])) if changeworld: #change the map kwargs['Broadcast'].broadcast(\ "changeworld %s"\ % (changeworld.group(1))) if balance: if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot balance if the game has not started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has balanced the game." % (name)) self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,True,False), kwargs=kwargs) balancethread.start() if getbalance: self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,False,False), kwargs=kwargs) balancethread.start() if reportbal: self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,False,True), kwargs=kwargs) balancethread.start() if swap: #swap a player to a different team swapplayer = self.getPlayerByName(swap.group(1)) newteam = 0 team = swapplayer['team'] if team == 1: newteam = 2 if team == 2: newteam = 1 if newteam == 0: return kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (swapplayer['clinum'], newteam)) if setteam: #swap a player to x team setplayer = self.getPlayerByName(setteam.group(2)) newteam = setteam.group(1) kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (setplayer['clinum'], newteam)) self.logCommand(client['name'],message) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. All commands are logged to prevent you from abusing them.The following are commands and a short description of what they do."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin restart ^whard reset of the server. ONLY use in weird cases."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin shuffle ^wwill shuffle the game and set to previous phase."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin kick playername ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin timeout playername ^wwill remove a player for one game."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin ban playername ^wwill remove a player from the server and ban that IP address permenantly."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin micoff playername ^wwill turn the players mic off. Use on mic spammers."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin micon playername ^wwill turn the players mic on."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin swap playername ^wwill move a specific player to another team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin balance ^wwill move two players to achieve balance."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin get balance ^wwill report avg. and median SF values for the teams as well as a stack value."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin report balance ^wwill send a message to ALL players that has the avg. and median SF values."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin setteam x playername ^wwill set players team to x."\ % (client['clinum'])) def superCommand(self, message, **kwargs): supercommand = re.match("sudo (.*)", str(message), flags=re.IGNORECASE) if supercommand: kwargs['Broadcast'].broadcast("%s" % (supercommand.group(1))) def doBalance(self, admin, doBalance=False, doReport=False, **kwargs): clinum = admin for each in self.playerlist: each['team'] = 0 time.sleep(1) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) startstack = abs(self.evaluateBalance(teamone, teamtwo)) if doReport: kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s.^y Stack value: ^r%s" \ % (teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'], 1), round(teamtwostats['median'],1), abs(stack))) return kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s. ^yStack value: ^r%s" \ % (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) #Find the players to swap lowest = -1 pick1 = None pick2 = None for player1 in teamone: if player1['commander']: continue for player2 in teamtwo: if player2['commander']: continue #sort of inefficient to send the teamlist each time ltarget = abs(self.evaluateBalance(teamone, teamtwo, player1, player2, True)) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 #If the stack isn't improved, abort it if (lowest >= startstack): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yUnproductive balance. No swapping scenario would improve the balance over its current state." % (admin)) return kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Balance will swap ^r%s ^yand ^r%s" \ % (clinum, pick1['name'], pick2['name'])) if not doBalance: index1 = map(itemgetter('clinum'), teamone).index(pick1['clinum']) index2 = map(itemgetter('clinum'), teamtwo).index(pick2['clinum']) teamone[index1]['team'] = 2 teamtwo[index2]['team'] = 1 teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) #kwargs['Broadcast'].broadcast(\ #"SendMessage %s ^cProposed change: ^y Team One (%s players) Avg. SF: ^r%s^y median SF: ^r%s^y, Team Two (%s players) Avg. SF: ^r%s^y median SF: ^r%s. ^yStack value: ^r%s" \ #% (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) return if doBalance: #Do the switch kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 2;\ set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 1"\ % (pick1['clinum'], pick2['clinum'])) #Give them gold if needed self.giveGold(True, pick1, **kwargs) self.giveGold(True, pick2, **kwargs) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^yAfter balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s"\ % (teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase kwargs['Broadcast'].broadcast("echo SERVERVAR: norunes is #norunes#") if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False each['value'] = 0 if (phase == 6): if self.UPDATE: #fetch admin list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() #check if server is empty after 2 minutes pluginthread = threading.Thread(target=self.pluginreload, args=(), kwargs=kwargs) pluginthread.start() self.RegisterScripts(**kwargs) self.ItemList() if (phase == 4): kwargs['Broadcast'].broadcast("listclients") def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/admin.ini') adminlist = response.read() f = open(self.CONFIG, 'w') f.write(adminlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() if self.NEEDRELOAD: self.pluginreload(**kwargs) return #Update the wrapper try: gitpath = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../.git") command = ["git","--git-dir",gitpath,"pull"] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate() result = output[0].split("\n")[0] print 'result is %s' % result #TODO: make sure these work on all servers? notneeded = re.match("Already up-to-date.", result) needed = re.match("Updating .*", result) except: print 'error getting git update' return if notneeded: print 'update not needed' self.NEEDRELOAD = False return if needed: print 'update needed' self.NEEDRELOAD = True self.pluginreload(**kwargs) return def pluginreload(self, **kwargs): print 'pluginreload called' #Wait a couple minutes to allow clients to connect time.sleep(120) #Figure out how many clients are present kwargs['Broadcast'].broadcast("serverstatus") def onServerStatusResponse(self, *args, **kwargs): if self.NEEDRELOAD: gamemap = args[0] active = int(args[2]) if active == 0: self.reload_plugins() kwargs['Broadcast'].broadcast("NextPhase; PrevPhase") self.NEEDRELOAD = False def logCommand(self, client, message, **kwargs): localtime = time.localtime(time.time()) date = ("%s-%s-%s, %s:%s:%s" % (localtime[1], localtime[2], localtime[0], localtime[3], localtime[4], localtime[5])) f = open('admin.log', 'a') f.write("Timestamp: \"%s\", Admin: %s, Command: %s\n" % (date, client, message)) f.close def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team self.requestTracker(cli, **kwargs) def onShuffle (self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 each['value'] = 0 clinum = args[0] time.sleep(2) shufflelist = [] #Put all the active players in a list for each in self.playerlist: if not each['active']: continue if each['team'] > 0: shufflelist.append(each) #sort shufflelists based on SF shufflelist = sorted(shufflelist, key=itemgetter('sf', 'level', 'clinum'), reverse=True) #randomly choose if we begin with human or beast r = random.randint(1,2) #Assign new teams, just like the K2 way, but Ino won't always be on humans for each in shufflelist: #TODO: is there a cleaner, more pythonic way to do this? each['team'] = r if r == 1: r += 1 elif r == 2: r -=1 #Now actually do the shuffling for each in shufflelist: kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (each['clinum'], each['team'])) #Finish it off by going forward a phase kwargs['Broadcast'].broadcast(\ "nextphase") kwargs['Broadcast'].broadcast(\ "SendMessage %s You have shuffled the game." % (clinum)) #Run balancer to get it nice and even #self.onBalance(clinum, **kwargs) kwargs['Broadcast'].broadcast("Startgame") def getTeamInfo(self, teamlist, **kwargs): teamsf = [] combteamsf = float(0) #figure out current averages and set some commonly used variables: for each in teamlist: combteamsf += each['sf'] teamsf.append(each['sf']) sizeteam = len(teamlist) avgteam = combteamsf/sizeteam med = median(teamsf) teaminfo = {'size' : sizeteam, 'avg' : avgteam, 'total' : combteamsf, 'median' : med} return teaminfo def evaluateBalance(self, team1, team2, pick1=None, pick2=None, swap=False, **kwargs): #This function will swap out the picked players in a temporary list if swap is true and report the stack percent #If swap is false, it will just report the balance #First, make new lists that we can modify: teamone = list(team1) teamtwo = list(team2) if swap: #Remove those players from the lists... for each in teamone: if each['clinum'] == pick1['clinum']: teamone.remove(each) for each in teamtwo: if each['clinum'] == pick2['clinum']: teamtwo.remove(each) #Add to the lists teamone.append(pick2) teamtwo.append(pick1) #Get the new team stats... teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #Evaluate team balance teamoneshare = teamonestats['total']/(teamonestats['total'] + teamtwostats['total']) diffmedone = teamonestats['median']/(teamonestats['median'] + teamtwostats['median']) stack = teamoneshare + diffmedone #positive if team one is stacked, negative if team two is stacked return (stack - 1) * 100 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) client['commander'] = False def onUnitChange(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) self.requestTracker(cli, **kwargs) if args[1] != "Player_Commander": return client['commander'] = True def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = int(args[0]) name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #usually used when reloading plugin during a game acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights' : 700, 'Ammo Pack' : 500, 'Ammo Satchel' : 200, 'Chainmail' : 300, 'Gust of Wind' : 450, 'Magic Amplifier' : 700, 'Brain of Maliken' : 750, 'Heart of Maliken' : 950, 'Lungs of Maliken' : 1000, 'Mana Crystal' : 500, 'Mana Stone' : 200, 'Platemail' : 650, 'Power Absorption' : 350, 'Shield of Wisdom' : 650, 'Stone Hide' : 650, 'Tough Skin' : 300, 'Trinket of Restoration' : 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) self.requestTracker(cli, **kwargs) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def giveGold(self, balance, client, **kwargs): if client['value'] == 0: return gold = round(client['value']/2, 0) if balance: gold = client['value'] kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou have been compensated %s gold for your lost items.; GiveGold %s %s"\ % (client['clinum'], gold, client['clinum'], gold)) client['value'] = 0 def getMatchID(self, *args, **kwargs): matchid = args[0] kwargs['Broadcast'].broadcast("Set Entity_NpcController_Description %s" % (matchid)) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] self.requestTracker(caller, **kwargs) if event == 'DLL': if value == 'NONE': return if value != self.DLL: banthread = threading.Thread(target=self.banclient, args=(caller, None), kwargs=kwargs) banthread.start() def banclient(self, *args, **kwargs): clinum = args[0] kwargs['Broadcast'].broadcast(\ "ClientExecScript %s clientdo cmd \"UICall game_options \\\"HTTPGetFile(\'http://masterserver.savage2.s2games.com/create.php?phrase=1\', \'~/null\');\\\"\"" % (clinum)) time.sleep(1) kwargs['Broadcast'].broadcast(\ "ClientExecScript %s clientdo cmd \"quit\"" % (clinum)) def getServerVar(self, *args, **kwargs): var = args[0] if var == 'norunes': self.norunes = args[1] def requestTracker (self, cli, **kwargs): tm = time.time() client = self.getPlayerByClientNum(cli) #If player requests item purchase, team join, unit select more than 12 times in 1 second, boot them if (tm - client['f_req']) > 1: client['req'] = 0 client['f_req'] = tm return client['req'] += 1 if client['req'] > 10: reason = "Spamming server requests results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (client['clinum'], reason))
class pug(ConsolePlugin): VERSION = "1.0.1" ms = None PHASE = 0 STARTSTAMP = 0 STARTED = False PICKING = False HUMANPICK = False playerlist = [] startinfo = { 'h_captain': None, 'h_ready': False, 'h_first': False, 'b_captain': None, 'b_ready': False, 'b_first': False } teamlist = [] TIME = 0 def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) ''' for (name, value) in ini.items('var'): if (name == "clan1"): self.CLAN1 = value if (name == "clan2"): self.CLAN2 = value ''' pass def onStartServer(self, *args, **kwargs): self.PHASE = 0 self.playerlist = [] self.startinfo = { 'h_captain': None, 'h_ready': False, 'h_first': False, 'b_captain': None, 'b_ready': False, 'b_first': False } def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'ip' : ip,\ 'sf' : 0,\ 'name' : 'X',\ 'active' : False,\ 'team' : 0,\ 'ping' : 0,\ 'clan' : 'X'}) #kwargs['Broadcast'].broadcast("SendMessage %s ^cTo toggle your PUG availability send the chat message ^rpug noplay" % (id)) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client['active'] = False if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast( "set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"; set Pet_HumanWorker_Inventory9 \"\";" ) if self.PICKING: resetall(**kwargs) if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast( "set Gadget_Hail_ModelPath \"trigger UpdateError 1\"; set Pet_BeastWorker_Inventory9 \"\";" ) if self.PICKING: resetall(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername client['play'] = True kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"showwidget pug_button\"" % (cli)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics(id).get('all_stats').get(int(id)) level = int(stats['level']) sf = int(stats['sf']) exp = int(stats['exp']) time = int(stats['secs']) time = time / 60 #sf = int(exp/time) clan = stats['clan_tag'] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) client['level'] = level client['sf'] = sf client['active'] = True client['clan'] = clan client['newteam'] = 0 kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"showwidget pug_button\"" % (cli)) if self.PICKING: kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"hidewidget team_button0; hidewidget team_button1\"" % (cli)) def onTeamChange(self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team if self.PICKING: for each in self.teamlist: if (each['player'] == cli) and (team != each['team']): #don't let them switch kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['player'], each['team'])) return #kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['player'])) def onGameStart(self, *args, **kwargs): self.STARTSTAMP = args[1] def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if phase == 5: self.STARTSTAMP = args[1] self.STARTED = True self.PICKING = False if phase == 6: self.PICKING = False self.teamlist = [] self.startinfo = { 'h_captain': None, 'h_ready': False, 'h_first': False, 'b_captain': None, 'b_ready': False, 'b_first': False } kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set sv_maxteamdifference 10;\ set Pet_Shaman_Prerequisite 1;\ set Pet_HumanWorker_Inventory9 \"\";\ set Pet_BeastWorker_Inventory9 \"\";") kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput" ) kwargs['Broadcast'].broadcast( "ClientExecScript -1 clientdo cmd \"showwidget team_button0; showwidget team_button1\"" ) if phase == 7: for each in self.playerlist: each['newteam'] = 0 self.PICKING = False self.STARTED = False resetall(**kwargs) def togglePlay(self, client, playing=None, **kwargs): color = '^g' if self.PICKING: kwargs['Broadcast'].broadcast( "SendMessage %s ^rYou cannot toggle your status once picking has begun." % (client['clinum'])) return if not playing: if client['play']: client['play'] = False color = '^r' else: client['play'] = True else: client['play'] = playing if not client['play']: color = '^r' #kwargs['Broadcast'].broadcast("SendMessage %s ^cYour Playing Status: %s%s" % (client['clinum'], color, client['play'])) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] #info = self.startinfo #Captain initiated if event == 'Captain': #If they are already captain, do nothing if caller == self.startinfo[ 'b_captain'] or caller == self.startinfo['h_captain']: return #Beasts, set captain if value == 'beasts': self.startinfo['b_captain'] = caller kwargs['Broadcast'].broadcast( "set Gadget_Hail_ModelPath \"trigger UpdateError 0\"; set Pet_BeastWorker_Inventory9 \"%s\"" % (client['name'])) if not self.startinfo['h_captain']: self.startinfo['h_first'] = True #Humans, set captain if value == 'humans': self.startinfo['h_captain'] = caller kwargs['Broadcast'].broadcast( "set State_Interrupted_EffectPath \"trigger UpdateDetail 0\"; set Pet_HumanWorker_Inventory9 \"%s\"" % (client['name'])) if not self.startinfo['b_captain']: self.startinfo['b_first'] = True #Check if picking is initiated, if so determine who gets the next picking if self.PICKING: self.setpicking(**kwargs) return #Start picking process through the normal mechanism if self.startinfo['h_captain'] and self.startinfo['b_captain']: self.beginpicking(**kwargs) #Toggle player availability if event == 'Toggle': playing = False if value == 'true': playing = True self.togglePlay(client, playing, **kwargs) #Player select if event == 'Select': player = self.getPlayerByName(value) #switch everything to ingame_picking function if the game is already started if self.PHASE == 5: #pickthread = threading.Thread(target=self.ingame_picking, args=(caller, client, player, None), kwargs=kwargs) #pickthread.start() #self.ingame_picking(caller, client, player, **kwargs) print 'Will go to ingame picking' if caller == self.startinfo['h_captain']: #check players status if not player['play']: kwargs['Broadcast'].broadcast( "SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 1 client['newteam'] = 1 self.teamlist.append({ "player": player["clinum"], "team": 1 }) kwargs['Broadcast'].broadcast( "SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Humans!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (player['clinum'])) kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain'])) self.HUMANPICK = False if caller == self.startinfo['b_captain']: if not player['play']: kwargs['Broadcast'].broadcast( "SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 2 client['newteam'] = 2 self.teamlist.append({ "player": player["clinum"], "team": 2 }) kwargs['Broadcast'].broadcast( "SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Beasts!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (player['clinum'])) kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'], self.startinfo['h_captain'])) self.HUMANPICK = True if self.PICKING: self.setpicking(**kwargs) #Ready if event == 'Ready': if self.STARTED: return if caller == self.startinfo['h_captain']: if self.startinfo['h_ready']: return self.startinfo['h_ready'] = True kwargs['Broadcast'].broadcast( "SendMessage -1 ^r%s^w has indicated that Humans are ready!" % (client['name'])) if caller == self.startinfo['b_captain']: if self.startinfo['b_ready']: return self.startinfo['b_ready'] = True kwargs['Broadcast'].broadcast( "SendMessage -1 ^r%s^w has indicated that Beasts are ready!" % (client['name'])) #Start the game if both captains say they are ready if self.startinfo['h_ready'] and self.startinfo['b_ready']: kwargs['Broadcast'].broadcast( "set State_ImpPoisoned_Name \"trigger UpdateSpeed 0\"") self.populate(**kwargs) if event == 'Resign': #if pick has begun and a captain resigns, just reset the whole damn thing if self.PICKING: self.resetall(**kwargs) if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast( "set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"; set Pet_HumanWorker_Inventory9 \"\";" ) if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast( "set Gadget_Hail_ModelPath \"trigger UpdateError 1\"; set Pet_BeastWorker_Inventory9 \"\";" ) #self.setpicking(**kwargs) def resetall(self, **kwargs): self.PICKING = False self.teamlist = [] self.startinfo = { 'h_captain': None, 'h_ready': False, 'h_first': False, 'b_captain': None, 'b_ready': False, 'b_first': False } kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set sv_maxteamdifference 10;\ set Pet_Shaman_Prerequisite 1;\ set Pet_HumanWorker_Inventory9 \"\";\ set Pet_BeastWorker_Inventory9 \"\";") kwargs['Broadcast'].broadcast( "ClientExecScript -1 clientdo cmd \"showwidget team_button0; showwidget team_button1\"" ) for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0; SendMessage -1 ^yTeams are reset after captain resignation." % (each['clinum'])) def RegisterStart(self, **kwargs): self.PICKING = True def beginpicking(self, **kwargs): #move everyone to spec for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['clinum'])) self.teamlist = [] #start by making the teams unjoinable kwargs['Broadcast'].broadcast( "set sv_setupTimeCommander 600000000; set sv_maxteamdifference 1; set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 0\";" ) kwargs['Broadcast'].broadcast( "ClientExecScript -1 clientdo cmd \"hidewidget team_button0; hidewidget team_button1\"" ) #move captains to the appropriate team and have them switch back to lobby for each in self.playerlist: if each['clinum'] == self.startinfo['h_captain']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (each['clinum'])) if each['clinum'] == self.startinfo['b_captain']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (each['clinum'])) kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"Action ToggleLobby\"" % (self.startinfo['h_captain'])) kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"Action ToggleLobby\"" % (self.startinfo['b_captain'])) self.teamlist.append({ "player": self.startinfo['h_captain'], "team": 1 }) self.teamlist.append({ "player": self.startinfo['b_captain'], "team": 2 }) #Set variables to get the first captain to start picking if self.startinfo['h_first']: self.HUMANPICK = True self.setpicking(**kwargs) else: self.HUMANPICK = False self.setpicking(**kwargs) kwargs['Broadcast'].broadcast("echo STARTTOURNEY") def populate(self, **kwargs): for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['clinum'], each['newteam'])) #Send to the next phase kwargs['Broadcast'].broadcast( "NextPhase; set sv_setupTimeCommander 60000; PrevPhase") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] try: client = self.getPlayerByName(name) except: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) def onServerStatus(self, *args, **kwargs): if self.STARTED != 1: return pickthread = threading.Thread(target=self.ingame_picking, args=(), kwargs=kwargs) pickthread.start() def ingame_picking(self, *args, **kwargs): self.listClients(self, **kwargs) teamone = [] teamtwo = [] time.sleep(1) #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) #figure out who gets the pick team1 = len(teamone) team2 = len(teamtwo) if team1 > team2: self.HUMANPICK = False self.setpicking(**kwargs) if team2 > team1: self.HUMANPICK = True self.setpicking(**kwargs) if team1 == team2: return def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #TODO: listclients clinum is always double diget (00, 01, etc.) so this might be a problem acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def setpicking(self, **kwargs): if self.HUMANPICK: kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'], self.startinfo['h_captain'])) else: kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain']))
class sandbox(ConsolePlugin): VERSION = "0.2.5" playerlist = [] leaderlist = [] modlist = [] PHASE = 0 def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('modders'): self.leaderlist.append({'name': name, 'level' : value}) pass def reload_config(self): self.leaderlist = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('modders'): self.leaderlist.append({'name': name, 'level' : value}) def reload_plugins(self): config = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../s2wrapper.ini") ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'sandbox': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): self.playerlist = [] self.modlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'active' : False,\ 'level' : 0,\ 'leader' : False,}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername kwargs['Broadcast'].broadcast("SendMessage %s ^yThis server is running the Sandbox plugin by GGGGGGGG. Version : %s. Mods currently active: ^r%" % (cli, self.VERSION, self.modlist)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) client = self.getPlayerByClientNum(cli) client['level'] = level client['active'] = True if self.isLeader(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as a modder. You can now use the sandbox. Send the chat message: ^rsb help ^cto see what commands you can perform."\ % (cli)) client['leader'] = True def isLeader(self, client, **kwargs): leader = False for each in self.leaderlist: if client['name'].lower() == each['name']: leader = True return leader def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) leader = self.isLeader(client, **kwargs) if not leader: return startgame = re.match("sb startgame", message, flags=re.IGNORECASE) giveteamgold = re.match("sb giveteamgold (\S+) (\S+)", message, flags=re.IGNORECASE) giveplayergold = re.match("sb givegold (\S+) (\S+)", message, flags=re.IGNORECASE) giveplayersoul = re.match("sb givesoul (\S+) (\S+)", message, flags=re.IGNORECASE) giveplayerexperience = re.match("sb giveexp (\S+) (\S+)", message, flags=re.IGNORECASE) giveplayerammo = re.match("sb giveammo (\S+)", message, flags=re.IGNORECASE) resetattributes = re.match("sb resetattributes (\S+)", message, flags=re.IGNORECASE) resetexp = re.match("sb resetexp (\S+)", message, flags=re.IGNORECASE) refillhealth = re.match("sb refillhealth (\S+)", message, flags=re.IGNORECASE) refillmana = re.match("sb refillmana (\S+)", message, flags=re.IGNORECASE) refillstamina = re.match("sb refillstamina (\S+)", message, flags=re.IGNORECASE) kick = re.match("sb kick (\S+)", message, flags=re.IGNORECASE) slap = re.match("sb slap (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("sb changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("sb help", message, flags=re.IGNORECASE) playerhelp = re.match("sb player help", message, flags=re.IGNORECASE) teamchange = re.match("sb allowteamchange", message, flags=re.IGNORECASE) teamdifference = re.match("sb teamdiff", message, flags=re.IGNORECASE) changepassword = re.match("sb password (\S+)", message, flags=re.IGNORECASE) setteam = re.match("sb setteam (\S+) (\S+)", message, flags=re.IGNORECASE) sbsudo = re.match("sb sudo (.*)", message, flags=re.IGNORECASE) modhelp = re.match("sb mod help", message, flags=re.IGNORECASE) movespeed = re.match("sb mod speed (\S+)", message, flags=re.IGNORECASE) gravity = re.match("sb mod gravity (\S+)", message, flags=re.IGNORECASE) buildspeed = re.match("sb mod buildspeed (\S+)", message, flags=re.IGNORECASE) jump = re.match("sb mod jump (\S+)", message, flags=re.IGNORECASE) modenable = re.match("mm enable (\S+)", message, flags=re.IGNORECASE) modactive = re.match("mm get active", message, flags=re.IGNORECASE) modindirectory = re.match("mm get list", message, flags=re.IGNORECASE) modreset = re.match("mm reset", message, flags=re.IGNORECASE) mmhelp = re.match("mm help", message, flags=re.IGNORECASE) mmcreate = re.match("mm create (\S+)", message, flags=re.IGNORECASE) mmdelete = re.match("mm delete (\S+)", message, flags=re.IGNORECASE) mmmodify = re.match("mm modify (\S+) (\S+) (.*)", message, flags=re.IGNORECASE) mmview = re.match("mm view (\S+)", message, flags=re.IGNORECASE) mmwrite = re.match("mm write (\S+) (.*)") if startgame: kwargs['Broadcast'].broadcast("startgame") if sbsudo: kwargs['Broadcast'].broadcast("%s" % (sbsudo.group(1))) if giveteamgold: kwargs['Broadcast'].broadcast("giveteamgold %s %s" % (giveteamgold.group(1), giveteamgold.group(2))) if giveplayergold: playergold = self.getPlayerByName(giveplayergold.group(1)) kwargs['Broadcast'].broadcast("givegold %s %s" % (playergold['clinum'], giveplayergold.group(2))) if giveplayerammo: playerammo = self.getPlayerByName(giveplayerammo.group(1)) kwargs['Broadcast'].broadcast("giveammo %s" % (playerammo['clinum'])) if giveplayersoul: playersoul = self.getPlayerByName(giveplayersoul.group(1)) kwargs['Broadcast'].broadcast("givesoul %s %s" % (playersoul['clinum'], giveplayersoul.group(2))) if giveplayerexperience: playerexperience = self.getPlayerByName(giveplayerexperience.group(1)) kwargs['Broadcast'].broadcast("giveexp %s %s" % (playerexperience['clinum'], giveplayerexperience.group(2))) if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast("Kick %s \"%s\""% (kickclient['clinum'], reason)) if slap: #slap will move a player x+100, y+200 to get them off of a structure slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists"\ % (slapclient['clinum'], slapclient['clinum'])) if changeworld: kwargs['Broadcast'].broadcast("changeworld %s" % (changeworld.group(1))) if movespeed: kwargs['Broadcast'].broadcast("set p_speed %s" % (movespeed.group(1))) if jump: kwargs['Broadcast'].broadcast("set p_jump %s" % (jump.group(1))) if gravity: kwargs['Broadcast'].broadcast("set p_gravity %s" % (gravity.group(1))) if buildspeed: kwargs['Broadcast'].broadcast(\ "set Player_Conjurer_BuildingRepairRate %s;\ set Player_Engineer_BuildingRepairRate %s;"\ % (buildspeed.group(1), buildspeed.group(1))) if teamchange: kwargs['Broadcast'].broadcast("set g_allowteamchange true") if teamdifference: kwargs['Broadcast'].broadcast("set sv_maxTeamDifference 20") if changepassword: kwargs['Broadcast'].broadcast("set svr_connectpass %s" % (changepassword.group(1))) if setteam: #swap a player to a different team setplayer = self.getPlayerByName(setteam.group(2)) newteam = setteam.group(1) kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (setplayer['clinum'], newteam)) if resetattributes: resetattributesplayer = self.getPlayerByName(resetattributes.group(1)) kwargs['Broadcast'].broadcast("ResetAttributes #GetIndexFromClientNum(%s)#" % (resetattributesplayer['clinum'])) if resetexp: resetexpplayer = self.getPlayerByName(resetexp.group(1)) kwargs['Broadcast'].broadcast("ResetExp %s" % (resetexpplayer['clinum'])) if refillhealth: refillhealthplayer = self.getPlayerByName(refillhealth.group(1)) kwargs['Broadcast'].broadcast("RefillHealth #GetIndexFromClientNum(%s)#" % (refillhealthplayer['clinum'])) if refillmana: refillmanaplayer = self.getPlayerByName(refillmana.group(1)) kwargs['Broadcast'].broadcast("RefillMana #GetIndexFromClientNum(%s)#" % (refillmanaplayer['clinum'])) if refillstamina: refillstaminaplayer = self.getPlayerByName(refillstamina.group(1)) kwargs['Broadcast'].broadcast("RefillStamina #GetIndexFromClientNum(%s)#" % (refillstaminaplayer['clinum'])) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb mod help ^w for more info about the sb mod commands."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb player help ^w for more info about command's that affect players."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb startgame ^w will start the game"\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb giveteamgold team amount^w. will give gold to a team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb sudo args ^wdo whatever commands you want."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb allowteamchange ^wwill allow switching team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb teamdiff ^wwill allow everyone to join in the same team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb changepassword ^wwill change the server's password."\ % (client['clinum'])) if modhelp: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb buildspeed amount ^wwill change the build speed."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb mod gravity amount ^wwill change the gravity."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb mod jump amount ^wwill change the jump height."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb mod speed amount ^wwill change the movement speed of the server."\ % (client['clinum'])) if playerhelp: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb setteam playername ^wwill move a specific player to another team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb givegold player amount ^wwill give gold to a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb givesoul player amount ^wwill give souls to a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb giveexp player amount ^wwill give experience to a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb resetexp player ^wwill reset exp of a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb resetattributes ^wwill reset all attributes of a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb refillhealth ^wwill refill a player health."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb refillmana ^wwill refill a player mana."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb refillstamina ^wwill refill a player stamina."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb giveammo player ^wwill give ammo to a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb kick ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb slap playername ^wwill move the player. Use to get them off of structures if they are exploiting."\ % (client['clinum'])) if mmhelp: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm enable modname ^wwill enable a mod."\ % (client['clinum'])) #modenable kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm get active ^wwill show all active mods."\ % (client['clinum'])) #modactive kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm get list ^wwill show all the possible mods."\ % (client['clinum'])) #modindirectory kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm reset ^wwill reset everything to its default settings."\ % (client['clinum'])) #modreset kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm create name ^wwill create a new mod with the specified name."\ % (client['clinum'])) #mmcreate kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm delete name^wwill delete a mod with the specified name."\ % (client['clinum'])) #mmdelete kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm modify name linenumber arg^wwill edit a mod by replacing a line with its arg."\ % (client['clinum'])) #mmmodify kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm view name ^wwill view what a mod contain with the specified name."\ % (client['clinum'])) #mmview kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm write name arg ^wwill write a line in a mod file."\ % (client['clinum'])) #mmwrite if modenable: #Enable a specific mod modName = "./mods/" + modenable.group(1) if os.path.isfile(modName): #Check if it exists with open(modName, 'r') as modfile: for line in modfile: kwargs['Broadcast'].broadcast("%s" % (line)) self.modlist.append(modenable.group(1)) kwargs['Broadcast'].broadcast("SendMessage -1 %s has been enabled." % (modenable.group(1))) else: kwargs['Broadcast'].broadcast("SendMessage -1 %s does not exist." % (modenable.group(1))) if modactive: #Shows the active mods currently on the server kwargs['Broadcast'].broadcast("SendMessage %s mods currently active on this server:" % (client['clinum'])) if len(self.modlist) == 0: kwargs['Broadcast'].broadcast("SendMessage %s None" % (client['clinum'])) else: for element in self.modlist: kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], element)) if modreset: #Reset all the mods to its original state self.modlist = [] with open("./mods/original", 'r') as original: for line in original: kwargs['Broadcast'].broadcast("%s" % (line)) kwargs['Broadcast'].broadcast("SendMessage -1 All mods have been reseted.") if modindirectory: #Used to check what mods are in the directory modindir = os.listdir("./mods/") for each in modindir: kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], each)) if mmcreate: #Used to create a mod modName = mmcreate.group(1) with open(modName, 'w') as newmodfile: newmodfile.write("//%s", newmodfile) kwargs['Broadcast'].broadcast("SendMessage %s %s has been created succesfully" % (client['clinum'], newmodfile)) if mmview: #Used to view a mod with open("./mods/" + mmview.group(1), 'r') as modFile: for line in modFile: numberLine = 0 kwargs['Broadcast'].broadcast("SendMessage %s %s %s" % (client['clinum'], numberLine, line)) numberLine += 1 if mmdelete: #Used to delete a mod os.remove("./mods/" + mmdelete.group(1)) kwargs['Broadcast'].broadcast("SendMessage %s %s has been deleted with success" % (client['clinum'], mmdelete.group(1))) if mmwrite: #Used to write a line in a mod with open("./mods/" + mmwrite.group(1), 'a+') as modFile: modFile.write(mmwrite.group(2)) kwargs['Broadcast'].broadcast("SendMessage %s %s has been added to %s successfully" % (client['clinum'], mmwrite.group(2), mmwrite.group(1))) if mmmodify: #modify a specific line with open("./mods/" + mmmodify.group(1), 'r') as modFile: data = modFile.readlines() data[mmmodify.group(2)] = mmmodifiy.group(3) with open("./mods" + mmmodify.group(1), 'w') as modFile: modFile.writelines(data) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] self.modlist = [] with open("./mods/original", 'r') as original: for line in original: kwargs['Broadcast'].broadcast("%s" % (line)) for each in self.playerlist: each['team'] = 0 each['commander'] = False if (phase == 6): #fetch leader list and reload at the start of each game try: response = urllib2.urlopen('http://cedeqien.com/modders.ini') leaderlist = response.read() leaderfile = os.path.join(os.path.dirname(self.CONFIG),'modders.ini') with open(leaderfile, 'w') as f: f.write(leaderlist) #reload the config file self.onPluginLoad(leaderfile) except: return def onListClients(self, *args, **kwargs): clinum = int(args[0]) name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #usually used when reloading plugin during a game acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum']))