mirror of
https://github.com/wolfswolke/DeathGarden_API_Rebirth.git
synced 2026-03-21 17:54:09 -05:00
Reworked JOIN and HOST lobby function for private matches. Also fixed a dumb bug that i when a privat lobby existed said "oh im not in that lemme ERROR"
743 lines
40 KiB
Python
743 lines
40 KiB
Python
import hashlib
|
|
import os
|
|
import threading
|
|
import uuid
|
|
import random
|
|
from collections import Counter
|
|
from logic.time_handler import get_time
|
|
from logic.logging_handler import logger
|
|
from logic.mongodb_handler import mongo
|
|
|
|
mirrors_match_status = ["None", "NoMatch", "Created", "Creating", "DelayedCreation", "Opened", "Completed", "Timedout",
|
|
"Closing", "Closed", "Killing", "Killed", "Destroyed"]
|
|
|
|
max_b_count_dev = 1
|
|
max_b_count_prod = 5
|
|
|
|
|
|
def random_game_mode(match_config=None, hash_of_map=None):
|
|
if match_config:
|
|
md5 = hashlib.md5(match_config.encode('utf-8')).hexdigest()
|
|
return {'gameMode': f'{md5}-Default',
|
|
'MatchConfiguration': match_config}
|
|
|
|
MatchConfig_SLU_DownTown = {"gameMode": "4b4bbb82b85e662e5121233ae06f9b1c-Default",
|
|
"MatchConfiguration": "/Game/Configuration/MatchConfig/MatchConfig_SLU_DownTown.MatchConfig_SLU_DownTown"} # broken
|
|
|
|
MatchConfig_Demo_HarvestYourExit_1v5 = {"gameMode": "789c81dfb11fe39b7247c7e488e5b0d4-Default",
|
|
"MatchConfiguration": "/Game/Configuration/MatchConfig/MatchConfig_Demo_HarvestYourExit_1v5.MatchConfig_Demo_HarvestYourExit_1v5"}
|
|
MatchConfig_Demo = {"gameMode": "08d2279d2ed3fba559918aaa08a73fa8-Default",
|
|
"MatchConfiguration": "/Game/Configuration/MatchConfig/MatchConfig_Demo.MatchConfig_Demo"}
|
|
MatchConfig_ARC_Fortress = {'gameMode': 'd071fb6678668246d6d999c9892c2a60-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_ARC_Fortress.MatchConfig_ARC_Fortress'}
|
|
|
|
MatchConfig_ARC_BlastFurnace = {'gameMode': '4cb782397d46fc432d10bdc24538097a-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_ARC_BlastFurnace.MatchConfig_ARC_BlastFurnace'}
|
|
MatchConfig_ARC_BlastFurnace_2Hunters = {'gameMode': '1760f0a98f85cf53b6011b322cad1586-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_ARC_BlastFurnace_2Hunters.MatchConfig_ARC_BlastFurnace_2Hunters'}
|
|
MatchConfig_ARC_Expedition = {'gameMode': '3d9c3d09116d982ec7d631ae38e4628b-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_ARC_Expedition.MatchConfig_ARC_Expedition'}
|
|
MatchConfig_ARC_Expedition_2Hunters = {'gameMode': 'a79946d18164f1b8b8589c81778ab15e-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_ARC_Expedition_2Hunters.MatchConfig_ARC_Expedition_2Hunters'}
|
|
MatchConfig_ARC_ScrapYard = {'gameMode': 'd4e84bc42020d2daa92cf141b5f545b4-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_ARC_ScrapYard.MatchConfig_ARC_ScrapYard'}
|
|
MatchConfig_ARC_ScrapYard_2Hunters = {'gameMode': 'cd9986d916859aa8e1ec4c5bac41d0e8-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_ARC_ScrapYard_2Hunters.MatchConfig_ARC_ScrapYard_2Hunters'}
|
|
MatchConfig_CAV_All = {'gameMode': 'fac37036b5799852e499ce02dd716914-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_CAV_All.MatchConfig_CAV_All'} # Broken
|
|
MatchConfig_CAV_All_2Hunters = {'gameMode': '3f1052dc0058bf795ad24f4d292b57f9-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_CAV_All_2Hunters.MatchConfig_CAV_All_2Hunters'}
|
|
MatchConfig_Custom = {'gameMode': '401cc719864f3e7dade5291ea1399469-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_Custom.MatchConfig_Custom'}
|
|
MatchConfig_CustomMatch = {'gameMode': 'e3744bb4acbc0e5dc107e999c6132f18-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_CustomMatch.MatchConfig_CustomMatch'} # Broken
|
|
MatchConfig_Demo_2v10_4Needles = {'gameMode': 'b844f2e112df38cb1696c10012aa2976-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_Demo_2v10_4Needles.MatchConfig_Demo_2v10_4Needles'}
|
|
MatchConfig_Demo_2v10_5Needles = {'gameMode': '5ecd49c3b64a089717e0e604bd32a76a-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_Demo_2v10_5Needles.MatchConfig_Demo_2v10_5Needles'}
|
|
MatchConfig_Demo_2v8_4Needles = {'gameMode': 'fe29231c7bdcc6e2bc4d1891e8b9decd-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_Demo_2v8_4Needles.MatchConfig_Demo_2v8_4Needles'}
|
|
MatchConfig_Demo_2v8_5Needles = {'gameMode': 'cfe80d8e2d9a5d1aefeac4ac5d2de3ac-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_Demo_2v8_5Needles.MatchConfig_Demo_2v8_5Needles'}
|
|
MatchConfig_Demo_HarvestYourExit = {'gameMode': 'd4f962f287d04cb6fd266ac2b2e7705e-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_Demo_HarvestYourExit.MatchConfig_Demo_HarvestYourExit'}
|
|
|
|
MatchConfig_DES_City = {'gameMode': 'b05564a0712a62ebe5dd2228333c9237-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_City.MatchConfig_DES_City'}
|
|
MatchConfig_DES_City_2Hunters = {'gameMode': 'a0fdf9ce92261dcc5492f353b62f34f3-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_City_2Hunters.MatchConfig_DES_City_2Hunters'} # Broken
|
|
MatchConfig_DES_Fortress = {'gameMode': 'b63232e2c852823ac87bae2367edf875-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_Fortress.MatchConfig_DES_Fortress'}
|
|
MatchConfig_DES_Fortress_2Hunters = {'gameMode': 'e3b6d0d277c8f36dffc0bb9f51e057c0-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_Fortress_2Hunters.MatchConfig_DES_Fortress_2Hunters'}
|
|
MatchConfig_DES_GoldRush = {'gameMode': '4b12293b22fdef0a6d2f2b21a79fa9b1-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_GoldRush.MatchConfig_DES_GoldRush'}
|
|
MatchConfig_DES_GoldRush_2v10_5Needles = {'gameMode': '1a80bd0f2cec80a7a18ae6f605de788b-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_GoldRush_2v10_5Needles.MatchConfig_DES_GoldRush_2v10_5Needles'}
|
|
MatchConfig_DES_Mayan = {'gameMode': '86006559cbf3f749a73c7095f06c566c-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_Mayan.MatchConfig_DES_Mayan'}
|
|
MatchConfig_DES_Mayan_2v10_5Needles = {'gameMode': '4e2d42e4448ea91914a67b60487b691f-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_Mayan_2v10_5Needles.MatchConfig_DES_Mayan_2v10_5Needles'}
|
|
MatchConfig_DES_Oilfield = {'gameMode': '7fcd68d7493bf41e57c1b9b68502a43d-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_Oilfield.MatchConfig_DES_Oilfield'}
|
|
MatchConfig_DES_Oilfield_2Hunters = {'gameMode': '06dffbe8772084ece87a6c73eaf48df8-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_DES_Oilfield_2Hunters.MatchConfig_DES_Oilfield_2Hunters'}
|
|
MatchConfig_JUN_Fortress = {'gameMode': 'b32306ecddb7a60fbbb91a872d4f15fe-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_JUN_Fortress.MatchConfig_JUN_Fortress'}
|
|
MatchConfig_JUN_Fortress_2Hunters = {'gameMode': '23eea0d20f661b516666d1151aad8718-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_JUN_Fortress_2Hunters.MatchConfig_JUN_Fortress_2Hunters'}
|
|
MatchConfig_NewMaps = {'gameMode': 'ad4d7af5763ab472800abbe73f7d2740-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_NewMaps.MatchConfig_NewMaps'}
|
|
MatchConfig_PRM_Special = {'gameMode': 'bdf7473d4b23baae7e13a6c2c46c5094-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_PRM_Special.MatchConfig_PRM_Special'}
|
|
MatchConfig_RUI_All = {'gameMode': '027b541cfcaa4ab088dab234a02e81d3-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_RUI_All.MatchConfig_RUI_All'}
|
|
MatchConfig_RUI_All_2Hunters = {'gameMode': 'de1bb601c3dab35e896d0366da563445-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_RUI_All_2Hunters.MatchConfig_RUI_All_2Hunters'}
|
|
MatchConfig_WA_Cemetery = {'gameMode': '9af69a666badf6b443628f7f80c58445-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_WA_Cemetery.MatchConfig_WA_Cemetery'}
|
|
MatchConfig_WA_Cemetery_2Hunters = {'gameMode': '59f81208123d114050207c04d1e9af3f-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_WA_Cemetery_2Hunters.MatchConfig_WA_Cemetery_2Hunters'}
|
|
MatchConfig_WA_Rivers = {'gameMode': '33cbc6d506de6c85a5eead04f5a57c92-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_WA_Rivers.MatchConfig_WA_Rivers'}
|
|
MatchConfig_WA_Rivers_2Hunters = {'gameMode': 'feac811fdef1d1a2f2fc26b3c99205fd-Default',
|
|
'MatchConfiguration': '/Game/Configuration/MatchConfig/MatchConfig_WA_Rivers_2Hunters.MatchConfig_WA_Rivers_2Hunters'}
|
|
|
|
all_maps = [MatchConfig_SLU_DownTown, MatchConfig_Demo_HarvestYourExit_1v5, MatchConfig_Demo,
|
|
MatchConfig_ARC_Fortress, MatchConfig_ARC_BlastFurnace, MatchConfig_ARC_BlastFurnace_2Hunters,
|
|
MatchConfig_ARC_Expedition, MatchConfig_ARC_Expedition_2Hunters, MatchConfig_ARC_ScrapYard,
|
|
MatchConfig_ARC_ScrapYard_2Hunters, MatchConfig_CAV_All, MatchConfig_CAV_All_2Hunters,
|
|
MatchConfig_Custom, MatchConfig_CustomMatch, MatchConfig_Demo_2v10_4Needles,
|
|
MatchConfig_Demo_2v10_5Needles, MatchConfig_Demo_2v8_4Needles, MatchConfig_Demo_2v8_5Needles,
|
|
MatchConfig_Demo_HarvestYourExit, MatchConfig_DES_City, MatchConfig_DES_City_2Hunters,
|
|
MatchConfig_DES_Fortress, MatchConfig_DES_Fortress_2Hunters, MatchConfig_DES_GoldRush,
|
|
MatchConfig_DES_GoldRush_2v10_5Needles, MatchConfig_DES_Mayan, MatchConfig_DES_Mayan_2v10_5Needles,
|
|
MatchConfig_DES_Oilfield, MatchConfig_DES_Oilfield_2Hunters, MatchConfig_JUN_Fortress,
|
|
MatchConfig_JUN_Fortress_2Hunters, MatchConfig_NewMaps, MatchConfig_PRM_Special,
|
|
MatchConfig_RUI_All, MatchConfig_RUI_All_2Hunters, MatchConfig_WA_Cemetery,
|
|
MatchConfig_WA_Cemetery_2Hunters, MatchConfig_WA_Rivers, MatchConfig_WA_Rivers_2Hunters]
|
|
|
|
if hash_of_map != "Default":
|
|
for MatchConfig in all_maps:
|
|
if MatchConfig['gameMode'] == hash_of_map:
|
|
return MatchConfig
|
|
|
|
high_probability = [MatchConfig_DES_GoldRush, MatchConfig_WA_Rivers, MatchConfig_ARC_BlastFurnace] * 3
|
|
normal_probability = [MatchConfig_WA_Cemetery, MatchConfig_ARC_Expedition, MatchConfig_JUN_Fortress] * 2
|
|
low_probability = [MatchConfig_DES_Fortress, MatchConfig_DES_Mayan]
|
|
probability_list = high_probability + normal_probability + low_probability
|
|
return random.choice(probability_list)
|
|
|
|
|
|
class QueueData:
|
|
def __init__(self, side):
|
|
self.side = side
|
|
|
|
|
|
class Session:
|
|
def __init__(self, userid, clientIds):
|
|
self.userid = userid
|
|
self.clientIds = clientIds
|
|
|
|
|
|
class QueuedPlayer:
|
|
def __init__(self, userId, side, lastCheckedForMatch):
|
|
self.userId = userId
|
|
self.side = side
|
|
self.lastCheckedForMatch = lastCheckedForMatch
|
|
|
|
def __repr__(self):
|
|
return f"QueuedPlayer(userId={self.userId}, side={self.side}, lastCheckedForMatch={self.lastCheckedForMatch})"
|
|
|
|
|
|
class Lobby:
|
|
def __init__(self, isReady, host, nonHosts, id, isPrepared, hasStarted, status, MatchConfig, last_host_check,
|
|
version=None, is_private=False, max_a_count=1, max_b_count=5, private_players=None):
|
|
self.isReady = isReady
|
|
self.host = host
|
|
self.nonHosts = nonHosts
|
|
self.id = id
|
|
self.isPrepared = isPrepared
|
|
self.hasStarted = hasStarted
|
|
self.status = status
|
|
self.matchConfig = MatchConfig
|
|
self.last_host_check = last_host_check
|
|
self.is_private = is_private
|
|
self.version = version
|
|
self.max_a_count = max_a_count
|
|
self.max_b_count = max_b_count
|
|
self.private_players = private_players
|
|
|
|
|
|
class KilledLobby:
|
|
def __init__(self, id, reason, killedTime, lobby):
|
|
self.id = id
|
|
self.reason = reason
|
|
self.killedTime = killedTime
|
|
self.lobby = lobby
|
|
|
|
|
|
class MatchmakingQueue:
|
|
def __init__(self):
|
|
self.openLobbies = []
|
|
self.killedLobbies = []
|
|
self.queuedPlayers = []
|
|
self.matchmaking_lock = threading.Lock()
|
|
|
|
def cleanup_queue_players(self):
|
|
for i, player in enumerate(self.queuedPlayers):
|
|
if player.lastCheckedForMatch < get_time()[0] - 15:
|
|
self.queuedPlayers.pop(i)
|
|
logger.graylog_logger(level="info", handler="cleanup_queue_players",
|
|
message="Removed player from queue due to timeout.")
|
|
|
|
def queuePlayer(self, side, userId):
|
|
self.cleanup_queue_players()
|
|
try:
|
|
# Check if user is owner of broken lobby
|
|
for openLobby in self.openLobbies:
|
|
if openLobby.host == userId:
|
|
if openLobby.is_private:
|
|
continue
|
|
if not openLobby.hasStarted or not openLobby.status == "CLOSED":
|
|
self.openLobbies.pop(self.openLobbies.index(openLobby))
|
|
logger.graylog_logger(level="info", handler="matchmaking_queuePlayer",
|
|
message="Killed broken lobby from queuePlayer")
|
|
current_timestamp, expiration_timestamp = get_time()
|
|
|
|
# check if user is already in queue
|
|
if userId in [player.userId for player in self.queuedPlayers]:
|
|
return
|
|
queued_player = QueuedPlayer(userId, side,
|
|
current_timestamp)
|
|
if userId in [player.userId for player in self.queuedPlayers]:
|
|
return
|
|
logger.graylog_logger(level="debug", handler="matchmaking_queuePlayer", message=f"Queued Player {userId}")
|
|
self.queuedPlayers.append(queued_player)
|
|
except Exception as e:
|
|
logger.graylog_logger(level="error", handler="matchmaking_queuePlayer", message=e)
|
|
|
|
def getQueuedPlayer(self, userid):
|
|
try:
|
|
for i, queuedPlayer in enumerate(self.queuedPlayers):
|
|
if queuedPlayer.userId == userid:
|
|
return queuedPlayer, i
|
|
return None, -1
|
|
except Exception as e:
|
|
logger.graylog_logger(level="error", handler="matchmaking_getQueuedPlayer", message=e)
|
|
return None
|
|
|
|
def getQueueStatus(self, side, userId, region, additional_user_ids=None, game_mode=None, version=None):
|
|
|
|
try:
|
|
eta_data = {
|
|
"queueData": {
|
|
"ETA": -10000,
|
|
"position": 0,
|
|
"sizeA": 0,
|
|
"sizeB": 1
|
|
},
|
|
"status": "QUEUED"
|
|
}
|
|
|
|
self.cleanup_queue_players()
|
|
for player in self.queuedPlayers:
|
|
if player.userId == userId:
|
|
player.lastCheckedForMatch = get_time()[0]
|
|
|
|
queuedPlayer, index = self.getQueuedPlayer(userId)
|
|
if not queuedPlayer:
|
|
return {}
|
|
if not version:
|
|
return {}
|
|
|
|
if os.environ['DEV'] == "true":
|
|
max_players_b = max_b_count_dev
|
|
else:
|
|
max_players_b = max_b_count_prod
|
|
for openLobby in self.openLobbies:
|
|
if openLobby.version:
|
|
if openLobby.version != version:
|
|
continue
|
|
if openLobby.is_private:
|
|
is_non_host = False
|
|
if openLobby.private_players:
|
|
for user in openLobby.private_players:
|
|
if userId == user:
|
|
is_non_host = True
|
|
if is_non_host:
|
|
ret = mongo.write_data_with_list(userId, login_steam=False,
|
|
items_dict={"last_played_faction": "Runner"})
|
|
if ret:
|
|
# remove player from openLobby.private_players
|
|
openLobby.private_players.pop(openLobby.private_players.index(userId))
|
|
openLobby.nonHosts.append(queuedPlayer)
|
|
# creatorId, matchId, joinerId=None, region=None, matchConfig=None,
|
|
# SessionSettings=None, PrivateMatch=False, countA=1, countB=5
|
|
data = self.createQueueResponseMatched(creatorId=openLobby.host, matchId=openLobby.id,
|
|
joinerId=userId, matchConfig=openLobby.matchConfig,
|
|
SessionSettings=openLobby.SessionSettings, PrivateMatch=True,
|
|
countB=openLobby.max_b_count, countA=openLobby.max_a_count)
|
|
self.queuedPlayers.pop(index)
|
|
return data
|
|
else:
|
|
logger.graylog_logger(level="error", handler="matchmaking_getQueueStatus",
|
|
message="Failed to set last_played_faction to Runner")
|
|
return eta_data
|
|
elif userId == openLobby.host:
|
|
ret = mongo.write_data_with_list(userId, login_steam=False,
|
|
items_dict={"last_played_faction": "Hunter"})
|
|
if ret:
|
|
data = self.createQueueResponseMatched(openLobby.host, openLobby.id,
|
|
matchConfig=openLobby.matchConfig, PrivateMatch=True,
|
|
countB=openLobby.max_b_count,
|
|
countA=openLobby.max_a_count)
|
|
self.queuedPlayers.pop(index)
|
|
return data
|
|
else:
|
|
logger.graylog_logger(level="error", handler="matchmaking_getQueueStatus",
|
|
message="Failed to set last_played_faction to Hunter")
|
|
return eta_data
|
|
# Status Outside is EQueueStatus
|
|
# None
|
|
# PendingOnline
|
|
# Online
|
|
# PendingWarparty
|
|
# Queued
|
|
# Matched
|
|
# Failed
|
|
# ServerFull
|
|
# FriendNotPlaying
|
|
# WarpartyFull
|
|
|
|
# Status inside is EMirrorsMatchStatus
|
|
|
|
|
|
# enum class EPlatform : uint8 {
|
|
# None,
|
|
# Windows,
|
|
# XboxOne,
|
|
# Ps4,
|
|
# };
|
|
# Funny thing. There is Platform and Platforms
|
|
# enum class EPlatforms : uint8 {
|
|
# None,
|
|
# Steam,
|
|
# Xbox1,
|
|
# PS4,
|
|
# Dev,
|
|
# };
|
|
else:
|
|
# Player not in that private lobby
|
|
continue
|
|
else:
|
|
continue
|
|
|
|
if side == 'B':
|
|
if self.openLobbies:
|
|
for openLobby in self.openLobbies:
|
|
if not openLobby.status == "CLOSED":
|
|
if openLobby.last_host_check < get_time()[0] - 15:
|
|
self.openLobbies.pop(self.openLobbies.index(openLobby))
|
|
logger.graylog_logger(level="info", handler="matchmaking_getQueueStatus",
|
|
message="Lobby killed due to host not checking in")
|
|
return eta_data
|
|
if openLobby.host == userId:
|
|
if openLobby.is_private:
|
|
logger.graylog_logger(level="debug", handler="matchmaking_getQueueStatus",
|
|
message="Lobby is private CHECK 1")
|
|
continue
|
|
logger.graylog_logger(level="info", handler="matchmaking_getQueueStatus",
|
|
message=f"Kill lobby due to host not checking in: {openLobby.id}"
|
|
f", index: {index}, val: "
|
|
f"{self.openLobbies.index(openLobby)}")
|
|
self.openLobbies.pop(self.openLobbies.index(openLobby))
|
|
logger.graylog_logger(level="info", handler="matchmaking_getQueueStatus",
|
|
message="Killed broken lobby Host on Side RUNNER.")
|
|
return eta_data
|
|
for openLobby in self.openLobbies:
|
|
if not openLobby.isReady or openLobby.hasStarted or openLobby.status == "CLOSED" or openLobby.status == "KILLED":
|
|
continue
|
|
if openLobby.version != version:
|
|
continue
|
|
# Private match logic
|
|
if openLobby.is_private:
|
|
logger.graylog_logger(level="debug", handler="matchmaking_getQueueStatus",
|
|
message="Lobby is private")
|
|
if userId in openLobby.nonHosts or userId == openLobby.host:
|
|
data = self.createQueueResponseMatched(openLobby.host, openLobby.id, userId,
|
|
matchConfig=openLobby.matchConfig,
|
|
SessionSettings=openLobby.SessionSettings, PrivateMatch=False)
|
|
self.queuedPlayers.pop(index)
|
|
return data
|
|
else:
|
|
continue
|
|
else:
|
|
logger.graylog_logger(level="debug", handler="matchmaking_getQueueStatus",
|
|
message="Lobby is NOT private")
|
|
|
|
if userId in openLobby.nonHosts:
|
|
data = self.createQueueResponseMatched(openLobby.host, openLobby.id, userId,
|
|
matchConfig=openLobby.matchConfig,
|
|
SessionSettings=openLobby.SessionSettings)
|
|
self.queuedPlayers.pop(index)
|
|
return data
|
|
if len(openLobby.nonHosts) < max_players_b:
|
|
logger.graylog_logger(level="debug", handler="matchmaking_getQueueStatus",
|
|
message=f"Len is {len(openLobby.nonHosts)}")
|
|
if additional_user_ids:
|
|
with self.matchmaking_lock:
|
|
open_slots = max_players_b - len(openLobby.nonHosts)
|
|
queued_player_count = 1 + len(additional_user_ids)
|
|
if queued_player_count <= open_slots:
|
|
for user_id in additional_user_ids:
|
|
if user_id not in openLobby.nonHosts:
|
|
openLobby.nonHosts.append(user_id)
|
|
additional_queuedPlayer, additional_index = self.getQueuedPlayer(
|
|
user_id)
|
|
self.queuedPlayers.pop(additional_index)
|
|
else:
|
|
continue
|
|
openLobby.nonHosts.append(queuedPlayer)
|
|
self.queuedPlayers.pop(index)
|
|
data = self.createQueueResponseMatched(openLobby.host, openLobby.id, userId,
|
|
matchConfig=openLobby.matchConfig,
|
|
SessionSettings=openLobby.SessionSettings)
|
|
if data:
|
|
return data
|
|
else:
|
|
return eta_data
|
|
else:
|
|
logger.graylog_logger(level="debug", handler="matchmaking_getQueueStatus",
|
|
message=f"Len Non Hosts >= 3 for {openLobby.id}")
|
|
return eta_data
|
|
logger.graylog_logger(level="debug", handler="matchmaking_getQueueStatus",
|
|
message="No Open Lobbies fit the criteria.")
|
|
return eta_data
|
|
|
|
else:
|
|
return eta_data
|
|
else:
|
|
if self.openLobbies:
|
|
for openLobby in self.openLobbies:
|
|
if openLobby.version != version:
|
|
continue
|
|
if openLobby.is_private:
|
|
if userId == openLobby.host:
|
|
data = self.createQueueResponseMatched(openLobby.host, openLobby.id, userId,
|
|
matchConfig=openLobby.matchConfig,
|
|
SessionSettings=openLobby.SessionSettings)
|
|
self.queuedPlayers.pop(index)
|
|
return data
|
|
else:
|
|
continue
|
|
if openLobby.host == userId:
|
|
self.openLobbies.pop(self.openLobbies.index(openLobby))
|
|
logger.graylog_logger(level="info", handler="matchmaking_getQueueStatus",
|
|
message="Killed broken lobby")
|
|
matchId = self.genMatchUUID()
|
|
if game_mode:
|
|
Match_Config = random_game_mode(hash_of_map=game_mode)
|
|
else:
|
|
Match_Config = random_game_mode()
|
|
current_time = get_time()[0]
|
|
lobby = Lobby(isReady=False, host=queuedPlayer, nonHosts=[], id=matchId, isPrepared=False,
|
|
hasStarted=False, status="OPENED", MatchConfig=Match_Config,
|
|
last_host_check=current_time, is_private=False, version=version)
|
|
self.openLobbies.append(lobby)
|
|
self.queuedPlayers.pop(index)
|
|
return self.createQueueResponseMatched(userId, matchId, region=region, matchConfig=Match_Config)
|
|
except Exception as e:
|
|
logger.graylog_logger(level="error", handler="matchmaking_getQueueStatus", message=e)
|
|
return None
|
|
|
|
def removePlayerFromQueue(self, userid):
|
|
_, index = self.getQueuedPlayer(userid)
|
|
if index != -1:
|
|
self.queuedPlayers.pop(index)
|
|
|
|
def remove_player_from_match(self, matchId, userId):
|
|
try:
|
|
lobby, _ = self.getLobbyById(matchId)
|
|
if lobby:
|
|
for i, player in enumerate(lobby.nonHosts):
|
|
if player.userId == userId:
|
|
lobby.nonHosts.pop(i)
|
|
break
|
|
return {"status": "success"}
|
|
except Exception as e:
|
|
logger.graylog_logger(level="error", handler="remove_player_from_match", message=e)
|
|
return {"status": "error"}
|
|
|
|
def getLobbyById(self, id):
|
|
for i, lobby in enumerate(self.openLobbies):
|
|
if lobby.id == id:
|
|
return lobby, i
|
|
return None, -1
|
|
|
|
def getKilledLobbyById(self, id):
|
|
for killedLobby in self.killedLobbies:
|
|
if killedLobby.id == id:
|
|
return killedLobby
|
|
return None
|
|
|
|
def register_private_match(self, len_a_hunter, len_b_runner, match_config, host):
|
|
# check if already hosting:
|
|
for openLobby in self.openLobbies:
|
|
if openLobby.host == host:
|
|
return None
|
|
match_id = self.genMatchUUID()
|
|
current_time = get_time()[0] + 5 * 60 * 1000
|
|
Match_Config = random_game_mode(match_config)
|
|
queuedPlayers = []
|
|
logger.graylog_logger(level="debug", handler="register_private_match",
|
|
message=f"Match Config: {Match_Config} with {len_a_hunter} and {len_b_runner}")
|
|
lobby = Lobby(isReady=False, host=host, nonHosts=queuedPlayers, id=match_id, isPrepared=False,
|
|
hasStarted=False, status="OPENED", MatchConfig=Match_Config, last_host_check=current_time,
|
|
is_private=True, max_a_count=len_a_hunter, max_b_count=len_b_runner, private_players=[])
|
|
self.openLobbies.append(lobby)
|
|
return match_id
|
|
|
|
def join_private_match(self, match_id, user_id):
|
|
lobby, _ = self.getLobbyById(match_id)
|
|
if lobby:
|
|
if lobby.is_private:
|
|
if user_id == lobby.host:
|
|
return {"status": "ERROR", "message": "Host cannot be a runner in their own match."}, 400
|
|
if len(lobby.nonHosts) < lobby.max_b_count:
|
|
# private_players + user_id
|
|
if user_id not in lobby.private_players:
|
|
lobby.private_players.append(user_id)
|
|
return {"status": "OK", "message": "User added to private match."}, 200
|
|
else:
|
|
return {"status": "ERROR", "message": "User already in private match."}, 400
|
|
else:
|
|
return {"status": "ERROR", "message": "Private match is full."}, 400
|
|
else:
|
|
return {"status": "ERROR", "message": "Match is not private."}, 400
|
|
else:
|
|
return {"status": "ERROR", "message": "Match not found."}, 400
|
|
|
|
def registerMatch(self, matchId, sessionSettings, userId):
|
|
lobby, _ = self.getLobbyById(matchId)
|
|
if lobby:
|
|
lobby.host = userId
|
|
lobby.isReady = True
|
|
lobby.SessionSettings = sessionSettings
|
|
return self.createMatchResponse(matchId=matchId, userId=userId)
|
|
|
|
def closeMatch(self, matchId):
|
|
lobby, _ = self.getLobbyById(matchId)
|
|
if lobby:
|
|
lobby.status = "CLOSED"
|
|
return self.createMatchResponse(matchId=matchId)
|
|
|
|
def deleteMatch(self, matchId):
|
|
lobby, index = self.getLobbyById(matchId)
|
|
if lobby:
|
|
self.openLobbies.pop(index)
|
|
current_timestamp, expiration_timestamp = get_time()
|
|
killedLobby = KilledLobby(lobby.id, "killed_by_host", current_timestamp, lobby=lobby)
|
|
self.killedLobbies.append(killedLobby)
|
|
|
|
def isOwner(self, matchId, userid):
|
|
lobby, _ = self.getLobbyById(matchId)
|
|
return lobby and lobby.host == userid
|
|
|
|
def deleteOldMatches(self):
|
|
current_time = get_time()
|
|
for i in range(len(self.killedLobbies) - 1, -1, -1):
|
|
if self.killedLobbies[i].killedTime < current_time - 5 * 60 * 1000:
|
|
self.killedLobbies.pop(i)
|
|
|
|
def createMatchResponse(self, matchId, killed=None, userId=None):
|
|
try:
|
|
lobby_temp, id_temp = self.getLobbyById(matchId)
|
|
if lobby_temp is None:
|
|
logger.graylog_logger(level="debug", handler="createMatchResponse",
|
|
message="Returning NONE in lobby_temp because TEMP none.")
|
|
return
|
|
if lobby_temp.host == userId:
|
|
# lobby.last_host_check = get_time()[0] + 3
|
|
self.openLobbies[id_temp].last_host_check = get_time()[0] + 3
|
|
lobby, id = self.getLobbyById(matchId)
|
|
if not lobby:
|
|
lobby = self.getKilledLobbyById(matchId)
|
|
|
|
if killed:
|
|
lobby.status = "KILLED"
|
|
current_timestamp, expiration_timestamp = get_time()
|
|
if not lobby.isReady or lobby.hasStarted or lobby.status == "CLOSED":
|
|
if lobby.last_host_check < get_time()[0] - 15:
|
|
self.openLobbies.pop(self.openLobbies.index(lobby))
|
|
logger.graylog_logger(level="info", handler="matchmaking_createMatchResponse",
|
|
message="Lobby killed due to host not checking in, Returning NONE")
|
|
return
|
|
host = lobby.host
|
|
if type(host) == QueuedPlayer:
|
|
host = host.userId
|
|
non_host = []
|
|
for item in lobby.nonHosts:
|
|
if type(item) == QueuedPlayer:
|
|
non_host.append(item.userId)
|
|
else:
|
|
non_host.append(item)
|
|
try:
|
|
SessionSettings = lobby.SessionSettings
|
|
except:
|
|
SessionSettings = ""
|
|
gameMode = lobby.matchConfig["gameMode"]
|
|
#if os.environ['DEV'] == "true":
|
|
# count_a = 1
|
|
# count_b = max_b_count_dev
|
|
#else:
|
|
count_a = lobby.max_a_count
|
|
count_b = lobby.max_b_count
|
|
MatchConfiguration = lobby.matchConfig["MatchConfiguration"]
|
|
if host == "147d48b8-6c71-456c-8c72-8d75cff31c51":
|
|
sideA = []
|
|
players = non_host
|
|
else:
|
|
players = [host] + non_host
|
|
sideA = [host]
|
|
return {
|
|
"Category": "Steam-te-18f25613-36778-ue4-374f864b",
|
|
"creationDateTime": current_timestamp,
|
|
"creator": host,
|
|
"customData": {
|
|
"SessionSettings": SessionSettings,
|
|
},
|
|
"MatchId": matchId,
|
|
"props": {
|
|
"countA": count_a,
|
|
"countB": count_b,
|
|
"gameMode": gameMode,
|
|
"MatchConfiguration": MatchConfiguration,
|
|
"platform": "",
|
|
"EncryptionKey": "fZ6lAM3Y3XNNz5qH86cgUP6Q0Bh7/Y72yQMfW/9nh74=",
|
|
},
|
|
"skill": [],
|
|
"reason": "",
|
|
"region": "all",
|
|
"geolocation": [],
|
|
"version": 2,
|
|
"churn": 0,
|
|
"rank": 1,
|
|
"Schema": 3,
|
|
"sideA": sideA,
|
|
"sideB": [player.userId for player in lobby.nonHosts],
|
|
"Players": players,
|
|
"status": lobby.status
|
|
}
|
|
except Exception as e:
|
|
logger.graylog_logger(level="error", handler="matchmaking_createMatchResponse", message=e)
|
|
|
|
def createQueueResponseMatched(self, creatorId, matchId, joinerId=None, region=None, matchConfig=None,
|
|
SessionSettings=None, PrivateMatch=False, countA=1, countB=5):
|
|
try:
|
|
current_timestamp, expiration_timestamp = get_time()
|
|
gameMode = matchConfig["gameMode"]
|
|
MatchConfiguration = matchConfig["MatchConfiguration"]
|
|
if creatorId == "147d48b8-6c71-456c-8c72-8d75cff31c51":
|
|
host = []
|
|
players = ([joinerId] if joinerId else [])
|
|
else:
|
|
host = [creatorId]
|
|
players = [creatorId] + ([joinerId] if joinerId else [])
|
|
if PrivateMatch:
|
|
status_base = "MATCHED"
|
|
status_int = "CREATED"
|
|
else:
|
|
status_base = "MATCHED"
|
|
status_int = "CREATED"
|
|
#if os.environ['DEV'] == "true":
|
|
# count_a = 1
|
|
# count_b = max_b_count_dev
|
|
#else:
|
|
count_a = countA
|
|
count_b = countB
|
|
return {
|
|
"status": status_base,
|
|
"matchData": {
|
|
"category": "Steam-te-18f25613-36778-ue4-374f864b",
|
|
"creationDateTime": current_timestamp,
|
|
"creator": creatorId,
|
|
"customData": {
|
|
"SessionSettings": SessionSettings
|
|
},
|
|
"matchId": matchId,
|
|
"props": {
|
|
"countA": count_a,
|
|
"countB": count_b,
|
|
"gameMode": gameMode,
|
|
"MatchConfiguration": MatchConfiguration,
|
|
"platform": "",
|
|
"EncryptionKey": "fZ6lAM3Y3XNNz5qH86cgUP6Q0Bh7/Y72yQMfW/9nh74=",
|
|
},
|
|
"rank": 1,
|
|
"schema": 3,
|
|
"skill": [],
|
|
"reason": "",
|
|
"region": "all",
|
|
"geolocation": [],
|
|
"version": 2,
|
|
"churn": 0,
|
|
"sideA": host,
|
|
"sideB": [joinerId] if joinerId else [],
|
|
"Players": players,
|
|
"status": status_int
|
|
},
|
|
}
|
|
except Exception as e:
|
|
logger.graylog_logger(level="error", handler="matchmaking_createQueueResponseMatched", message=e)
|
|
|
|
def getSession(self, userid):
|
|
try:
|
|
for lobby in self.openLobbies:
|
|
if lobby.host == userid:
|
|
return Session(lobby.host, [player.userId for player in lobby.nonHosts])
|
|
for player in lobby.nonHosts:
|
|
if player.userId == userid:
|
|
return Session(lobby.host, [player.userId for player in lobby.nonHosts])
|
|
return None
|
|
except Exception as e:
|
|
logger.graylog_logger(level="error", handler="getSession", message=e)
|
|
|
|
def genMatchUUID(self):
|
|
return str(uuid.uuid4())
|
|
|
|
def clear_queue(self):
|
|
open_lobbies = self.openLobbies
|
|
for lobby in open_lobbies:
|
|
match_id = lobby.id
|
|
self.deleteMatch(match_id)
|
|
logger.graylog_logger(level="info", handler="clear_queue",
|
|
message=f"Killed lobby: {match_id} with CLEAR_QUEUE")
|
|
return {"status": "success"}
|
|
|
|
def get_len_of_queue(self):
|
|
length = len(self.queuedPlayers)
|
|
return int(length)
|
|
|
|
def get_len_of_killed_lobbies(self):
|
|
length = len(self.killedLobbies)
|
|
return int(length)
|
|
|
|
def get_len_of_queued_runners(self):
|
|
length = len([player for player in self.queuedPlayers if player.side == "B"])
|
|
return int(length)
|
|
|
|
def get_len_of_queued_hunters(self):
|
|
length = len([player for player in self.queuedPlayers if player.side == "A"])
|
|
return int(length)
|
|
|
|
def get_len_of_open_lobbies(self):
|
|
length = len(self.openLobbies)
|
|
return int(length)
|
|
|
|
def get_lobby_data(self):
|
|
return self.openLobbies
|
|
|
|
|
|
matchmaking_queue = MatchmakingQueue()
|