-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The chat for each battle now takes place in a channel. Channels use for this purpose have names prefixed by __battle__ When a client joins/leaves a battle, he is auto-joined/left to this channel. (-> such channels can register with ChanServ and set a founder, topic, operators, mutes, bans, etc.) To speak in a battle, use SAY/SAYEX/SAYFROM into its channel. -- Changes to protocol -- - JOINBATTLE (server) has an extra arg, containing the name of the channel associated to the battle - removed SAYBATTLEPRIVATE SAYBATTLEPRIVATEEX - deprecated SAYBATTLE SAYBATTLEEX (-> use SAY/SAYEX) - added !registerbattle and !mute/!unmute to ChanServ - deprecated SETCHANNELKEY and ChanServ !lock/!unlock (-> use !setkey) - fix #283: LEFT is reflected back to the user who leaves a channel Clients should send the 'u' compatibility flag to signal that they are prepared for the above. Full backwards compatibility exists for clients lacking 'u'.
- Loading branch information
1 parent
05f7acb
commit a1c0e85
Showing
6 changed files
with
443 additions
and
436 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,141 @@ | ||
from Channel import Channel | ||
|
||
class Battle(): | ||
def __init__(self, root, id, type, natType, password, port, maxplayers, | ||
hashcode, rank, maphash, map, title, modname, | ||
passworded, host, users): | ||
class Battle(Channel): | ||
def __init__(self, root, name): | ||
|
||
Channel.__init__(self, root, name) | ||
self.identity = 'battle' | ||
|
||
# battle | ||
self.battle_id = None #FIXME: it would be great to remove this and use battle.name to identify battles, but it causes a big change to protocol -> wait for #58 | ||
self.host = None | ||
self.type = '' | ||
self.natType = '' | ||
self.port = 0 | ||
|
||
self._root = root | ||
self.id = id #name | ||
self.passworded = passworded #key | ||
self.password = password #key | ||
self.users = users #users (set) # list with all session_ids of joined users | ||
self.host = host #founder # client.session_id | ||
self.mutelist = {} #mutelist | ||
|
||
self.title = title | ||
self.title = '' | ||
self.map = '' | ||
self.maphash = None | ||
self.modname = '' | ||
self.hashcode = None | ||
self.engine = '' | ||
self.version = '' | ||
self.modname = modname | ||
self.map = map | ||
self.maxplayers = maxplayers | ||
|
||
self.hashcode = hashcode | ||
self.maphash = maphash | ||
|
||
self.type = type | ||
self.rank = 0 | ||
self.maxplayers = 0 | ||
self.spectators = 0 # duplicated info? | ||
self.locked = False | ||
self.rank = rank | ||
|
||
self.pending_users = set() | ||
|
||
self.bots = {} | ||
self.script_tags = {} | ||
self.startrects = {} | ||
self.disabled_units = [] | ||
self.port = port | ||
self.natType = natType | ||
|
||
self.replay_script = {} | ||
self.replay_script = {} #FIXME: inaccessible via protocol | ||
self.replay = False | ||
self.sending_replay_script = False | ||
|
||
self.pending_users = set() #users who requested to join, but haven't heard back from the host yet | ||
self.spectators = 0 # duplicated info? | ||
|
||
def joinBattle(self, client): | ||
# client joins battle + notifies others | ||
if client.compat['u']: | ||
client.Send('JOINBATTLE %s %s %s' % (self.battle_id, self.hashcode, self.name)) | ||
self.addUser(client) # join the battles channel | ||
else: | ||
client.Send('JOINBATTLE %s %s' % (self.battle_id, self.hashcode)) | ||
self.users.add(client.session_id) | ||
|
||
scriptPassword = client.scriptPassword | ||
host = self._root.protocol.clientFromSession(self.host) | ||
if scriptPassword and host.compat['sp']: | ||
host.Send('JOINEDBATTLE %s %s %s' % (self.battle_id, client.username, scriptPassword)) | ||
if client!=host: | ||
client.Send('JOINEDBATTLE %s %s %s' % (self.battle_id, client.username, scriptPassword)) | ||
else: | ||
host.Send('JOINEDBATTLE %s %s' % (self.battle_id, client.username)) | ||
if client!=host: | ||
client.Send('JOINEDBATTLE %s %s' % (self.battle_id, client.username)) | ||
|
||
scripttags = [] | ||
for tag, val in self.script_tags.items(): | ||
scripttags.append('%s=%s'%(tag, val)) | ||
client.Send('SETSCRIPTTAGS %s'%'\t'.join(scripttags)) | ||
if self.disabled_units: | ||
client.Send('DISABLEUNITS %s' % ' '.join(self.disabled_units)) | ||
self._root.broadcast('JOINEDBATTLE %s %s' % (self.battle_id, client.username), ignore=set([self.host, client.session_id])) | ||
|
||
if self.natType > 0: | ||
if battle.host == client.session_id: | ||
raise NameError('%s is having an identity crisis' % (client.name)) | ||
if client.udpport: | ||
self._root.usernames[host].Send('CLIENTIPPORT %s %s %s' % (username, client.ip_address, client.udpport)) | ||
|
||
specs = 0 | ||
for sessionid in self.users: | ||
battle_client = self._root.protocol.clientFromSession(sessionid) | ||
if battle_client and battle_client.battlestatus['mode'] == '0': | ||
specs += 1 | ||
battlestatus = self.calc_battlestatus(battle_client) | ||
client.Send('CLIENTBATTLESTATUS %s %s %s' % (battle_client.username, battlestatus, battle_client.teamcolor)) | ||
|
||
for iter in self.bots: | ||
bot = self.bots[iter] | ||
client.Send('ADDBOT %s %s' % (self.battle_id, iter)+' %(owner)s %(battlestatus)s %(teamcolor)s %(AIDLL)s' % (bot)) | ||
|
||
for allyno in self.startrects: | ||
rect = self.startrects[allyno] | ||
client.Send('ADDSTARTRECT %s' % (allyno)+' %(left)s %(top)s %(right)s %(bottom)s' % (rect)) | ||
|
||
client.battlestatus = {'ready':'0', 'id':'0000', 'ally':'0000', 'mode':'0', 'sync':'00', 'side':'00', 'handicap':'0000000'} | ||
client.teamcolor = '0' | ||
client.current_battle = self.battle_id | ||
client.Send('REQUESTBATTLESTATUS') | ||
|
||
def leaveBattle(self, client): | ||
self.removeUser(client) | ||
|
||
client.scriptPassword = None | ||
client.current_battle = None | ||
client.hostport = None | ||
|
||
for bot in list(client.battle_bots): | ||
del client.battle_bots[bot] | ||
if bot in self.bots: | ||
del self.bots[bot] | ||
self._root.broadcast_battle('REMOVEBOT %s %s' % (self.battle_id, bot), battle.id) | ||
self._root.broadcast('LEFTBATTLE %s %s'%(self.battle_id, client.username)) | ||
if client.session_id == self.host: | ||
return | ||
|
||
oldspecs = self.spectators | ||
specs = 0 | ||
for session_id in self.users: | ||
user = self._root.protocol.clientFromSession(session_id) | ||
if user and user.battlestatus['mode'] == '0': | ||
specs += 1 | ||
self.spectators = specs | ||
if oldspecs != specs: | ||
self._root.broadcast('UPDATEBATTLEINFO %s %i %i %s %s' % (self.battle_id, self.spectators, self.locked, self.maphash, self.map)) | ||
|
||
def calc_battlestatus(self, client): | ||
battlestatus = client.battlestatus | ||
status = self._root.protocol._bin2dec('0000%s%s0000%s%s%s%s%s0'%(battlestatus['side'], | ||
battlestatus['sync'], battlestatus['handicap'], | ||
battlestatus['mode'], battlestatus['ally'], | ||
battlestatus['id'], battlestatus['ready'])) | ||
return status | ||
|
||
def hasBotflag(self): | ||
host = self._root.protocol.clientFromSession(self.host) | ||
return host.bot | ||
|
||
def canChangeSettings(self, client): | ||
return client.session_id == self.host | ||
|
||
def setKey(): | ||
return #todo: currently there is no way to inform clients when a new channel/battle key is set/unset | ||
def passworded(self): | ||
return 0 if self.key in ('*', None) else 1 | ||
|
Oops, something went wrong.