.BANCHO. Implemented packet streams for multiplayer

This commit is contained in:
Nyo 2016-10-04 23:43:02 +02:00
parent afbd8e7e8c
commit 795b6f09be
12 changed files with 187 additions and 287 deletions

View File

@ -111,7 +111,7 @@ def handle(userToken, packetData):
match.matchModMode = matchModModes.normal
# Send updated settings
match.sendUpdate()
match.sendUpdates()
# Console output
log.info("MPROOM{}: Updated room settings".format(match.matchID))

View File

@ -2,7 +2,6 @@ from common.log import logUtils as log
from constants import clientPackets
from constants import exceptions
from constants import serverPackets
from events import joinMatchEvent
from objects import glob
@ -26,7 +25,7 @@ def handle(userToken, packetData):
match = glob.matches.matches[matchID]
# Join that match
joinMatchEvent.joinMatch(userToken, matchID, packetData["matchPassword"])
userToken.joinMatch(matchID)
# Give host to match creator
match.setHost(userID)

View File

@ -3,38 +3,26 @@ from common.log import logUtils as log
from constants import clientPackets
from constants import exceptions
from constants import serverPackets
from helpers import chatHelper as chat
from objects import glob
def handle(userToken, packetData):
# read packet data
packetData = clientPackets.joinMatch(packetData)
matchID = packetData["matchID"]
password = packetData["password"]
# Get match from ID
joinMatch(userToken, packetData["matchID"], packetData["password"])
def joinMatch(userToken, matchID, password, isPasswordHashed = False):
try:
# Stop spectating
userToken.stopSpectating()
# Leave other matches
if userToken.matchID > -1 and userToken.matchID != matchID:
userToken.partMatch()
# Get usertoken data
userID = userToken.userID
# Make sure the match exists
if matchID not in glob.matches.matches:
raise exceptions.matchNotFoundException
return
# Match exists, get object
match = glob.matches.matches[matchID]
# Hash password if needed
if isPasswordHashed == False and password != "":
if password != "":
password = generalUtils.stringMd5(password)
# Check password
@ -44,24 +32,7 @@ def joinMatch(userToken, matchID, password, isPasswordHashed = False):
raise exceptions.matchWrongPasswordException
# Password is correct, join match
result = match.userJoin(userID)
# Check if we've joined the match successfully
if not result:
raise exceptions.matchJoinErrorException
# Match joined, set matchID for usertoken
userToken.joinMatch(matchID)
# Send packets
userToken.enqueue(serverPackets.matchJoinSuccess(matchID))
chat.joinChannel(token=userToken, channel="#multi_{}".format(matchID))
except exceptions.matchNotFoundException:
userToken.enqueue(serverPackets.matchJoinFail())
log.warning("{} has tried to join a mp room, but it doesn't exist".format(userToken.username))
except exceptions.matchWrongPasswordException:
userToken.enqueue(serverPackets.matchJoinFail())
log.warning("{} has tried to join a mp room, but he typed the wrong password".format(userToken.username))
except exceptions.matchJoinErrorException:
userToken.enqueue(serverPackets.matchJoinFail())
log.warning("{} has tried to join a mp room, but an error has occured".format(userToken.username))
log.warning("{} has tried to join a mp room, but he typed the wrong password".format(userToken.username))

View File

@ -21,7 +21,7 @@ def handle(userToken, _=None):
userToken.stopSpectating()
# Part matches
userToken.partMatch()
userToken.leaveMatch()
# Part all joined channels
for i in userToken.joinedChannels:

View File

@ -24,8 +24,4 @@ def handle(userToken, packetData):
slotID = match.getUserSlotID(userID)
# Enqueue frames to who's playing
for i in range(0,16):
if match.slots[i].userID > -1 and match.slots[i].status == slotStatuses.playing:
token = glob.tokens.getTokenFromUserID(match.slots[i].userID)
if token is not None:
token.enqueue(serverPackets.matchFrames(slotID, packetData))
glob.streams.broadcast(match.playingStreamName, serverPackets.matchFrames(slotID, packetData))

