I knew a threaded bancho server was going to be a bad idea...

This commit is contained in:
Giuseppe Guerra 2017-12-21 18:58:56 +01:00
parent 050c1d5fe8
commit e63a85e4a4
20 changed files with 200 additions and 219 deletions

View File

@ -15,9 +15,9 @@ def handle(userToken, packetData):
matchID = userToken.matchID matchID = userToken.matchID
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
match = glob.matches.matches[matchID]
# Set slot or match mods according to modType # Set slot or match mods according to modType
with glob.matches.matches[matchID] as match:
if match.matchModMode == matchModModes.FREE_MOD: if match.matchModMode == matchModModes.FREE_MOD:
# Freemod # Freemod
# Host can set global DT/HT # Host can set global DT/HT

View File

@ -10,9 +10,7 @@ def handle(userToken, packetData):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# Get our match with glob.matches.matches[matchID] as match:
match = glob.matches.matches[matchID]
# Host check # Host check
if userToken.userID != match.hostUserID: if userToken.userID != match.hostUserID:
return return

View File

@ -21,10 +21,8 @@ def handle(userToken, packetData):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# Get match object
match = glob.matches.matches[matchID]
# Host check # Host check
with glob.matches.matches[matchID] as match:
if userToken.userID != match.hostUserID: if userToken.userID != match.hostUserID:
return return

View File

@ -8,8 +8,6 @@ def handle(userToken, packetData):
# Read packet data # Read packet data
packetData = clientPackets.changeSlot(packetData) packetData = clientPackets.changeSlot(packetData)
# Get match with glob.matches.matches[userToken.matchID] as match:
match = glob.matches.matches[userToken.matchID]
# Change slot # Change slot
match.userChangeSlot(userID, packetData["slotID"]) match.userChangeSlot(userID, packetData["slotID"])

View File

@ -20,9 +20,7 @@ def handle(userToken, packetData):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
raise exceptions.matchCreateError() raise exceptions.matchCreateError()
# Get match object with glob.matches.matches[matchID] as match:
match = glob.matches.matches[matchID]
# Join that match # Join that match
userToken.joinMatch(matchID) userToken.joinMatch(matchID)

View File

@ -17,14 +17,12 @@ def handle(userToken, packetData):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# Match exists, get object
match = glob.matches.matches[matchID]
# Hash password if needed # Hash password if needed
# if password != "": # if password != "":
# password = generalUtils.stringMd5(password) # password = generalUtils.stringMd5(password)
# Check password # Check password
with glob.matches.matches[matchID] as match:
if match.matchPassword != "" and match.matchPassword != password: if match.matchPassword != "" and match.matchPassword != password:
raise exceptions.matchWrongPasswordException() raise exceptions.matchWrongPasswordException()

View File

@ -15,8 +15,6 @@ def handle(userToken, _, has):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# The match exists, get object
match = glob.matches.matches[matchID]
# Set has beatmap/no beatmap # Set has beatmap/no beatmap
with glob.matches.matches[matchID] as match:
match.userHasBeatmap(userID, has) match.userHasBeatmap(userID, has)

View File

@ -15,8 +15,6 @@ def handle(userToken, _):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# Get match object
match = glob.matches.matches[matchID]
# Change team # Change team
with glob.matches.matches[matchID] as match:
match.changeTeam(userID) match.changeTeam(userID)

View File

@ -15,8 +15,6 @@ def handle(userToken, _):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# The match exists, get object
match = glob.matches.matches[matchID]
# Set our match complete # Set our match complete
with glob.matches.matches[matchID] as match:
match.playerCompleted(userID) match.playerCompleted(userID)

View File

@ -15,8 +15,6 @@ def handle(userToken, _):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# Match exists, get object
match = glob.matches.matches[matchID]
# Fail user # Fail user
with glob.matches.matches[matchID] as match:
match.playerFailed(userID) match.playerFailed(userID)

View File

