IRC Support for username with spaces
BATs with Donor have bright yellow username in chat General performance improvements Code cleaning Multiplayer improvements and fixes Fixed some spectator bugs
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
# TODO: Rewrite this shit
|
||||
from objects import glob
|
||||
from helpers import generalFunctions
|
||||
|
||||
class banchoConfig:
|
||||
class banchoConfig():
|
||||
"""
|
||||
Class that loads settings from bancho_settings db table
|
||||
"""
|
||||
@@ -12,31 +13,30 @@ class banchoConfig:
|
||||
"""
|
||||
Initialize a banchoConfig object (and load bancho_settings from db)
|
||||
|
||||
[loadFromDB -- if True, load values from db. If False, don't load values. Default: True]
|
||||
loadFromDB -- if True, load values from db. If False, don't load values. Optional.
|
||||
"""
|
||||
|
||||
if loadFromDB:
|
||||
try:
|
||||
self.loadSettings()
|
||||
except:
|
||||
raise
|
||||
|
||||
|
||||
def loadSettings(self):
|
||||
"""
|
||||
(re)load bancho_settings from DB and set values in config array
|
||||
"""
|
||||
|
||||
self.config["banchoMaintenance"] = generalFunctions.stringToBool(glob.db.fetch("SELECT value_int FROM bancho_settings WHERE name = 'bancho_maintenance'")["value_int"])
|
||||
self.config["freeDirect"] = generalFunctions.stringToBool(glob.db.fetch("SELECT value_int FROM bancho_settings WHERE name = 'free_direct'")["value_int"])
|
||||
self.config["menuIcon"] = glob.db.fetch("SELECT value_string FROM bancho_settings WHERE name = 'menu_icon'")["value_string"]
|
||||
self.config["loginNotification"] = glob.db.fetch("SELECT value_string FROM bancho_settings WHERE name = 'login_notification'")["value_string"]
|
||||
|
||||
|
||||
def setMaintenance(self, maintenance):
|
||||
"""
|
||||
Turn on/off bancho maintenance mode. Write new value to db too
|
||||
|
||||
maintenance -- if True, turn on maintenance mode. If false, turn it off
|
||||
"""
|
||||
|
||||
self.config["banchoMaintenance"] = maintenance
|
||||
glob.db.execute("UPDATE bancho_settings SET value_int = %s WHERE name = 'bancho_maintenance'", [int(maintenance)])
|
||||
|
@@ -1,6 +1,6 @@
|
||||
from objects import glob
|
||||
|
||||
class channel:
|
||||
class channel():
|
||||
"""
|
||||
A chat channel
|
||||
"""
|
||||
@@ -16,7 +16,6 @@ class channel:
|
||||
temp -- if True, channel will be deleted when there's no one in the channel
|
||||
hidden -- if True, channel won't be shown in channels list
|
||||
"""
|
||||
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.publicRead = publicRead
|
||||
@@ -33,25 +32,21 @@ class channel:
|
||||
elif self.name.startswith("#multi_"):
|
||||
self.clientName = "#multiplayer"
|
||||
|
||||
|
||||
def userJoin(self, userID):
|
||||
"""
|
||||
Add a user to connected users
|
||||
|
||||
userID -- user ID that joined the channel
|
||||
"""
|
||||
|
||||
if userID not in self.connectedUsers:
|
||||
self.connectedUsers.append(userID)
|
||||
|
||||
|
||||
def userPart(self, userID):
|
||||
"""
|
||||
Remove a user from connected users
|
||||
|
||||
userID -- user ID that left the channel
|
||||
"""
|
||||
|
||||
if userID in self.connectedUsers:
|
||||
self.connectedUsers.remove(userID)
|
||||
|
||||
@@ -60,7 +55,6 @@ class channel:
|
||||
if self.temp == True and ((l == 0) or (l == 1 and 999 in self.connectedUsers)):
|
||||
glob.channels.removeChannel(self.name)
|
||||
|
||||
|
||||
def getConnectedUsers(self):
|
||||
"""
|
||||
Get connected user IDs list
|
||||
@@ -69,7 +63,6 @@ class channel:
|
||||
"""
|
||||
return self.connectedUsers
|
||||
|
||||
|
||||
def getConnectedUsersCount(self):
|
||||
"""
|
||||
Count connected users
|
||||
|
@@ -2,16 +2,14 @@ from objects import glob
|
||||
from objects import channel
|
||||
from helpers import logHelper as log
|
||||
|
||||
class channelList:
|
||||
class channelList():
|
||||
"""
|
||||
Channel list
|
||||
|
||||
channels -- dictionary. key: channel name, value: channel object
|
||||
"""
|
||||
|
||||
channels = {}
|
||||
|
||||
|
||||
def loadChannels(self):
|
||||
"""
|
||||
Load chat channels from db and add them to channels dictionary
|
||||
@@ -27,7 +25,6 @@ class channelList:
|
||||
publicWrite = True if i["public_write"] == 1 else False
|
||||
self.addChannel(i["name"], i["description"], publicRead, publicWrite)
|
||||
|
||||
|
||||
def addChannel(self, name, description, publicRead, publicWrite, temp = False, hidden = False):
|
||||
"""
|
||||
Add a channel object to channels dictionary
|
||||
@@ -42,7 +39,6 @@ class channelList:
|
||||
self.channels[name] = channel.channel(name, description, publicRead, publicWrite, temp, hidden)
|
||||
log.info("Created channel {}".format(name))
|
||||
|
||||
|
||||
def addTempChannel(self, name):
|
||||
"""
|
||||
Add a temporary channel (like #spectator or #multiplayer), gets deleted when there's no one in the channel
|
||||
@@ -56,7 +52,6 @@ class channelList:
|
||||
self.channels[name] = channel.channel(name, "Chat", True, True, True, True)
|
||||
log.info("Created temp channel {}".format(name))
|
||||
|
||||
|
||||
def removeChannel(self, name):
|
||||
"""
|
||||
Removes a channel from channels list
|
||||
|
@@ -1,4 +1,4 @@
|
||||
class chatFilters:
|
||||
class chatFilters():
|
||||
def __init__(self, fileName="filters.txt"):
|
||||
self.filters = {}
|
||||
self.loadFilters(fileName)
|
||||
|
@@ -17,12 +17,10 @@ def connect():
|
||||
glob.tokens.enqueueAll(serverPackets.userPanel(999))
|
||||
glob.tokens.enqueueAll(serverPackets.userStats(999))
|
||||
|
||||
|
||||
def disconnect():
|
||||
"""Remove FokaBot from connected users"""
|
||||
glob.tokens.deleteToken(glob.tokens.getTokenFromUserID(999))
|
||||
|
||||
|
||||
def fokabotResponse(fro, chan, message):
|
||||
"""
|
||||
Check if a message has triggered fokabot (and return its response)
|
||||
@@ -57,4 +55,4 @@ def fokabotResponse(fro, chan, message):
|
||||
return i["callback"](fro, chan, message[1:])
|
||||
|
||||
# No commands triggered
|
||||
return False
|
||||
return False
|
158
objects/match.py
158
objects/match.py
@@ -10,8 +10,20 @@ from constants import dataTypes
|
||||
from constants import matchTeams
|
||||
from helpers import logHelper as log
|
||||
from helpers import chatHelper as chat
|
||||
from helpers import generalFunctions
|
||||
import copy
|
||||
|
||||
class match:
|
||||
class slot():
|
||||
def __init__(self):
|
||||
self.status = slotStatuses.free
|
||||
self.team = 0
|
||||
self.userID = -1
|
||||
self.mods = 0
|
||||
self.loaded = False
|
||||
self.skip = False
|
||||
self.complete = False
|
||||
|
||||
class match():
|
||||
"""Multiplayer match object"""
|
||||
matchID = 0
|
||||
inProgress = False
|
||||
@@ -21,7 +33,7 @@ class match:
|
||||
beatmapName = ""
|
||||
beatmapID = 0
|
||||
beatmapMD5 = ""
|
||||
slots = [] # list of dictionaries {"status": 0, "team": 0, "userID": -1, "mods": 0, "loaded": False, "skip": False, "complete": False}
|
||||
slots = []
|
||||
hostUserID = 0
|
||||
gameMode = gameModes.std
|
||||
matchScoringType = matchScoringTypes.score
|
||||
@@ -46,7 +58,10 @@ class match:
|
||||
self.inProgress = False
|
||||
self.mods = 0
|
||||
self.matchName = matchName
|
||||
self.matchPassword = matchPassword
|
||||
if matchPassword != "":
|
||||
self.matchPassword = generalFunctions.stringMd5(matchPassword)
|
||||
else:
|
||||
self.matchPassword = ""
|
||||
self.beatmapID = beatmapID
|
||||
self.beatmapName = beatmapName
|
||||
self.beatmapMD5 = beatmapMD5
|
||||
@@ -60,12 +75,11 @@ class match:
|
||||
# Create all slots and reset them
|
||||
self.slots = []
|
||||
for _ in range(0,16):
|
||||
self.slots.append({"status": slotStatuses.free, "team": 0, "userID": -1, "mods": 0, "loaded": False, "skip": False, "complete": False})
|
||||
self.slots.append(slot())
|
||||
|
||||
# Create #multiplayer channel
|
||||
glob.channels.addTempChannel("#multi_{}".format(self.matchID))
|
||||
|
||||
|
||||
def getMatchData(self):
|
||||
"""
|
||||
Return binary match data structure for packetHelper
|
||||
@@ -85,15 +99,15 @@ class match:
|
||||
|
||||
# Slots status IDs, always 16 elements
|
||||
for i in range(0,16):
|
||||
struct.append([self.slots[i]["status"], dataTypes.byte])
|
||||
struct.append([self.slots[i].status, dataTypes.byte])
|
||||
|
||||
# Slot teams, always 16 elements
|
||||
for i in range(0,16):
|
||||
struct.append([self.slots[i]["team"], dataTypes.byte])
|
||||
struct.append([self.slots[i].team, dataTypes.byte])
|
||||
|
||||
# Slot user ID. Write only if slot is occupied
|
||||
for i in range(0,16):
|
||||
uid = self.slots[i]["userID"]
|
||||
uid = self.slots[i].userID
|
||||
if uid > -1:
|
||||
struct.append([uid, dataTypes.uInt32])
|
||||
|
||||
@@ -109,15 +123,13 @@ class match:
|
||||
# Slot mods if free mod is enabled
|
||||
if self.matchModMode == matchModModes.freeMod:
|
||||
for i in range(0,16):
|
||||
struct.append([self.slots[i]["mods"], dataTypes.uInt32])
|
||||
struct.append([self.slots[i].mods, dataTypes.uInt32])
|
||||
|
||||
# Seed idk
|
||||
struct.append([self.seed, dataTypes.uInt32])
|
||||
|
||||
return struct
|
||||
|
||||
|
||||
|
||||
def setHost(self, newHost):
|
||||
"""
|
||||
Set room host to newHost and send him host packet
|
||||
@@ -149,26 +161,25 @@ class match:
|
||||
If Null is passed, that value won't be edited
|
||||
"""
|
||||
if slotStatus != None:
|
||||
self.slots[slotID]["status"] = slotStatus
|
||||
self.slots[slotID].status = slotStatus
|
||||
|
||||
if slotTeam != None:
|
||||
self.slots[slotID]["team"] = slotTeam
|
||||
self.slots[slotID].team = slotTeam
|
||||
|
||||
if slotUserID != None:
|
||||
self.slots[slotID]["userID"] = slotUserID
|
||||
self.slots[slotID].userID = slotUserID
|
||||
|
||||
if slotMods != None:
|
||||
self.slots[slotID]["mods"] = slotMods
|
||||
self.slots[slotID].mods = slotMods
|
||||
|
||||
if slotLoaded != None:
|
||||
self.slots[slotID]["loaded"] = slotLoaded
|
||||
self.slots[slotID].loaded = slotLoaded
|
||||
|
||||
if slotSkip != None:
|
||||
self.slots[slotID]["skip"] = slotSkip
|
||||
self.slots[slotID].skip = slotSkip
|
||||
|
||||
if slotComplete != None:
|
||||
self.slots[slotID]["complete"] = slotComplete
|
||||
|
||||
self.slots[slotID].complete = slotComplete
|
||||
|
||||
def setSlotMods(self, slotID, mods):
|
||||
"""
|
||||
@@ -182,7 +193,6 @@ class match:
|
||||
self.sendUpdate()
|
||||
log.info("MPROOM{}: Slot{} mods changed to {}".format(self.matchID, slotID, mods))
|
||||
|
||||
|
||||
def toggleSlotReady(self, slotID):
|
||||
"""
|
||||
Switch slotID ready/not ready status
|
||||
@@ -191,14 +201,14 @@ class match:
|
||||
slotID -- slot number
|
||||
"""
|
||||
# Update ready status and setnd update
|
||||
oldStatus = self.slots[slotID]["status"]
|
||||
oldStatus = self.slots[slotID].status
|
||||
if oldStatus == slotStatuses.ready:
|
||||
newStatus = slotStatuses.notReady
|
||||
else:
|
||||
newStatus = slotStatuses.ready
|
||||
self.setSlot(slotID, newStatus, None, None, None)
|
||||
self.sendUpdate()
|
||||
log.info("MPROOM{}: Slot{} changed ready status to {}".format(self.matchID, slotID, self.slots[slotID]["status"]))
|
||||
log.info("MPROOM{}: Slot{} changed ready status to {}".format(self.matchID, slotID, self.slots[slotID].status))
|
||||
|
||||
def toggleSlotLock(self, slotID):
|
||||
"""
|
||||
@@ -208,13 +218,13 @@ 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"])
|
||||
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:
|
||||
if self.slots[slotID].status == slotStatuses.locked:
|
||||
newStatus = slotStatuses.free
|
||||
else:
|
||||
newStatus = slotStatuses.locked
|
||||
@@ -240,33 +250,31 @@ class match:
|
||||
return
|
||||
|
||||
# Set loaded to True
|
||||
self.slots[slotID]["loaded"] = True
|
||||
self.slots[slotID].loaded = True
|
||||
log.info("MPROOM{}: User {} loaded".format(self.matchID, userID))
|
||||
|
||||
# Check all loaded
|
||||
total = 0
|
||||
loaded = 0
|
||||
for i in range(0,16):
|
||||
if self.slots[i]["status"] == slotStatuses.playing:
|
||||
if self.slots[i].status == slotStatuses.playing:
|
||||
total+=1
|
||||
if self.slots[i]["loaded"] == True:
|
||||
if self.slots[i].loaded == True:
|
||||
loaded+=1
|
||||
|
||||
if total == loaded:
|
||||
self.allPlayersLoaded()
|
||||
|
||||
|
||||
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 self.slots[i].userID > -1 and self.slots[i].status == slotStatuses.playing:
|
||||
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
|
||||
if token != None:
|
||||
token.enqueue(serverPackets.allPlayersLoaded())
|
||||
|
||||
log.info("MPROOM{}: All players loaded! Match starting...".format(self.matchID))
|
||||
|
||||
|
||||
def playerSkip(self, userID):
|
||||
"""
|
||||
Set a player skip status to True
|
||||
@@ -278,13 +286,13 @@ class match:
|
||||
return
|
||||
|
||||
# Set skip to True
|
||||
self.slots[slotID]["skip"] = True
|
||||
self.slots[slotID].skip = True
|
||||
log.info("MPROOM{}: User {} skipped".format(self.matchID, userID))
|
||||
|
||||
# Send skip packet to every playing useR
|
||||
# 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 and uid > -1:
|
||||
uid = self.slots[i].userID
|
||||
if (self.slots[i].status & slotStatuses.playing > 0) and uid > -1:
|
||||
token = glob.tokens.getTokenFromUserID(uid)
|
||||
if token != None:
|
||||
token.enqueue(serverPackets.playerSkipped(uid))
|
||||
@@ -293,9 +301,9 @@ class match:
|
||||
total = 0
|
||||
skipped = 0
|
||||
for i in range(0,16):
|
||||
if self.slots[i]["status"] == slotStatuses.playing:
|
||||
if self.slots[i].status == slotStatuses.playing:
|
||||
total+=1
|
||||
if self.slots[i]["skip"] == True:
|
||||
if self.slots[i].skip == True:
|
||||
skipped+=1
|
||||
|
||||
if total == skipped:
|
||||
@@ -304,8 +312,8 @@ 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 self.slots[i].userID > -1 and self.slots[i].status == slotStatuses.playing:
|
||||
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
|
||||
if token != None:
|
||||
token.enqueue(serverPackets.allPlayersSkipped())
|
||||
|
||||
@@ -329,9 +337,9 @@ class match:
|
||||
total = 0
|
||||
completed = 0
|
||||
for i in range(0,16):
|
||||
if self.slots[i]["status"] == slotStatuses.playing:
|
||||
if self.slots[i].status == slotStatuses.playing:
|
||||
total+=1
|
||||
if self.slots[i]["complete"] == True:
|
||||
if self.slots[i].complete == True:
|
||||
completed+=1
|
||||
|
||||
if total == completed:
|
||||
@@ -345,38 +353,34 @@ class match:
|
||||
|
||||
# Reset slots
|
||||
for i in range(0,16):
|
||||
if self.slots[i]["userID"] > -1 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
|
||||
if self.slots[i].userID > -1 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()
|
||||
|
||||
# Send match complete
|
||||
for i in range(0,16):
|
||||
if self.slots[i]["userID"] > -1:
|
||||
token = glob.tokens.getTokenFromUserID(self.slots[i]["userID"])
|
||||
if self.slots[i].userID > -1:
|
||||
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
|
||||
if token != None:
|
||||
token.enqueue(serverPackets.matchComplete())
|
||||
|
||||
# Console output
|
||||
log.info("MPROOM{}: Match completed".format(self.matchID))
|
||||
|
||||
|
||||
|
||||
def getUserSlotID(self, userID):
|
||||
"""
|
||||
Get slot ID occupied by userID
|
||||
|
||||
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].userID == userID:
|
||||
return i
|
||||
|
||||
return None
|
||||
|
||||
def userJoin(self, userID):
|
||||
@@ -389,7 +393,7 @@ class match:
|
||||
|
||||
# Find first free slot
|
||||
for i in range(0,16):
|
||||
if self.slots[i]["status"] == slotStatuses.free:
|
||||
if self.slots[i].status == slotStatuses.free:
|
||||
# Occupy slot
|
||||
self.setSlot(i, slotStatuses.notReady, 0, userID, 0)
|
||||
|
||||
@@ -409,7 +413,6 @@ class match:
|
||||
|
||||
userID -- user if of the user
|
||||
"""
|
||||
|
||||
# Make sure the user is in room
|
||||
slotID = self.getUserSlotID(userID)
|
||||
if slotID == None:
|
||||
@@ -429,7 +432,7 @@ class match:
|
||||
if userID == self.hostUserID:
|
||||
# Give host to someone else
|
||||
for i in range(0,16):
|
||||
uid = self.slots[i]["userID"]
|
||||
uid = self.slots[i].userID
|
||||
if uid > -1:
|
||||
self.setHost(uid)
|
||||
break
|
||||
@@ -440,7 +443,6 @@ class match:
|
||||
# Console output
|
||||
log.info("MPROOM{}: {} left the room".format(self.matchID, userID))
|
||||
|
||||
|
||||
def userChangeSlot(self, userID, newSlotID):
|
||||
"""
|
||||
Change userID slot to newSlotID
|
||||
@@ -448,24 +450,23 @@ class match:
|
||||
userID -- user that changed slot
|
||||
newSlotID -- slot id of new slot
|
||||
"""
|
||||
|
||||
# Make sure the user is in room
|
||||
oldSlotID = self.getUserSlotID(userID)
|
||||
if oldSlotID == None:
|
||||
return
|
||||
|
||||
# Make sure there is no one inside new slot
|
||||
if self.slots[newSlotID]["userID"] > -1:
|
||||
if self.slots[newSlotID].userID > -1 and self.slots[newSlotID].status != slotStatuses.free:
|
||||
return
|
||||
|
||||
# Get old slot data
|
||||
oldData = self.slots[oldSlotID].copy()
|
||||
oldData = copy.deepcopy(self.slots[oldSlotID])
|
||||
|
||||
# Free old slot
|
||||
self.setSlot(oldSlotID, slotStatuses.free, 0, -1, 0)
|
||||
|
||||
# Occupy new slot
|
||||
self.setSlot(newSlotID, oldData["status"], oldData["team"], userID, oldData["mods"])
|
||||
self.setSlot(newSlotID, oldData.status, oldData.team, oldData.userID, oldData.mods)
|
||||
|
||||
# Send updated match data
|
||||
self.sendUpdate()
|
||||
@@ -479,12 +480,15 @@ class match:
|
||||
|
||||
newPassword -- new password string
|
||||
"""
|
||||
self.matchPassword = newPassword
|
||||
if newPassword != "":
|
||||
self.matchPassword = generalFunctions.stringMd5(newPassword)
|
||||
else:
|
||||
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 self.slots[i].userID > -1:
|
||||
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
|
||||
if token != None:
|
||||
token.enqueue(serverPackets.changeMatchPassword(self.matchPassword))
|
||||
|
||||
@@ -494,7 +498,6 @@ class match:
|
||||
# Console output
|
||||
log.info("MPROOM{}: Password changed to {}".format(self.matchID, self.matchPassword))
|
||||
|
||||
|
||||
def changeMatchMods(self, mods):
|
||||
"""
|
||||
Set match global mods
|
||||
@@ -531,7 +534,7 @@ class match:
|
||||
slotID -- ID of slot
|
||||
"""
|
||||
# Make sure there is someone in that slot
|
||||
uid = self.slots[slotID]["userID"]
|
||||
uid = self.slots[slotID].userID
|
||||
if uid == -1:
|
||||
return
|
||||
|
||||
@@ -541,7 +544,6 @@ class match:
|
||||
# Send updates
|
||||
self.sendUpdate()
|
||||
|
||||
|
||||
def playerFailed(self, userID):
|
||||
"""
|
||||
Send userID's failed packet to everyone in match
|
||||
@@ -555,7 +557,7 @@ class match:
|
||||
|
||||
# Send packet to everyone
|
||||
for i in range(0,16):
|
||||
uid = self.slots[i]["userID"]
|
||||
uid = self.slots[i].userID
|
||||
if uid > -1:
|
||||
token = glob.tokens.getTokenFromUserID(uid)
|
||||
if token != None:
|
||||
@@ -564,7 +566,6 @@ class match:
|
||||
# Console output
|
||||
log.info("MPROOM{}: {} has failed!".format(self.matchID, userID))
|
||||
|
||||
|
||||
def invite(self, fro, to):
|
||||
"""
|
||||
Fro invites to in this match.
|
||||
@@ -587,19 +588,16 @@ class match:
|
||||
message = "Come join my multiplayer match: \"[osump://{}/{} {}]\"".format(self.matchID, self.matchPassword.replace(" ", "_"), self.matchName)
|
||||
chat.sendMessage(token=froToken, to=toToken.username, message=message)
|
||||
|
||||
|
||||
def countUsers(self):
|
||||
"""
|
||||
Return how many players are in that match
|
||||
|
||||
return -- number of users
|
||||
"""
|
||||
|
||||
c = 0
|
||||
for i in range(0,16):
|
||||
if self.slots[i]["userID"] > -1:
|
||||
if self.slots[i].userID > -1:
|
||||
c+=1
|
||||
|
||||
return c
|
||||
|
||||
def changeTeam(self, userID):
|
||||
@@ -614,15 +612,15 @@ class match:
|
||||
return
|
||||
|
||||
# Update slot and send update
|
||||
newTeam = matchTeams.blue if self.slots[slotID]["team"] == matchTeams.red else matchTeams.red
|
||||
newTeam = matchTeams.blue if self.slots[slotID].team == matchTeams.red else matchTeams.red
|
||||
self.setSlot(slotID, None, newTeam)
|
||||
self.sendUpdate()
|
||||
|
||||
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 self.slots[i].userID > -1:
|
||||
token = glob.tokens.getTokenFromUserID(self.slots[i].userID)
|
||||
if token != None:
|
||||
token.enqueue(serverPackets.updateMatch(self.matchID))
|
||||
|
||||
@@ -645,10 +643,10 @@ class match:
|
||||
# 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].userID > -1 and (self.slots[i].status&slotStatuses.noMap) == 0:
|
||||
if firstTeam == -1:
|
||||
firstTeam = self.slots[i]["team"]
|
||||
elif firstTeam != self.slots[i]["teams"]:
|
||||
firstTeam = self.slots[i].team
|
||||
elif firstTeam != self.slots[i].team:
|
||||
log.info("MPROOM{}: Teams are valid".format(self.matchID))
|
||||
return True
|
||||
|
||||
|
@@ -2,7 +2,7 @@ from objects import match
|
||||
from objects import glob
|
||||
from constants import serverPackets
|
||||
|
||||
class matchList:
|
||||
class matchList():
|
||||
matches = {}
|
||||
usersInLobby = []
|
||||
lastID = 1
|
||||
@@ -32,49 +32,43 @@ class matchList:
|
||||
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):
|
||||
def disposeMatch(self, matchID):
|
||||
"""
|
||||
Destroy match object with id = __matchID
|
||||
Destroy match object with id = matchID
|
||||
|
||||
__matchID -- ID of match to dispose
|
||||
matchID -- ID of match to dispose
|
||||
"""
|
||||
|
||||
# Make sure the match exists
|
||||
if __matchID not in self.matches:
|
||||
if matchID not in self.matches:
|
||||
return
|
||||
|
||||
# Remove match object
|
||||
self.matches.pop(__matchID)
|
||||
self.matches.pop(matchID)
|
||||
|
||||
# Send match dispose packet to everyone in lobby
|
||||
for i in self.usersInLobby:
|
||||
token = glob.tokens.getTokenFromUserID(i)
|
||||
if token != None:
|
||||
token.enqueue(serverPackets.disposeMatch(__matchID))
|
||||
token.enqueue(serverPackets.disposeMatch(matchID))
|
||||
|
@@ -8,33 +8,9 @@ from objects import glob
|
||||
import uuid
|
||||
import time
|
||||
import threading
|
||||
from helpers import logHelper as log
|
||||
from helpers import chatHelper as chat
|
||||
|
||||
class token:
|
||||
"""
|
||||
Osu Token object
|
||||
|
||||
token -- token string
|
||||
userID -- userID associated to that token
|
||||
username -- username relative to userID (cache)
|
||||
actionID -- current user action (see actions.py)
|
||||
actionText -- current user action text
|
||||
actionMd5 -- md5 relative to user action
|
||||
actionMods -- current acton mods
|
||||
gameMode -- current user game mode
|
||||
location -- [latitude,longitude]
|
||||
queue -- packets queue
|
||||
joinedChannels -- list. Contains joined channel names
|
||||
spectating -- userID of spectating user. 0 if not spectating.
|
||||
spectators -- list. Contains userIDs of spectators
|
||||
country -- osu country code. Use countryHelper to convert from letter country code to osu country code
|
||||
pingTime -- latest packet received UNIX time
|
||||
loginTime -- login UNIX time
|
||||
latestTillerino -- beatmap ID of latest song from tillerino bot
|
||||
"""
|
||||
|
||||
|
||||
class token():
|
||||
def __init__(self, userID, token = None, ip = "", irc = False, timeOffset = 0):
|
||||
"""
|
||||
Create a token object and set userID and token
|
||||
@@ -44,8 +20,8 @@ class token:
|
||||
if not passed, token will be generated
|
||||
ip -- client ip. optional.
|
||||
irc -- if True, set this token as IRC client. optional.
|
||||
timeOffset -- the time offset from UTC for this user. optional.
|
||||
"""
|
||||
|
||||
# Set stuff
|
||||
self.userID = userID
|
||||
self.username = userHelper.getUsername(self.userID)
|
||||
@@ -71,7 +47,6 @@ class token:
|
||||
self.tillerino = [0,0,-1.0] # beatmap, mods, acc
|
||||
self.silenceEndTime = 0
|
||||
self.queue = bytes()
|
||||
self.osuDirectAlert = False # NOTE: Remove this when osu!direct will be fixed
|
||||
|
||||
# Spam protection
|
||||
self.spamRate = 0
|
||||
@@ -102,14 +77,14 @@ class token:
|
||||
if ip != "":
|
||||
userHelper.saveBanchoSession(self.userID, self.ip)
|
||||
|
||||
def enqueue(self, __bytes):
|
||||
def enqueue(self, bytes):
|
||||
"""
|
||||
Add bytes (packets) to queue
|
||||
|
||||
__bytes -- (packet) bytes to enqueue
|
||||
bytes -- (packet) bytes to enqueue
|
||||
"""
|
||||
if self.irc == False:
|
||||
self.queue += __bytes
|
||||
self.queue += bytes
|
||||
|
||||
|
||||
def resetQueue(self):
|
||||
@@ -117,95 +92,140 @@ class token:
|
||||
self.queue = bytes()
|
||||
|
||||
|
||||
def joinChannel(self, __channel):
|
||||
"""Add __channel to joined channels list
|
||||
def joinChannel(self, channel):
|
||||
"""
|
||||
Add channel to joined channels list
|
||||
|
||||
__channel -- channel name"""
|
||||
channel -- channel name
|
||||
"""
|
||||
if channel not in self.joinedChannels:
|
||||
self.joinedChannels.append(channel)
|
||||
|
||||
if __channel not in self.joinedChannels:
|
||||
self.joinedChannels.append(__channel)
|
||||
def partChannel(self, channel):
|
||||
"""
|
||||
Remove channel from joined channels list
|
||||
|
||||
channel -- channel name
|
||||
"""
|
||||
if channel in self.joinedChannels:
|
||||
self.joinedChannels.remove(channel)
|
||||
|
||||
def partChannel(self, __channel):
|
||||
"""Remove __channel from joined channels list
|
||||
|
||||
__channel -- channel name"""
|
||||
|
||||
if __channel in self.joinedChannels:
|
||||
self.joinedChannels.remove(__channel)
|
||||
|
||||
|
||||
def setLocation(self, __location):
|
||||
"""Set location (latitude and longitude)
|
||||
|
||||
__location -- [latitude, longitude]"""
|
||||
|
||||
self.location = __location
|
||||
def setLocation(self, location):
|
||||
"""
|
||||
Set location (latitude and longitude)
|
||||
|
||||
location -- [latitude, longitude]
|
||||
"""
|
||||
self.location = location
|
||||
|
||||
def getLatitude(self):
|
||||
"""Get latitude
|
||||
|
||||
return -- latitude"""
|
||||
"""
|
||||
Get latitude
|
||||
|
||||
return -- latitude
|
||||
"""
|
||||
return self.location[0]
|
||||
|
||||
|
||||
def getLongitude(self):
|
||||
"""Get longitude
|
||||
"""
|
||||
Get longitude
|
||||
|
||||
return -- longitude"""
|
||||
return -- longitude
|
||||
"""
|
||||
return self.location[1]
|
||||
|
||||
|
||||
def startSpectating(self, userID):
|
||||
"""Set the spectating user to userID
|
||||
"""
|
||||
Set the spectating user to userID
|
||||
|
||||
userID -- target userID"""
|
||||
userID -- target userID
|
||||
"""
|
||||
self.spectating = userID
|
||||
|
||||
|
||||
def stopSpectating(self):
|
||||
"""Set the spectating user to 0, aka no user"""
|
||||
# Remove our userID from host's spectators
|
||||
target = self.spectating
|
||||
targetToken = glob.tokens.getTokenFromUserID(target)
|
||||
if targetToken != None:
|
||||
# Remove us from host's spectators list
|
||||
targetToken.removeSpectator(self.userID)
|
||||
|
||||
# Send the spectator left packet to host
|
||||
targetToken.enqueue(serverPackets.removeSpectator(self.userID))
|
||||
for c in targetToken.spectators:
|
||||
spec = glob.tokens.getTokenFromUserID(c)
|
||||
spec.enqueue(serverPackets.fellowSpectatorLeft(self.userID))
|
||||
|
||||
# If nobody is spectating the host anymore, close #spectator channel
|
||||
if len(targetToken.spectators) == 0:
|
||||
chat.partChannel(token=targetToken, channel="#spect_{}".format(target), kick=True)
|
||||
|
||||
# Part #spectator channel
|
||||
chat.partChannel(token=self, channel="#spect_{}".format(target), kick=True)
|
||||
|
||||
# Set our spectating user to 0
|
||||
self.spectating = 0
|
||||
|
||||
# Console output
|
||||
log.info("{} are no longer spectating {}".format(self.username, target))
|
||||
|
||||
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, userID):
|
||||
"""Add userID to our spectators
|
||||
|
||||
userID -- new spectator userID"""
|
||||
"""
|
||||
Add userID to our spectators
|
||||
|
||||
userID -- new spectator userID
|
||||
"""
|
||||
# Add userID to spectators if not already in
|
||||
if userID not in self.spectators:
|
||||
self.spectators.append(userID)
|
||||
|
||||
|
||||
def removeSpectator(self, userID):
|
||||
"""Remove userID from our spectators
|
||||
|
||||
userID -- old spectator 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
|
||||
|
||||
def setCountry(self, __countryID):
|
||||
"""Set country to __countryID
|
||||
|
||||
__countryID -- numeric country ID. See countryHelper.py"""
|
||||
|
||||
self.country = __countryID
|
||||
|
||||
countryID -- numeric country ID. See countryHelper.py
|
||||
"""
|
||||
self.country = countryID
|
||||
|
||||
def getCountry(self):
|
||||
"""Get numeric country ID
|
||||
|
||||
return -- numeric country ID. See countryHelper.py"""
|
||||
"""
|
||||
Get numeric country ID
|
||||
|
||||
return -- numeric country ID. See countryHelper.py
|
||||
"""
|
||||
return self.country
|
||||
|
||||
|
||||
def updatePingTime(self):
|
||||
"""Update latest ping time"""
|
||||
self.pingTime = int(time.time())
|
||||
@@ -214,23 +234,24 @@ class token:
|
||||
"""Set a new away message"""
|
||||
self.awayMessage = __awayMessage
|
||||
|
||||
def joinMatch(self, __matchID):
|
||||
def joinMatch(self, matchID):
|
||||
"""
|
||||
Set match to matchID
|
||||
|
||||
__matchID -- new match ID
|
||||
matchID -- new match ID
|
||||
"""
|
||||
self.matchID = __matchID
|
||||
|
||||
def partMatch(self):
|
||||
"""Set match to -1"""
|
||||
self.matchID = -1
|
||||
self.matchID = matchID
|
||||
|
||||
def kick(self, message="You have been kicked from the server. Please login again."):
|
||||
"""Kick this user from the server"""
|
||||
"""
|
||||
Kick this user from the server
|
||||
|
||||
message -- Notification message to send to this user. Optional.
|
||||
"""
|
||||
# Send packet to target
|
||||
log.info("{} has been disconnected. (kick)".format(self.username))
|
||||
self.enqueue(serverPackets.notification(message))
|
||||
if message != "":
|
||||
self.enqueue(serverPackets.notification(message))
|
||||
self.enqueue(serverPackets.loginFailed())
|
||||
|
||||
# Logout event
|
||||
|
@@ -3,10 +3,9 @@ from objects import glob
|
||||
import time
|
||||
import threading
|
||||
from events import logoutEvent
|
||||
from helpers import logHelper as log
|
||||
from helpers import userHelper
|
||||
|
||||
class tokenList:
|
||||
class tokenList():
|
||||
"""
|
||||
List of connected osu tokens
|
||||
|
||||
@@ -27,7 +26,6 @@ class tokenList:
|
||||
irc -- if True, set this token as IRC client
|
||||
return -- token object
|
||||
"""
|
||||
|
||||
newToken = osuToken.token(userID, ip=ip, irc=irc, timeOffset=timeOffset)
|
||||
self.tokens[newToken.token] = newToken
|
||||
return newToken
|
||||
@@ -38,7 +36,6 @@ class tokenList:
|
||||
|
||||
token -- token string
|
||||
"""
|
||||
|
||||
if token in self.tokens:
|
||||
# Delete session from DB
|
||||
if self.tokens[token].ip != "":
|
||||
@@ -47,16 +44,13 @@ class tokenList:
|
||||
# Pop token from list
|
||||
self.tokens.pop(token)
|
||||
|
||||
|
||||
def getUserIDFromToken(self, token):
|
||||
"""
|
||||
Get user ID from a token
|
||||
|
||||
token -- token to find
|
||||
|
||||
return: false if not found, userID if found
|
||||
return -- false if not found, userID if found
|
||||
"""
|
||||
|
||||
# Make sure the token exists
|
||||
if token not in self.tokens:
|
||||
return False
|
||||
@@ -64,7 +58,6 @@ class tokenList:
|
||||
# Get userID associated to that token
|
||||
return self.tokens[token].userID
|
||||
|
||||
|
||||
def getTokenFromUserID(self, userID):
|
||||
"""
|
||||
Get token from a user ID
|
||||
@@ -72,7 +65,6 @@ class tokenList:
|
||||
userID -- user ID to find
|
||||
return -- False if not found, token object if found
|
||||
"""
|
||||
|
||||
# Make sure the token exists
|
||||
for _, value in self.tokens.items():
|
||||
if value.userID == userID:
|
||||
@@ -81,7 +73,6 @@ class tokenList:
|
||||
# Return none if not found
|
||||
return None
|
||||
|
||||
|
||||
def getTokenFromUsername(self, username):
|
||||
"""
|
||||
Get token from a username
|
||||
@@ -89,7 +80,6 @@ class tokenList:
|
||||
username -- username to find
|
||||
return -- False if not found, token object if found
|
||||
"""
|
||||
|
||||
# lowercase
|
||||
who = username.lower()
|
||||
|
||||
@@ -101,7 +91,6 @@ class tokenList:
|
||||
# Return none if not found
|
||||
return None
|
||||
|
||||
|
||||
def deleteOldTokens(self, userID):
|
||||
"""
|
||||
Delete old userID's tokens if found
|
||||
@@ -114,11 +103,6 @@ class tokenList:
|
||||
if value.userID == userID:
|
||||
# Delete this token from the dictionary
|
||||
self.tokens[key].kick("You have logged in from somewhere else. You can't connect to Bancho/IRC from more than one device at the same time.")
|
||||
#self.tokens.pop(key)
|
||||
|
||||
# break or items() function throws errors
|
||||
#break
|
||||
|
||||
|
||||
def multipleEnqueue(self, packet, who, but = False):
|
||||
"""
|
||||
@@ -128,7 +112,6 @@ class tokenList:
|
||||
who -- userIDs array
|
||||
but -- if True, enqueue to everyone but users in who array
|
||||
"""
|
||||
|
||||
for _, value in self.tokens.items():
|
||||
shouldEnqueue = False
|
||||
if value.userID in who and not but:
|
||||
@@ -145,22 +128,20 @@ class tokenList:
|
||||
|
||||
packet -- packet bytes to enqueue
|
||||
"""
|
||||
|
||||
for _, value in self.tokens.items():
|
||||
value.enqueue(packet)
|
||||
|
||||
def usersTimeoutCheckLoop(self, __timeoutTime = 100, __checkTime = 100):
|
||||
def usersTimeoutCheckLoop(self, timeoutTime = 100, checkTime = 100):
|
||||
"""
|
||||
Deletes all timed out users.
|
||||
If called once, will recall after __checkTime seconds and so on, forever
|
||||
If called once, will recall after checkTime seconds and so on, forever
|
||||
CALL THIS FUNCTION ONLY ONCE!
|
||||
|
||||
__timeoutTime - seconds of inactivity required to disconnect someone (Default: 100)
|
||||
__checkTime - seconds between loops (Default: 100)
|
||||
timeoutTime - seconds of inactivity required to disconnect someone (Default: 100)
|
||||
checkTime - seconds between loops (Default: 100)
|
||||
"""
|
||||
|
||||
timedOutTokens = [] # timed out users
|
||||
timeoutLimit = time.time()-__timeoutTime
|
||||
timeoutLimit = time.time()-timeoutTime
|
||||
for key, value in self.tokens.items():
|
||||
# Check timeout (fokabot is ignored)
|
||||
if value.pingTime < timeoutLimit and value.userID != 999 and value.irc == False:
|
||||
@@ -174,15 +155,13 @@ class tokenList:
|
||||
logoutEvent.handle(self.tokens[i], None)
|
||||
|
||||
# Schedule a new check (endless loop)
|
||||
threading.Timer(__checkTime, self.usersTimeoutCheckLoop, [__timeoutTime, __checkTime]).start()
|
||||
threading.Timer(checkTime, self.usersTimeoutCheckLoop, [timeoutTime, checkTime]).start()
|
||||
|
||||
def spamProtectionResetLoop(self):
|
||||
"""
|
||||
Reset spam rate every 10 seconds.
|
||||
CALL THIS FUNCTION ONLY ONCE!
|
||||
"""
|
||||
#log.debug("Resetting spam protection...")
|
||||
|
||||
# Reset spamRate for every token
|
||||
for _, value in self.tokens.items():
|
||||
value.spamRate = 0
|
||||
|
Reference in New Issue
Block a user