View File

@ -22,27 +22,4 @@ def handle(userToken, _):
if userToken.userID != match.hostUserID:
return
# Make sure we have enough players
if match.countUsers() < 2 or match.checkTeams() == False:
return
# Change inProgress value
match.inProgress = True
# Set playing to ready players and set load, skip and complete to False
for i in range(0,16):
if (match.slots[i].status & slotStatuses.ready) > 0:
match.slots[i].status = slotStatuses.playing
match.slots[i].loaded = False
match.slots[i].skip = False
match.slots[i].complete = False
# Send match start packet
for i in range(0,16):
if (match.slots[i].status & slotStatuses.playing) > 0 and match.slots[i].userID != -1:
token = glob.tokens.getTokenFromUserID(match.slots[i].userID)
if token is not None:
token.enqueue(serverPackets.matchStart(matchID))
# Send updates
match.sendUpdate()
match.start()

View File

@ -1,2 +1,2 @@
def handle(userToken, _=None):
userToken.partMatch()
userToken.leaveMatch()

View File

@ -1,5 +1,5 @@
# TODO: Enqueue all
import copy
import dill
from common import generalUtils
from common.constants import gameModes
@ -20,6 +20,7 @@ class slot:
self.status = slotStatuses.free
self.team = 0
self.userID = -1
self.user = None
self.mods = 0
self.loaded = False
self.skip = False
@ -27,22 +28,6 @@ class slot:
class match:
"""Multiplayer match object"""
matchID = 0
inProgress = False
mods = 0
matchName = ""
matchPassword = ""
beatmapName = ""
beatmapID = 0
beatmapMD5 = ""
slots = []
hostUserID = 0
gameMode = gameModes.STD
matchScoringType = matchScoringTypes.score
matchTeamType = matchTeamTypes.headToHead
matchModMode = matchModModes.normal
seed = 0
def __init__(self, matchID, matchName, matchPassword, beatmapID, beatmapName, beatmapMD5, gameMode, hostUserID):
"""
Create a new match object
@ -57,6 +42,8 @@ class match:
hostUserID -- user id of the host
"""
self.matchID = matchID
self.streamName = "multi/{}".format(self.matchID)
self.playingStreamName = "{}/playing".format(self.streamName)
self.inProgress = False
self.mods = 0
self.matchName = matchName
@ -69,7 +56,7 @@ class match:
self.beatmapMD5 = beatmapMD5
self.hostUserID = hostUserID
self.gameMode = gameMode
self.matchScoringTypes = matchScoringTypes.score # default values
self.matchScoringType = matchScoringTypes.score # default values
self.matchTeamType = matchTeamTypes.headToHead # default value
self.matchModMode = matchModModes.normal # default value
self.seed = 0
@ -79,6 +66,10 @@ class match:
for _ in range(0,16):
self.slots.append(slot())
# Create streams
glob.streams.add(self.streamName)
glob.streams.add(self.playingStreamName)
# Create #multiplayer channel
glob.channels.addTempChannel("#multi_{}".format(self.matchID))
@ -109,9 +100,8 @@ class match:
# Slot user ID. Write only if slot is occupied
for i in range(0,16):
uid = self.slots[i].userID
if uid > -1:
struct.append([uid, dataTypes.UINT32])
if self.slots[i].user is not None:
struct.append([self.slots[i].user.userID, dataTypes.UINT32])
# Other match data
struct.extend([
@ -138,50 +128,37 @@ class match:
newHost -- new host userID
"""
slotID = self.getUserSlotID(newHost)
if slotID is None:
return
token = self.slots[slotID].user
self.hostUserID = newHost
token.enqueue(serverPackets.matchTransferHost())
self.sendUpdates()
log.info("MPROOM{}: {} is now the host".format(self.matchID, token.username))
# Send host packet to new host
token = glob.tokens.getTokenFromUserID(newHost)
if token is not None:
token.enqueue(serverPackets.matchTransferHost())
def setSlot(self, slotID, status = None, team = None, user = -1, mods = None, loaded = None, skip = None, complete = None):
#self.setSlot(i, slotStatuses.notReady, 0, user, 0)
if status is not None:
self.slots[slotID].status = status
log.info("MPROOM{}: {} is now the host".format(self.matchID, newHost))
if team is not None:
self.slots[slotID].team = team
def setSlot(self, slotID, slotStatus = None, slotTeam = None, slotUserID = None, slotMods = None, slotLoaded = None, slotSkip = None, slotComplete = None):
"""
Set a slot to a specific userID and status
if user is not -1:
self.slots[slotID].user = user
slotID -- id of that slot (0-15)
slotStatus -- see slotStatuses.py
slotTeam -- team id
slotUserID -- user ID of user in that slot
slotMods -- mods enabled in that slot. 0 if not free mod.
slotLoaded -- loaded status True/False
slotSkip -- skip status True/False
slotComplete -- completed status True/False
if mods is not -1:
self.slots[slotID].mods = mods
If Null is passed, that value won't be edited
"""
if slotStatus is not None:
self.slots[slotID].status = slotStatus
if loaded is not None:
self.slots[slotID].loaded = loaded
if slotTeam is not None:
self.slots[slotID].team = slotTeam
if skip is not None:
self.slots[slotID].skip = skip
if slotUserID is not None:
self.slots[slotID].userID = slotUserID
if slotMods is not None:
self.slots[slotID].mods = slotMods
if slotLoaded is not None:
self.slots[slotID].loaded = slotLoaded
if slotSkip is not None:
self.slots[slotID].skip = slotSkip
if slotComplete is not None:
self.slots[slotID].complete = slotComplete
if complete is not None:
self.slots[slotID].complete = complete
def setSlotMods(self, slotID, mods):
"""
@ -191,8 +168,8 @@ class match:
mods -- new mods
"""
# Set new slot data and send update
self.setSlot(slotID, None, None, None, mods)
self.sendUpdate()
self.setSlot(slotID, mods=mods)
self.sendUpdates()
log.info("MPROOM{}: Slot{} mods changed to {}".format(self.matchID, slotID, mods))
def toggleSlotReady(self, slotID):
@ -208,8 +185,8 @@ class match:
newStatus = slotStatuses.notReady
else:
newStatus = slotStatuses.ready
self.setSlot(slotID, newStatus, None, None, None)
self.sendUpdate()
self.setSlot(slotID, newStatus)
self.sendUpdates()
log.info("MPROOM{}: Slot{} changed ready status to {}".format(self.matchID, slotID, self.slots[slotID].status))
def toggleSlotLock(self, slotID):
@ -219,26 +196,21 @@ class match:
slotID -- slot number
"""
# Get token of user in that slot (if there's someone)
if self.slots[slotID].userID > -1:
token = glob.tokens.getTokenFromUserID(self.slots[slotID].userID)
else:
token = None
# Check if slot is already locked
if self.slots[slotID].status == slotStatuses.locked:
newStatus = slotStatuses.free
else:
newStatus = slotStatuses.locked
# Send updated settings to kicked user, so he returns to lobby
if self.slots[slotID].user is not None:
self.slots[slotID].user.enqueue(serverPackets.updateMatch(self.matchID))
# Set new slot status
self.setSlot(slotID, newStatus, 0, -1, 0)
if token is not None:
# Send updated settings to kicked user, so he returns to lobby
token.enqueue(serverPackets.updateMatch(self.matchID))
# Send updates to everyone else
self.sendUpdate()
self.sendUpdates()
log.info("MPROOM{}: Slot{} {}".format(self.matchID, slotID, "locked" if newStatus == slotStatuses.locked else "unlocked"))
def playerLoaded(self, userID):
@ -269,12 +241,7 @@ class match:
def allPlayersLoaded(self):
"""Send allPlayersLoaded packet to every playing usr in match"""
for i in range(0,16):
if self.slots[i].userID > -1 and self.slots[i].status == slotStatuses.playing:
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
if token is not None:
token.enqueue(serverPackets.allPlayersLoaded())
glob.streams.broadcast(self.playingStreamName, serverPackets.allPlayersLoaded())
log.info("MPROOM{}: All players loaded! Match starting...".format(self.matchID))
def playerSkip(self, userID):
@ -292,12 +259,7 @@ class match:
log.info("MPROOM{}: User {} skipped".format(self.matchID, userID))
# Send skip packet to every playing user
for i in range(0,16):
uid = self.slots[i].userID
if (self.slots[i].status & slotStatuses.playing > 0) and uid > -1:
token = glob.tokens.getTokenFromUserID(uid)
if token is not None:
token.enqueue(serverPackets.playerSkipped(uid))
glob.streams.broadcast(self.playingStreamName, serverPackets.playerSkipped(self.slots[slotID].user.userID))
# Check all skipped
total = 0
@ -313,12 +275,7 @@ class match:
def allPlayersSkipped(self):
"""Send allPlayersSkipped packet to every playing usr in match"""
for i in range(0,16):
if self.slots[i].userID > -1 and self.slots[i].status == slotStatuses.playing:
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
if token is not None:
token.enqueue(serverPackets.allPlayersSkipped())
glob.streams.broadcast(self.playingStreamName, serverPackets.allPlayersSkipped())
log.info("MPROOM{}: All players have skipped!".format(self.matchID))
def playerCompleted(self, userID):
@ -330,7 +287,7 @@ class match:
slotID = self.getUserSlotID(userID)
if slotID is None:
return
self.setSlot(slotID, None, None, None, None, None, None, True)
self.setSlot(slotID, complete=True)
# Console output
log.info("MPROOM{}: User {} has completed his play".format(self.matchID, userID))
@ -355,21 +312,20 @@ class match:
# Reset slots
for i in range(0,16):
if self.slots[i].userID > -1 and self.slots[i].status == slotStatuses.playing:
if self.slots[i].user is not None and self.slots[i].status == slotStatuses.playing:
self.slots[i].status = slotStatuses.notReady
self.slots[i].loaded = False
self.slots[i].skip = False
self.slots[i].complete = False
# Send match update
self.sendUpdate()
self.sendUpdates()
# Send match complete
for i in range(0,16):
if self.slots[i].userID > -1:
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
if token is not None:
token.enqueue(serverPackets.matchComplete())
glob.streams.broadcast(self.streamName, serverPackets.matchComplete())
# Destroy playing stream
glob.streams.remove(self.playingStreamName)
# Console output
log.info("MPROOM{}: Match completed".format(self.matchID))
@ -381,11 +337,11 @@ class match:
return -- slot id if found, None if user is not in room
"""
for i in range(0,16):
if self.slots[i].userID == userID:
if self.slots[i].user is not None and self.slots[i].user.userID == userID:
return i
return None
def userJoin(self, userID):
def userJoin(self, user):
"""
Add someone to users in match
@ -395,39 +351,38 @@ class match:
# Make sure we're not in this match
for i in range(0,16):
if self.slots[i].userID == userID:
if self.slots[i].user == user:
# Set bugged slot to free
self.setSlot(i, slotStatuses.free, 0, -1, 0)
self.setSlot(i, slotStatuses.free, 0, None, 0)
# Find first free slot
for i in range(0,16):
if self.slots[i].status == slotStatuses.free:
# Occupy slot
self.setSlot(i, slotStatuses.notReady, 0, userID, 0)
self.setSlot(i, slotStatuses.notReady, 0, user, 0)
# Send updated match data
self.sendUpdate()
self.sendUpdates()
# Console output
log.info("MPROOM{}: {} joined the room".format(self.matchID, userID))
log.info("MPROOM{}: {} joined the room".format(self.matchID, user.username))
return True
return False
def userLeft(self, userID):
def userLeft(self, user):
"""
Remove someone from users in match
userID -- user if of the user
"""
# Make sure the user is in room
slotID = self.getUserSlotID(userID)
slotID = self.getUserSlotID(user.userID)
if slotID is None:
return
# Set that slot to free
self.setSlot(slotID, slotStatuses.free, 0, -1, 0)
self.setSlot(slotID, slotStatuses.free, 0, None, 0)
# Check if everyone left
if self.countUsers() == 0:
@ -437,19 +392,18 @@ class match:
return
# Check if host left
if userID == self.hostUserID:
if user.userID == self.hostUserID:
# Give host to someone else
for i in range(0,16):
uid = self.slots[i].userID
if uid > -1:
self.setHost(uid)
if self.slots[i].user is not None:
self.setHost(self.slots[i].user.userID)
break
# Send updated match data
self.sendUpdate()
self.sendUpdates()
# Console output
log.info("MPROOM{}: {} left the room".format(self.matchID, userID))
log.info("MPROOM{}: {} left the room".format(self.matchID, user.username))
def userChangeSlot(self, userID, newSlotID):
"""
@ -464,20 +418,21 @@ class match:
return
# Make sure there is no one inside new slot
if self.slots[newSlotID].userID > -1 and self.slots[newSlotID].status != slotStatuses.free:
if self.slots[newSlotID].user is not None and self.slots[newSlotID].status != slotStatuses.free:
return
# Get old slot data
oldData = copy.deepcopy(self.slots[oldSlotID])
oldData = dill.copy(self.slots[oldSlotID])
#oldData = copy.deepcopy(self.slots[oldSlotID])
# Free old slot
self.setSlot(oldSlotID, slotStatuses.free, 0, -1, 0)
self.setSlot(oldSlotID, slotStatuses.free, 0, None, 0)
# Occupy new slot
self.setSlot(newSlotID, oldData.status, oldData.team, oldData.userID, oldData.mods)
self.setSlot(newSlotID, oldData.status, oldData.team, oldData.user, oldData.mods)
# Send updated match data
self.sendUpdate()
self.sendUpdates()
# Console output
log.info("MPROOM{}: {} moved to slot {}".format(self.matchID, userID, newSlotID))
@ -494,14 +449,10 @@ class match:
self.matchPassword = ""
# Send password change to every user in match
for i in range(0,16):
if self.slots[i].userID > -1:
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
if token is not None:
token.enqueue(serverPackets.changeMatchPassword(self.matchPassword))
glob.streams.broadcast(self.streamName, serverPackets.changeMatchPassword(self.matchPassword))
# Send new match settings too
self.sendUpdate()
self.sendUpdates()
# Console output
log.info("MPROOM{}: Password changed to {}".format(self.matchID, self.matchPassword))
@ -514,7 +465,7 @@ class match:
"""
# Set new mods and send update
self.mods = mods
self.sendUpdate()
self.sendUpdates()
log.info("MPROOM{}: Mods changed to {}".format(self.matchID, self.mods))
def userHasBeatmap(self, userID, has = True):
@ -533,7 +484,7 @@ class match:
self.setSlot(slotID, slotStatuses.noMap if not has else slotStatuses.notReady)
# Send updates
self.sendUpdate()
self.sendUpdates()
def transferHost(self, slotID):
"""
@ -542,15 +493,14 @@ class match:
slotID -- ID of slot
"""
# Make sure there is someone in that slot
uid = self.slots[slotID].userID
if uid == -1:
if self.slots[slotID].user is None:
return
# Transfer host
self.setHost(uid)
self.setHost(self.slots[slotID].user.userID)
# Send updates
self.sendUpdate()
self.sendUpdates()
def playerFailed(self, userID):
"""
@ -564,12 +514,7 @@ class match:
return
# Send packet to everyone
for i in range(0,16):
uid = self.slots[i].userID
if uid > -1:
token = glob.tokens.getTokenFromUserID(uid)
if token is not None:
token.enqueue(serverPackets.playerFailed(slotID))
glob.streams.broadcast(self.playingStreamName, serverPackets.playerFailed(slotID))
# Console output
log.info("MPROOM{}: {} has failed!".format(self.matchID, userID))
@ -604,7 +549,7 @@ class match:
"""
c = 0
for i in range(0,16):
if self.slots[i].userID > -1:
if self.slots[i].user is not None:
c+=1
return c
@ -622,17 +567,10 @@ class match:
# Update slot and send update
newTeam = matchTeams.blue if self.slots[slotID].team == matchTeams.red else matchTeams.red
self.setSlot(slotID, None, newTeam)
self.sendUpdate()
self.sendUpdates()
def sendUpdate(self):
# Send to users in room
for i in range(0,16):
if self.slots[i].userID > -1:
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
if token is not None:
token.enqueue(serverPackets.updateMatch(self.matchID))
# Send to users in lobby
def sendUpdates(self):
glob.streams.broadcast(self.streamName, serverPackets.updateMatch(self.matchID))
glob.streams.broadcast("lobby", serverPackets.updateMatch(self.matchID))
def checkTeams(self):
@ -641,14 +579,14 @@ class match:
return -- True if valid, False if invalid
"""
if match.matchTeamType != matchTeamTypes.teamVs or matchTeamTypes != matchTeamTypes.tagTeamVs:
if self.matchTeamType != matchTeamTypes.teamVs or self.matchTeamType != matchTeamTypes.tagTeamVs:
# Teams are always valid if we have no teams
return True
# We have teams, check if they are valid
firstTeam = -1
for i in range(0,16):
if self.slots[i].userID > -1 and (self.slots[i].status&slotStatuses.noMap) == 0:
if self.slots[i].user is not None and (self.slots[i].status&slotStatuses.noMap) == 0:
if firstTeam == -1:
firstTeam = self.slots[i].team
elif firstTeam != self.slots[i].team:
@ -657,3 +595,30 @@ class match:
log.warning("MPROOM{}: Invalid teams!".format(self.matchID))
return False
def start(self):
# Make sure we have enough players
if self.countUsers() < 2 or not self.checkTeams():
return
# Create playing channel
glob.streams.add(self.playingStreamName)
# Change inProgress value
match.inProgress = True
# Set playing to ready players and set load, skip and complete to False
# Make clients join playing stream
for i in range(0, 16):
if (self.slots[i].status & slotStatuses.ready) > 0:
self.slots[i].status = slotStatuses.playing
self.slots[i].loaded = False
self.slots[i].skip = False
self.slots[i].complete = False
self.slots[i].user.joinStream(self.playingStreamName)
# Send match start packet
glob.streams.broadcast(self.playingStreamName, serverPackets.matchStart(self.matchID))
# Send updates
self.sendUpdates()

View File

@ -21,34 +21,12 @@ class matchList:
hostUserID -- user id of who created the match
return -- match ID
"""
# Add a new match to matches list
# Add a new match to matches list and create its stream
matchID = self.lastID
self.lastID+=1
self.matches[matchID] = match.match(matchID, matchName, matchPassword, beatmapID, beatmapName, beatmapMD5, gameMode, hostUserID)
return matchID
'''def lobbyUserJoin(self, userID):
"""
Add userID to users in lobby
userID -- user who joined mp lobby
"""
# Make sure the user is not already in mp lobby
if userID not in self.usersInLobby:
# We don't need to join #lobby, client will automatically send a packet for it
self.usersInLobby.append(userID)
def lobbyUserPart(self, userID):
"""
Remove userID from users in lobby
userID -- user who left mp lobby
"""
# Make sure the user is in mp lobby
if userID in self.usersInLobby:
# Part lobby and #lobby channel
self.usersInLobby.remove(userID)'''
def disposeMatch(self, matchID):
"""
Destroy match object with id = matchID
@ -59,8 +37,10 @@ class matchList:
if matchID not in self.matches:
return
# Remove match object
self.matches.pop(matchID)
# Remove match object and stream
match = self.matches.pop(matchID)
glob.streams.remove(match.streamName)
glob.streams.remove(match.playingStreamName)
# Send match dispose packet to everyone in lobby
glob.streams.broadcast("lobby", serverPackets.disposeMatch(matchID))

View File

@ -216,47 +216,6 @@ class token:
# Set our spectating user to 0
self.spectating = None
def partMatch(self):
# Make sure we are in a match
if self.matchID == -1:
return
# Part #multiplayer channel
chat.partChannel(token=self, channel="#multi_{}".format(self.matchID), kick=True)
# Make sure the match exists
if self.matchID not in glob.matches.matches:
return
# The match exists, get object
match = glob.matches.matches[self.matchID]
# Set slot to free
match.userLeft(self.userID)
# Set usertoken match to -1
self.matchID = -1
'''def addSpectator(self, user):
"""
Add userID to our spectators
user -- user object
"""
# Add userID to spectators if not already in
if user not in self.spectators:
self.spectators.append(user)
def removeSpectator(self, userID):
"""
Remove userID from our spectators
userID -- old spectator userID
"""
# Remove spectator
if userID in self.spectators:
self.spectators.remove(userID)'''
def setCountry(self, countryID):
"""
Set country to countryID
@ -281,13 +240,66 @@ class token:
"""Set a new away message"""
self.awayMessage = __awayMessage
def joinMatch(self, matchID):
"""
Set match to matchID
Set match to matchID, join match stream and channel
matchID -- new match ID
"""
# Make sure the match exists
if matchID not in glob.matches.matches:
return
# Match exists, get object
match = glob.matches.matches[matchID]
# Stop spectating
self.stopSpectating()
# Leave other matches
if self.matchID > -1 and self.matchID != matchID:
self.leaveMatch()
# Try to join match
joined = match.userJoin(self)
if not joined:
self.enqueue(serverPackets.matchJoinFail())
return
# Set matchID, join stream, channel and send packet
self.matchID = matchID
self.joinStream(match.streamName)
chat.joinChannel(token=self, channel="#multi_{}".format(self.matchID))
self.enqueue(serverPackets.matchJoinSuccess(matchID))
def leaveMatch(self):
"""
Leave joined match, match stream and match channel
:return:
"""
# Make sure we are in a match
if self.matchID == -1:
return
# Part #multiplayer channel and streams (/ and /playing)
chat.partChannel(token=self, channel="#multi_{}".format(self.matchID), kick=True)
self.leaveStream("multi/{}".format(self.matchID))
self.leaveStream("multi/{}/playing".format(self.matchID)) # optional
# Make sure the match exists
if self.matchID not in glob.matches.matches:
return
# The match exists, get object
match = glob.matches.matches[self.matchID]
# Set slot to free
match.userLeft(self)
# Set usertoken match to -1
self.matchID = -1
def kick(self, message="You have been kicked from the server. Please login again."):
"""

View File

@ -40,4 +40,5 @@ class stream:
:return:
"""
for i in self.clients:
i.enqueue(data)
if i is not None:
i.enqueue(data)

View File

@ -13,7 +13,6 @@ class streamList:
"""
if name not in self.streams:
self.streams[name] = stream.stream(name)
print(str(self.streams))
def remove(self, name):
"""