@ -16,15 +16,13 @@ def handle(userToken, packetData):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# The match exists, get object
match = glob.matches.matches[matchID]
# Change slot id in packetData
slotID = match.getUserSlotID(userID)
# Parse the data # Parse the data
data = clientPackets.matchFrames(packetData) data = clientPackets.matchFrames(packetData)
with glob.matches.matches[matchID] as match:
# Change slot id in packetData
slotID = match.getUserSlotID(userID)
# Update the score # Update the score
match.updateScore(slotID, data["totalScore"]) match.updateScore(slotID, data["totalScore"])
match.updateHP(slotID, data["currentHp"]) match.updateHP(slotID, data["currentHp"])

View File

@ -17,8 +17,6 @@ def handle(userToken, packetData):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# Get match object
match = glob.matches.matches[matchID]
# Send invite # Send invite
with glob.matches.matches[matchID] as match:
match.invite(userID, packetData["userID"]) match.invite(userID, packetData["userID"])

View File

@ -12,8 +12,8 @@ def handle(userToken, packetData):
matchID = userToken.matchID matchID = userToken.matchID
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
match = glob.matches.matches[matchID]
with glob.matches.matches[matchID] as match:
# Host check # Host check
if userID != match.hostUserID: if userID != match.hostUserID:
return return

View File

@ -15,8 +15,6 @@ def handle(userToken, _):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# The match exists, get object
match = glob.matches.matches[matchID]
# Set our load status # Set our load status
with glob.matches.matches[matchID] as match:
match.playerLoaded(userID) match.playerLoaded(userID)

View File

@ -8,8 +8,8 @@ def handle(userToken, _):
matchID = userToken.matchID matchID = userToken.matchID
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
match = glob.matches.matches[matchID]
with glob.matches.matches[matchID] as match:
# Get our slotID and change ready status # Get our slotID and change ready status
slotID = match.getUserSlotID(userID) slotID = match.getUserSlotID(userID)
if slotID is not None: if slotID is not None:

View File

@ -15,8 +15,6 @@ def handle(userToken, _):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# The match exists, get object
match = glob.matches.matches[matchID]
# Skip # Skip
with glob.matches.matches[matchID] as match:
match.playerSkip(userID) match.playerSkip(userID)

View File

@ -13,9 +13,7 @@ def handle(userToken, _):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# The match exists, get object with glob.matches.matches[matchID] as match:
match = glob.matches.matches[matchID]
# Host check # Host check
if userToken.userID != match.hostUserID: if userToken.userID != match.hostUserID:
return return

View File

@ -16,10 +16,8 @@ def handle(userToken, packetData):
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:
return return
# Match exists, get object
match = glob.matches.matches[matchID]
# Host check # Host check
with glob.matches.matches[matchID] as match:
if userToken.userID != match.hostUserID: if userToken.userID != match.hostUserID:
return return

View File

@ -6,4 +6,5 @@ def handle(userToken, packetData):
matchID = packetData["matchID"] matchID = packetData["matchID"]
if matchID not in glob.matches.matches or not userToken.tournament: if matchID not in glob.matches.matches or not userToken.tournament:
return return
userToken.enqueue(glob.matches.matches[matchID].matchDataCache) with glob.matches.matches[matchID] as m:
userToken.enqueue(m.matchDataCache)

View File

