import json import logging from typing import Dict from twisted.web import resource from core import CoreConfig from titles.idac.season2 import IDACBase from titles.idac.config import IDACConfig from random import randint class IDACMatching(resource.Resource): isLeaf = True SessionQueue = {} Rooms = {} def __init__(self, cfg: CoreConfig, game_cfg: IDACConfig) -> None: self.core_config = cfg self.game_config = game_cfg self.base = IDACBase(cfg, game_cfg) self.logger = logging.getLogger("idac") def getMatchingState(self, machineSerial): #We use official state code here if len(self.SessionQueue) == 1: self.logger.info(f"IDAC Matching queued player {machineSerial}: empty dict, returned by default") return self.SessionQueue[machineSerial] elif self.SessionQueue[machineSerial] == 0: self.logger.info(f"IDAC Matching queued player {machineSerial}: matched player, returned by default") return self.SessionQueue[machineSerial] else: for sessionID in self.SessionQueue.keys(): if sessionID == machineSerial: continue if self.SessionQueue[sessionID] == 1: #uncomment these to process into actual game #self.SessionQueue[machineSerial] = 0 #self.SessionQueue[sessionID] = 0 self.joinRoom(machineSerial, sessionID) self.logger.info(f"IDAC Matching queued player {machineSerial}: rival {sessionID} found!! return matched state") return self.SessionQueue[machineSerial] self.logger.info(f"IDAC Matching queued player {machineSerial}: cannot find any rival, returned by default") return self.SessionQueue[machineSerial] def joinRoom(self, machineSerial, sessionID): #Random room name, It should be handled by game itself in later process roomName = "INDTA-Zenkoku-Room" #+randint(1, 1001) self.Rooms[machineSerial] = roomName self.Rooms[sessionID] = roomName def render_POST(self, req) -> bytes: url = req.uri.decode() req_data = json.loads(req.content.getvalue().decode()) header_application = self.decode_header(req.getAllHeaders()) machineSerial = header_application["a_serial"] self.logger.info( f"IDAC Matching request from {req.getClientIP()}: {url} - {req_data}" ) if url == "/regist": self.SessionQueue[machineSerial] = 1 self.logger.info(f"IDAC Matching registed player {machineSerial}") return json.dumps({"status_code": "0"}, ensure_ascii=False).encode("utf-8") elif url == "/status": if req_data.get('cancel_flag'): if machineSerial in self.SessionQueue: self.SessionQueue.pop(machineSerial) self.logger.info(f"IDAC Matching endpoint {req.getClientIP()} had quited") return json.dumps({"status_code": "0", "host": "", "port": self.game_config.server.matching_p2p, "room_name": self.Rooms[machineSerial], "state": 1}, ensure_ascii=False).encode("utf-8") if machineSerial not in self.Rooms.keys(): self.Rooms[machineSerial] = "None" return json.dumps({"status_code": "0", "host": self.game_config.server.matching_host, "port": self.game_config.server.matching_p2p, "room_name": self.Rooms[machineSerial], "state": self.getMatchingState(machineSerial)}, ensure_ascii=False).encode("utf-8") # resp = { # "status_code": "0", # # Only IPv4 is supported # "host": self.game_config.server.matching_host, # "port": self.game_config.server.matching_p2p, # "room_name": "INDTA", # "state": self.get_matching_state(), # } # #self.logger.debug(f"Response {resp}") #return json.dumps(resp, ensure_ascii=False).encode("utf-8") def decode_header(self, data: Dict) -> Dict: app: str = data[b"application"].decode() ret = {} for x in app.split(", "): y = x.split("=") ret[y[0]] = y[1].replace('"', "") return ret