@ -1,5 +1,6 @@
import copy import copy
import json import json
import threading
from common.log import logUtils as log from common.log import logUtils as log
from constants import dataTypes from constants import dataTypes
from constants import matchModModes from constants import matchModModes
@ -60,6 +61,7 @@ class match:
self.isTourney = isTourney self.isTourney = isTourney
self.isLocked = False # if True, users can't change slots/teams. Used in tourney matches self.isLocked = False # if True, users can't change slots/teams. Used in tourney matches
self.isStarting = False self.isStarting = False
self._lock = threading.Lock()
# Create all slots and reset them # Create all slots and reset them
self.slots = [] self.slots = []
@ -83,55 +85,55 @@ class match:
""" """
# General match info # General match info
# TODO: Test without safe copy, the error might have been caused by outdated python bytecode cache # TODO: Test without safe copy, the error might have been caused by outdated python bytecode cache
safeMatch = copy.deepcopy(self) # safeMatch = copy.deepcopy(self)
struct = [ struct = [
[safeMatch.matchID, dataTypes.UINT16], [self.matchID, dataTypes.UINT16],
[int(safeMatch.inProgress), dataTypes.BYTE], [int(self.inProgress), dataTypes.BYTE],
[0, dataTypes.BYTE], [0, dataTypes.BYTE],
[safeMatch.mods, dataTypes.UINT32], [self.mods, dataTypes.UINT32],
[safeMatch.matchName, dataTypes.STRING] [self.matchName, dataTypes.STRING]
] ]
if censored and safeMatch.matchPassword: if censored and self.matchPassword:
struct.append(["redacted", dataTypes.STRING]) struct.append(["redacted", dataTypes.STRING])
else: else:
struct.append([safeMatch.matchPassword, dataTypes.STRING]) struct.append([self.matchPassword, dataTypes.STRING])
struct.extend([ struct.extend([
[safeMatch.beatmapName, dataTypes.STRING], [self.beatmapName, dataTypes.STRING],
[safeMatch.beatmapID, dataTypes.UINT32], [self.beatmapID, dataTypes.UINT32],
[safeMatch.beatmapMD5, dataTypes.STRING] [self.beatmapMD5, dataTypes.STRING]
]) ])
# Slots status IDs, always 16 elements # Slots status IDs, always 16 elements
for i in range(0,16): for i in range(0,16):
struct.append([safeMatch.slots[i].status, dataTypes.BYTE]) struct.append([self.slots[i].status, dataTypes.BYTE])
# Slot teams, always 16 elements # Slot teams, always 16 elements
for i in range(0,16): for i in range(0,16):
struct.append([safeMatch.slots[i].team, dataTypes.BYTE]) struct.append([self.slots[i].team, dataTypes.BYTE])
# Slot user ID. Write only if slot is occupied # Slot user ID. Write only if slot is occupied
for i in range(0,16): for i in range(0,16):
if safeMatch.slots[i].user is not None and safeMatch.slots[i].user in glob.tokens.tokens: if self.slots[i].user is not None and self.slots[i].user in glob.tokens.tokens:
struct.append([glob.tokens.tokens[safeMatch.slots[i].user].userID, dataTypes.UINT32]) struct.append([glob.tokens.tokens[self.slots[i].user].userID, dataTypes.UINT32])
# Other match data # Other match data
struct.extend([ struct.extend([
[safeMatch.hostUserID, dataTypes.SINT32], [self.hostUserID, dataTypes.SINT32],
[safeMatch.gameMode, dataTypes.BYTE], [self.gameMode, dataTypes.BYTE],
[safeMatch.matchScoringType, dataTypes.BYTE], [self.matchScoringType, dataTypes.BYTE],
[safeMatch.matchTeamType, dataTypes.BYTE], [self.matchTeamType, dataTypes.BYTE],
[safeMatch.matchModMode, dataTypes.BYTE], [self.matchModMode, dataTypes.BYTE],
]) ])
# Slot mods if free mod is enabled # Slot mods if free mod is enabled
if safeMatch.matchModMode == matchModModes.FREE_MOD: if self.matchModMode == matchModModes.FREE_MOD:
for i in range(0,16): for i in range(0,16):
struct.append([safeMatch.slots[i].mods, dataTypes.UINT32]) struct.append([self.slots[i].mods, dataTypes.UINT32])
# Seed idk # Seed idk
# TODO: Implement this, it should be used for mania "random" mod # TODO: Implement this, it should be used for mania "random" mod
struct.append([safeMatch.seed, dataTypes.UINT32]) struct.append([self.seed, dataTypes.UINT32])
return struct return struct
@ -854,3 +856,11 @@ class match:
message = "The match is now empty." message = "The match is now empty."
chat.sendMessage("FokaBot", chanName, message) chat.sendMessage("FokaBot", chanName, message)
def __enter__(self):
# 🌚🌚🌚🌚🌚
self._lock.acquire()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self._lock.release()