class MapData(DAO): def __init__(self): self.log = Logging() def load(self): ''' DataFrame: ''' self.dataSource = [] connection = dataSource.Database().get_connection() cursor = connection.cursor() try: cursor.execute('SELECT * FROM accounts;') data = cursor.fetchall() for row in data: self.dataSource.append(row) except Exception as Error: self.log.warning(' account_data.py - Can\'t load table accounts') self.log.warning(str(Error)) finally: cursor.close() connection.close() def get_map_data(self): print('bin ich hier ?????') return self.dataSource
class ExchangeClient(): def __init__(self): self.log = Logging() def initialize(self, exchange_ip, exchange_port): try: exSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) exSocket.connect((exchange_ip, exchange_port)) self.log.info('Exchange-Client connected to logon server ' + str(exchange_ip) + ':' + str(exchange_port)) self.ioConnector = exSocket except: exSocket.close() self.log.warning('It could not be connected to the login server') sys.exit(0) try: exchangeHandler = ExchangeHandler() threadName = 'Exchange-Receiver - Port: ' + str(exchange_port) t = threading.Thread(target=exchangeHandler.loop, name=threadName, args=(self.ioConnector, )) t.start() except threading.ThreadError as e: self.log.warning('Exchange-Receiver could not be created ' + str(e)) return self.ioConnector
class Database(): ''' INFO: ALWAYS close the Instans to close the Connection ''' def __init__(self): self.log = Logging() self.log.debug('Database instance has been created') def initialize_data(self): pass #initialize_connection def get_connection(self): config = Config() config.initialize() try: connection = pymysql.connect( host=config.get_host(), port=config.get_port(), user=config.get_user(), password=config.get_pass(), db=config.get_database_name(), cursorclass=pymysql.cursors.DictCursor) return connection except pymysql.Error as Error: self.log.warning('Database - initialize_connection\n' + 'Config: ' + str(config.get_host()) + ' - ' + str(config.get_port()) + ' - ' + str(config.get_user()) + ' - ' + str(config.get_pass()) + ' - ' + str(config.get_database_name()) + '\nDatabase - inicon - Something went wrong: {}'. format(str(Error))) return False
class LoginServer: def __init__(self): self.log = Logging() def start(self, ip, port, game_client_dic, accountDataDic, hostList, ipbans): threadName = 'Login-Server - ' + str(port) try: t = threading.Thread(target=LoginServer.server, name=threadName, args=(self, ip, port, game_client_dic, accountDataDic, hostList, ipbans)) t.start() except threading.ThreadError as e: self.log.warning('Login Server could not be created: ' + str(e)) def server(self, logon_ip, login_port, game_client_dic, accountDataDic, hostList, ipbans): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.bind((logon_ip, login_port)) except socket.error: print('Binding faild') s.listen() self.log.info('Logon Socket is listening on Port: ' + str(login_port)) while True: c, self.addr = s.accept() self.log.info('Connected ' + str(self.addr[0]) + ':' + str(self.addr[1])) LoginHandler().session_created(c, self.addr, game_client_dic, accountDataDic, hostList, ipbans) s.close()
class Database(): ''' INFO: ALWAYS close the Instans to close the Connection ''' def __init__(self): self.log = Logging() self.log.debug('Database instance has been created') def initialize_data(self): pass #initialize_connection def get_connection(self): config = Config() config.initialize() try: connection = mysql.connector.connect( host=config.get_world_db_host(), port=config.get_world_db_port(), user=config.get_world_db_user(), password=config.get_world_db_passwo(), db=config.get_world_db_name(), auth_plugin='mysql_native_password') return connection except mysql.connector.Error as Error: self.log.warning( 'Database - initialize_connection\n' + 'Config: ' + str(config.get_world_db_host()) + ' - ' + str(config.get_world_db_port()) + ' - ' + str(config.get_world_db_user()) + ' - ' + str(config.get_world_db_passwo()) + ' - ' + str(config.get_world_db_name()) + '\nDatabase - Something went wrong: {}'.format(str(Error))) return False
class GameServer: def __init__(self): self.log = Logging() def initialize(self, ip, port): threadName = 'Game-Server - ' + str(port) try: t = threading.Thread(target=GameServer.server, name=threadName, args=(self, ip, port)) t.start() except threading.ThreadError as e: self.log.warning('Game Server could not be created: ' + str(e)) def server(self, game_ip, game_port): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.bind((game_ip, game_port)) except socket.error: self.log.warning('Game Socket - Binding faild') s.listen() self.log.info('Game Socket is listening on Port: ' + str(game_port)) while True: c, self.addr = s.accept() self.log.info('Connected ' + str(self.addr[0]) + ':' + str(self.addr[1])) GameHandler().session_created(c, self.addr) s.close()
class Main: def __init__(self): self.log = Logging() self.config = Config() self.console = Console() self.console.clear() def start(self): # ====================================================== # start message def clear(): return os.system('cls') clear() def wel(): welmsg = [ 58 * '─', '| 0.01 |' + 12 * ' ' + 'pyCestra - World Server' + 11 * ' ' + '|', 58 * "─" ] for x in welmsg: print(bcolors.blue + x + bcolors.cend) wel() # ====================================================== # connection test self.log.info('Connection Test...') database = dataSource.Database() if database.get_connection(): self.log.info('Connection Successfully') else: self.log.warning('Connection ERROR') sys.exit(0) # ====================================================== # world class test world = World() world.createWorld() # ====================================================== # exchange client test exchangeTransferList = [] exClient = ExchangeClient() exClient.initialize(self.config.get_exchange_ip(), self.config.get_exchange_port(), exchangeTransferList) self.log.debug('Game Server Start') GameServer().initialize(self.config.get_world_ip(), self.config.get_world_port(), exchangeTransferList, world)
class LoginServer: def __init__(self, ip, port, gameClientDic, accountDataDic, hostList, ipBans): self.log = Logging() self.logoniIP = ip self.logonPort = port self.gameClientDic = gameClientDic self.accountDataDic = accountDataDic self.hostList = hostList self.ipBans = ipBans self.start() def start(self): threadName = 'Login-Server - ' + str(self.logonPort) try: t = threading.Thread(target=self.server, name=threadName, args=(self.logoniIP, self.logonPort, self.gameClientDic, self.accountDataDic, self.hostList, self.ipBans)) t.start() except threading.ThreadError as e: self.log.warning('Login Server could not be created: ' + str(e)) def server(self, logoniIP, logonPort, gameClientDic, accountDataDic, hostList, ipBans): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.bind((self.logoniIP, self.logonPort)) except socket.error: print('Login Socket - Binding faild') s.listen() self.log.info('Logon Socket is listening on Port: ' + str(self.logonPort)) while True: c, self.addr = s.accept() self.log.info('[{}:{}] Client Connected '.format( str(self.addr[0]), str(self.addr[1]))) self.session_created(c, self.addr) s.close() def session_created(self, soecket, addr): threadName = 'Client-Session ' + str(addr[0]) + ':' + str(addr[1]) try: t = threading.Thread(target=LoginHandler, name=threadName, args=(soecket, addr, self.gameClientDic, self.accountDataDic, self.hostList, self.ipBans)) t.start() except threading.ThreadError as e: self.log.debug('Created Session ' + str(addr[0]) + ':' + str(addr[1]) + ': ' + str(e))
class DatabaseUpdateService: def __init__(self): self.log = Logging() def start(self, accountDic, updateTime): threadName = 'Database-Update-Service' try: t = threading.Thread(target=DatabaseUpdateService.update_loop, name=threadName, args=(self, accountDic, updateTime)) t.start() self.log.info('Database-Update-Service Successfully') except: self.log.warning('Database-Update-Service could not be created') def update_loop(self, accountDic, updateTime): def string_builder(i): queryPart = ('UPDATE `accounts` SET ' '`pass` = \'{}\',' '`rank` = \'{}\',' '`nickname` = \'{}\',' '`lastConnectionDate` = \'{}\',' '`lastIP` = \'{}\',' '`friends` = \'{}\',' '`reload_needed` = \'{}\',' '`logged` = \'{}\',' '`subscribe` = \'{}\' ' 'WHERE (`id` = \'{}\');'.format( i["pass"], i["rank"], i["nickname"], i["lastConnectionDate"], i["lastIP"], i["friends"], i["reload_needed"], i["logged"], i["subscribe"], i["id"])) return queryPart dao = DAO() while True: time.sleep(updateTime) self.log.debug('[Database-Update-Service] - ' 'Data is send to the database') start = time.time() counter = 0 for i in accountDic: query = string_builder(i) dao.multi_update_data(query) del query counter = counter + 1 ende = time.time() self.log.debug('[Database-Update-Service] - Data was transferred ' '(query:{}, total time: {:5.3f}s)'.format( counter, ende - start))
class MapData(DAO): def __init__(self): self.log = Logging() def load_in_to_class(self): ''' DataFrame: ''' self.dataSource = {} connection = dataSource.Database().get_connection() cursor = connection.cursor(dictionary=True) try: cursor.execute('SELECT * FROM maps;') data = cursor.fetchall() for result in data: try: mapData = Map( result['id'], result['date'], result['width'], result['heigth'], result['key'], result['places'], result['mapData'], result['cells'], result['monsters'], result['mappos'], result['numgroup'], result['fixSize'], result['minSize'], result['maxSize'], result['cases'], result['forbidden'], ) self.dataSource[result['id']] = mapData except Exception as Error: self.log.warning( 'maps_data.py - maps:{} can\'t be loaded'.format( str(result['id']))) self.log.warning(Error) except Exception as Error: self.log.warning('map_data.py - Can\'t load table accounts') self.log.warning(str(Error)) finally: cursor.close() connection.close() def get_map_data(self): return self.dataSource
class DAO: def __init__(self): self.log = Logging() self.connection = dataSource.Database().get_connection() self.cursor = self.connection.cursor() def get_data(self, query): connection = dataSource.Database().get_connection() cursor = connection.cursor() try: if not query.endswith(';'): query += ";" cursor.execute(query) data = cursor.fetchall() return data except Exception as e: self.log.warning('DAO.py - Can\'t load: \n{}\n{}'.format( query, str(e))) cursor.close() connection.close() finally: cursor.close() connection.close() def multi_update_data(self, query): ''' This function does not end the connection after use ''' try: if not query.endswith(';'): query += ";" self.cursor.execute(query) except pymysql.Error as Error: self.log.warning( 'DAO.py - update_data - Can\'t update the Database\n{}\n{}'. format(str(Error), query))
class ServerData(DAO): def __init__(self): self.log = Logging() self.Datasource = [] def load(self): ''' DataFrame: id, name, key, population, isSubscriberServer ['1','Demo', 'demo', 0, 0,] relevant data: id, key, population, isSubscriberServer ['1', 'key', 'population', 'isSubscriberServer'] ''' connection = dataSource.Database().get_connection() cursor = connection.cursor() try: cursor.execute('SELECT * FROM servers;') data = cursor.fetchall() for result in data: # only relevant data is saved server = Server(result['id'], result['key'], 0, result['population'], result['isSubscriberServer']) self.Datasource.append(server) except pymysql.Error as Error: self.log.warning('server_data.py - Can\'t load table servers - ') self.log.warning(str(Error)) finally: cursor.close() connection.close() def get_server_data(self): return self.Datasource
class AccountData(DAO): def __init__(self): self.log = Logging() self.Datasource = [] def load(self): ''' DataFrame: ''' connection = dataSource.Database().get_connection() cursor = connection.cursor(dictionary=True) try: cursor.execute('SELECT * FROM accounts;') data = cursor.fetchall() for row in data: self.Datasource.append(row) except Exception as Error: self.log.warning(' account_data.py - Can\'t load table accounts') self.log.warning(str(Error)) finally: cursor.close() connection.close() def get_account_data(self): return self.Datasource def single_update(self, acc_id, valueTyp, value): ''' acc_id valueTyp = Column name as in the database value example: update(1,'logged','1') ''' data = 'UPDATE `accounts` SET `{}` = \'{}\' WHERE (`id` = \'{}\');'.format(str(valueTyp),str(value),str(acc_id)) super().update_data(data) # Use databank account ID to find the right account def get_from_id(self, idwis): if not idwis == 0: account = idwis - 1 return self.Datasource[account] else: self.log.warning('account_data.py - Can\'t load account id 0')
class GameServer: def __init__(self): self.log = Logging() def initialize(self, ip, port, exchangeTransferList, world): self.world = world threadName = 'Game-Server - ' + str(port) try: t = threading.Thread(target=self.server, name=threadName, args=(ip, port, exchangeTransferList)) t.start() except threading.ThreadError as e: self.log.warning('Game Server could not be created: ' + str(e)) def server(self, game_ip, game_port, exchangeTransferList): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.bind((game_ip, game_port)) except socket.error: self.log.warning('Game Socket - Binding faild') s.listen() self.log.info('Game Socket is listening on Port: ' + str(game_port)) while True: c, self.addr = s.accept() self.log.debug('[{}:{}] Client Connected '.format(str(self.addr[0]),str(self.addr[1]))) self.session_created(c, self.addr, exchangeTransferList) s.close() def session_created(self, socket, addr, exchangeTransferList): threadName = 'Game-Client-Session '+str(addr[0])+':'+ str(addr[1]) try: t = threading.Thread(target=GameHandler, name=threadName, args=(socket, addr, exchangeTransferList, self.world,)) t.start() except: self.log.warning('Game Client could not be created '+ str(addr[0])+':'+ str(addr[1]))
class ExchangeServer(): def __init__(self): self.log = Logging() def start(self, ip, port, hostList): threadName = 'Exchange-Server - ' + str(port) try: t = threading.Thread(target=ExchangeServer.server, name=threadName, args=(self, ip, port, hostList)) t.start() except: self.log.warning('Exchange Server could not be created') def server(self, ex_ip, ex_port, hostList): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.bind((ex_ip, ex_port)) except socket.error: self.log.warning('Exchange Socket - Binding faild') s.listen() self.log.info('Exchange Socket is listening on Port: ' + str(ex_port)) while True: c, self.addr = s.accept() self.log.info('Exchange Client connected ' + str(self.addr[0]) + ':' + str(self.addr[1])) ExchangeServer().session_created(c, self.addr, hostList) s.close() def session_created(self, soecket, addr, hostList): threadName = 'Exchange-Client ' + str(addr[0]) + ':' + str(addr[1]) try: t = threading.Thread(target=HelloExchangeClient, name=threadName, args=(soecket, addr, hostList)) t.start() except: self.log.warning('Exchange Client could not be created ' + str(addr[0]) + ':' + str(addr[1]))
class Map(): def __init__(self, mapId, date, width, heigth, key, places, mapData, cells, monsters, mapPos, numGroup, fixSize, minSize, maxSize, cases, forbidden): self.log = Logging() self.id = mapId self.data = date self.width = width self.heigth = heigth self.key = key self.places = places self.mapData = mapData self.cells = cells self.monsters = monsters self.numGroup = numGroup self.fixSize = fixSize self.minSize = minSize self.maxSize = maxSize self.forbiddenCellSpawn = cases # ----------------------------------------- # if (!places.equalsIgnoreCase("") && !places.equalsIgnoreCase("|")) { # final String[] split = places.split("\\|"); # this.maxTeam0 = split[0].length() / 2; # this.maxTeam1 = split[1].length() / 2; # } # ----------------------------------------- try: mapPos.split(',') self.X = mapPos[0] self.Y = mapPos[1] del mapPos except Exception as Error: self.log.warning('[MAP {}] Map.__init__ - (mapPos) - {}'.format( self.id, Error)) # ----------------------------------------- # subArea # ----------------------------------------- try: split = forbidden.split(';') self.noTrader = split[0] in '1' self.noCollector = split[1] in '1' self.noPrism = split[2] in '1' self.noTP = split[3] in '1' self.noDefie = split[4] in '1' self.noAgro = split[5] in '1' self.noChannel = split[6] in '1' del forbidden, split except Exception as Error: self.log.warning('[MAP {}] Map.__init__ - (forbidden) - {}'.format( self.id, Error)) # ----------------------------------------- try: cryptManager = CryptManager() self.cases = cryptManager.decompile_map_data(self, self.mapData) del cryptManager, self.mapData except Exception as Error: self.log.warning( '[MAP {}] Map.__init__ - (decompile_map_data) - {}'.format( self.id, Error)) # if # this.cases = CryptManager.decompileMapData(this, dData) # else: # final String[] cellsDataArray = cellsData.split("\\|"); # String[] array; # for (int length = (array = cellsDataArray).length, j = 0; j < length; ++j) { # final String o = array[j]; # boolean Walkable = true; # ... # ... # ... # ----------------------------------------- # String[] split2; # for (int length2 = (split2 = monsters.split("\\|")).length, k = 0; k < length2; ++k) { # final String mob = split2[k]; # ----------------------------------------- # if (!cases.isEmpty()) { # for (final Case c : this.cases.values()) { # c.setWalkableInFight(false); # } # try { # String[] split3; # .... # .... # .... # -----------------------------------------
class PlayersData(DAO): def __init__(self): self.log = Logging() def load_in_to_class(self): ''' DataFrame: ''' self.dataSource = [] connection = dataSource.Database().get_connection() cursor = connection.cursor(dictionary=True) try: cursor.execute('SELECT * FROM players;') data = cursor.fetchall() for result in data: try: # the attributes are the inGame order stats = [result['vitality'], result['wisdom'], result['strength'], result['intelligence'], result['chance'], result['agility']] if result['color1'] == -1: color1 = 'ffffffff' else: color1 = hex(result['color1']).replace("0x","") if result['color2'] == -1: color2 = 'ffffffff' else: color2 = hex(result['color2']).replace("0x","") if result['color3'] == -1: color3 = 'ffffffff' else: color3 = hex(result['color3']).replace("0x","") player = Player(result['id'], result['name'], result['account'], result['group'], result['sexe'], result['class'], color1, color2, color3, result['kamas'], result['spellboost'], result['capital'], result['energy'], result['level'], result['xp'], result['size'], result['gfx'], result['alignement'], result['honor'], result['deshonor'], result['alvl'], stats, result['seeFriend'], result['seeAlign'], result['seeSeller'], result['channel'], result['map'], result['cell'], result['pdvper'], result['spells'], result['objets'], result['storeObjets'], result['savepos'], result['zaaps'], result['jobs'], result['mountxpgive'], result['title'], result['wife'], result['morphMode'], result['emotes'], result['prison'], result['server'], result['logged'], result['allTitle'], result['parcho'], result['timeDeblo'], result['noall'],) self.dataSource.append(player) except: self.log.warning('player_data.py - player:{} can\'t be loaded'.format(result['id'])) return self.dataSource except Exception as Error: self.log.warning('player_data.py - Can\'t load table player') self.log.warning(str(Error)) finally: cursor.close() connection.close() def get_player_data(self): return self.dataSource
class GameHandler: def __init__(self): self.log = Logging() def loop(self, gameClient): while True: data = gameClient.get_io_session().recv(2048) packet = data.decode() packetLog = packet.replace('\n', '[]') self.log.debug('[TODO client ip][<-GM-RECV] ' + packetLog) if not data: self.log.debug('[TODO client ip] PacketLoop no data') gameClient.kick() break GameHandler.parse(packet) def session_created(self, soecket, addr): threadName = 'Game-Client ' + str(addr[0]) + ':' + str(addr[1]) try: t = threading.Thread(target=GameClient, name=threadName, args=( soecket, addr, )) t.start() except: self.log.warning('Game Client could not be created ' + str(addr[0]) + ':' + str(addr[1])) def parse(self, packet): if packet[0] == 'A': print('parse_account_packet') return elif packet[0] == 'B': print('parseBasicsPacket') return elif packet[0] == 'C': print('parseConquestPacket') return elif packet[0] == 'c': print('parseChanelPacket') return elif packet[0] == 'D': print('parseDialogPacket') return elif packet[0] == 'd': print('parseDocumentPacket') return elif packet[0] == 'E': print('parseExchangePacket') return elif packet[0] == 'e': print('parseEnvironementPacket') return elif packet[0] == 'F': print('parseFrienDDacket') return elif packet[0] == 'f': print('parseFightPacket') return elif packet[0] == 'G': print('parseGamePacket') return elif packet[0] == 'g': print('parseGuildPacket') return elif packet[0] == 'h': print('parseHousePacket') return elif packet[0] == 'i': print('parseEnemyPacket') return elif packet[0] == 'J': print('parseJobOption') return elif packet[0] == 'K': print('parseHouseKodePacket') return elif packet[0] == 'O': print('parseObjectPacket') return elif packet[0] == 'P': print('parseGroupPacket') return elif packet[0] == 'R': print('parseMountPacket') return elif packet[0] == 'Q': print('parseQuestData') return elif packet[0] == 'S': print('parseSpellPacket') return elif packet[0] == 'T': print('parseFoireTroll') return elif packet[0] == 'W': print('parseWaypointPacket') return def parse_account_packet(self, packet): if packet[1] == 'A': print('addCharacter') return elif packet[1] == 'B': print('boost') return elif packet[1] == 'D': print('deleteCharacter') return elif packet[1] == 'f': print('getQueuePosition') return elif packet[1] == 'g': print('getGifts') return elif packet[1] == 'G': print('attributeGiftToCharacter') return elif packet[1] == 'i': print('sendIdentity') return elif packet[1] == 'L': print('getCharacters') return elif packet[1] == 'M': print('parseMigration') return elif packet[1] == 'S': print('setCharacter') return elif packet[1] == 'T': print('sendTicket') return elif packet[1] == 'V': print('requestRegionalVersion') return elif packet[1] == 'P': print('SocketManager.REALM_SEND_REQUIRED_APK') return
class LoginClient: def __init__(self, game_client_dic, accountDataDic): self.game_client_dic = game_client_dic self.accountDataDic = accountDataDic self.log = Logging() def write(self, o): msg = bytes(o+'\x00', 'utf-8') self.log.debug('[' + str(self.address[0]) + ':' + str(self.address[1]) + '][' + str(self.status.name) + '][SEND->] ' + o) self.IoSession.send(msg) def kick(self): # ----------------------------------------- # update 'logged' to 0 for i in self.accountDataDic: if i['id'] == self.account.get_id(): i['logged'] = 0 # ----------------------------------------- # delete entries in 'game_client_dic' dict_str = self.address[0] + ':' + str(self.address[1]) self.IoSession.close() try: self.game_client_dic.pop(dict_str) except KeyError: self.log.warning('[' + str(self.address[0]) + ':' + str(self.address[1]) + '][' + str(self.status.name) + '] The request in "game_client_dic" has been incorrectly removed') # ----------------------------------------- self.log.info('[' + str(self.address[0]) + ':' + str(self.address[1]) + '][' + str(self.status.name) + '] Client kick') sys.exit(0) def get_address(self): return self.address def set_address(self, a): self.address = a def get_id(self): return self.id def set_id(self, Client_id): self.id = Client_id def get_io_session(self): return self.IoSession def set_io_session(self, s): self.IoSession = s def get_key(self): return self.key def set_key(self, k): self.key = k def get_status(self): return self.status def set_status(self, status): self.status = status def get_account(self): return self.account def set_account(self, account): self.account = account
class GameHandler: def __init__(self, socket, addr, exchangeTransferList, world): self.log = Logging() self.world = world self.gameClient = GameClient(socket, addr) self.exchangeTransferList = exchangeTransferList self.socketManager = SocketManager(self.gameClient) self.accId = None self.account = None self.socketManager.GAME_SEND_HELLOGAME_PACKET() self.loop() def loop(self): while True: data = self.gameClient.get_session().recv(2048) packet = data.decode() packetLog = packet.replace('\n\x00', '[n][x00]') self.log.debug('[{}][ACC:{}][<-RECV] {}'.format(str(self.gameClient.get_addr()[0]), str(self.acc_display_number()), str(packetLog))) if not data: self.log.debug('[{}][ACC:{}] PacketLoop no data'.format(str(self.gameClient.get_addr()[0]), str('X'))) self.gameClient.kick() break multiPacket = packet.split("\n\x00") if len(multiPacket) > 2: for p in multiPacket: if not p == '': self.parse(p) else: self.parse(packet.replace('\n\x00', '')) def acc_display_number(self): if type(self.accId) != int: if self.account == None: self.accId = 'X' else: self.accId = self.gameClient.get_account().get_id() return self.accId # -------------------------------------------------------------------- # PARSE ACCOUNT PACKET def add_character(self, packet): __packetList = packet[2:].split('|') __forbiddenWords = [r'[Aa][Dd][Mm][Ii][Nn]', r'[Mm][Oo][Dd][Oo]', r'[Gg][Mm]', r'[Gg][Aa][Mm][Ee]-?[Mm][Aa][Ss][Tt][Ee][Rr]'] __isValid = True # check existing character names for player in self.world.get_players(): if player.get_name() == __packetList[0]: self.socketManager.GAME_SEND_NAME_ALREADY_EXIST() return # check for forbidden words for __f in __forbiddenWords: if re.search(__f, __packetList[0]): __isValid = False # checking prohibited symbols for __i in __packetList[0]: nick = re.match(r'[a-zA-Z]?\x2D?', __i) if nick.group(0) == '': __isValid = False if __isValid == False: self.socketManager.GAME_SEND_NAME_ALREADY_EXIST() return # check available character slots if self.gameClient.get_account().get_number_of_characters() >= 5: self.socketManager.GAME_SEND_CREATE_PERSO_FULL() return try: self.world.create_player(self.gameClient.get_account().get_id(), __packetList[0],int(__packetList[1]),int(__packetList[2]), int(__packetList[3]),int(__packetList[4]),int(__packetList[5])) # # save changes in the account class __playerList = self.world.get_players_by_accid(self.gameClient.get_account().get_id()) if len(__playerList) != 0: self.gameClient.get_account().set_characters(__playerList) self.socketManager.GAME_SEND_CREATE_OK() # # broadcast of the current player list self.socketManager.GAME_SEND_PLAYER_LIST(self.gameClient.get_account().get_subscribe(), self.gameClient.get_account().get_number_of_characters(), self.gameClient.get_account().get_characters()) self.socketManager.GAME_SEND_cMK_PACKET_TO_MAP() except Exception as e: self.socketManager.GAME_SEND_CREATE_FAILED() self.log.warning('[{}][ACC:{}] GameHandler.add_character Exception: {}'.format(str(self.gameClient.get_addr()[0]), str(self.acc_display_number()), str(e))) def boost(self, packet): self.log.warning('boost') def delete_character(self, packet): try: __packetList = packet[2:].split('|') # determine the position of the character, save the character displayPosition = int(__packetList[0]) deletion_target = self.gameClient.get_account().get_characters().get(displayPosition) # check if the player is above level 19 and if the answer is correct if (deletion_target.get_level() >= 20 and __packetList[1] == self.gameClient.get_account().get_reponse()) or deletion_target.get_level() < 20: self.world.delete_player(deletion_target.get_id()) # save changes in the account class __playerList = self.world.get_players_by_accid(self.gameClient.get_account().get_id()) if len(__playerList) != 0: self.gameClient.get_account().set_characters(__playerList) # broadcast of the current player list self.socketManager.GAME_SEND_PLAYER_LIST(self.gameClient.get_account().get_subscribe(), self.gameClient.get_account().get_number_of_characters(), self.gameClient.get_account().get_characters()) else: self.socketManager.GAME_SEND_DELETE_PERSO_FAILED() except Exception as e: self.socketManager.GAME_SEND_DELETE_PERSO_FAILED() self.log.warning('[{}][ACC:{}] GameHandler.delete_character Exception: {}'.format(str(self.gameClient.get_addr()[0]), str(self.acc_display_number()), str(e))) def get_queue_position(self, packet): # placeholder ¯\_(ツ)_/¯ __queueID = 1 __position = 1 self.socketManager.MULTI_SEND_Af_PACKET(__position, 1, 1, "1", __queueID) def get_gifts(self, packet): self.log.warning('getGifts') def attribute_gift_to_character(self, packet): self.log.warning('attributeGiftToCharacter') def send_identity(self, packet): self.gameClient.get_account().set_key(packet[2:]) def get_characters(self, packet): # both objects refer to each other gameClient <-> account self.gameClient.get_account().set_game_client(self.gameClient) # TODO relog in the fight __playerList = self.world.get_players_by_accid(self.gameClient.get_account().get_id()) self.gameClient.get_account().set_characters(__playerList) self.socketManager.GAME_SEND_PLAYER_LIST(self.gameClient.get_account().get_subscribe(), self.gameClient.get_account().get_number_of_characters(), self.gameClient.get_account().get_characters()) def parse_migration(self, packet): self.log.warning('parseMigration') def set_character(self, packet): try: __listPosition = int(packet[2:]) self.gameClient.get_account().set_player(__listPosition) # both objects refer to each other account <-> player self.gameClient.get_account().get_player().set_account(self.gameClient.get_account(), self.socketManager) self.gameClient.get_account().get_player().join_game() except Exception as e: self.socketManager.GAME_SEND_PERSO_SELECTION_FAILED() self.log.warning('[{}][ACC:{}] GameHandler.set_character Exception: {}'.format(str(self.gameClient.get_addr()[0]), str(self.acc_display_number()), str(e))) self.gameClient.kick() def send_ticket(self, packet): __accId = packet[2:] __accIsAvailable = False __delCount = 0 for acc in self.exchangeTransferList: if str(acc.get_id()) == __accId: self.gameClient.set_account(acc) self.account = acc __accIsAvailable = True del self.exchangeTransferList[__delCount] __delCount += 1 if __accIsAvailable == True: self.socketManager.GAME_SEND_ATTRIBUTE_SUCCESS() else: self.socketManager.GAME_SEND_ATTRIBUTE_FAILED() self.gameClient.kick() # TODO In my opinion, the queue is sent here (Main.gameServer.getWaitingCompte(id)) # try: # try: # pass # this.compte = Main.gameServer.getWaitingCompte(id); # except Exception as e: # self.socketManager.GAME_SEND_ATTRIBUTE_FAILED() # self.log.warning(e) # self.gameClient.kick() # String ip = this.session.getRemoteAddress().toString().substring(1).split("\\:")[0]; # this.compte.setGameClient(this); # this.compte.setCurIP(ip); # Main.gameServer.delWaitingCompte(this.compte); # Database.getStatique().getPlayerData().loadByAccountId(this.compte.getGuid()); # self.socketManager.GAME_SEND_ATTRIBUTE_SUCCESS(this); # except Exception as e: # self.log.warning(e) # self.gameClient.kick() def request_regional_version(self, packet): self.socketManager.GAME_SEND_AV0() def realm_send_required_apk(self, packet): self.socketManager.REALM_SEND_REQUIRED_APK() # -------------------------------------------------------------------- # PARSE GAME PACKET parseBasicsPacket def get_date(self, packet): self.socketManager.GAME_SEND_SERVER_HOUR() # -------------------------------------------------------------------- # PARSE GAME PACKET parseGamePacket def send_actions(self, packet): self.log.warning('sendActions') def send_game_create(self, packet): self.gameClient.get_account().get_player().send_game_create() def delete_character_GD(self, packet): self.log.warning('deleteCharacter') def show_monster_target(self, packet): self.log.warning('showMonsterTarget') def set_flag(self, packet): self.log.warning('setFlag') def set_ghosts(self, packet): self.log.warning('setFlag') def get_extra_informations(self, packet): # EndFightAction are checked here self.log.warning('EndFightAction are checked here') self.get_extra_informations_two(packet) pass def get_extra_informations_two(self, packet): try: # if (perso.get_fight() != null) # SocketManager.GAME_SEND_MAP_GMS_PACKETS(this.perso.get_fight().getMap(), this.perso); # SocketManager.GAME_SEND_GDK_PACKET(this); # return # House.load # SocketManager.GAME_SEND_MAP_GMS_PACKETS # SocketManager.GAME_SEND_MAP_MOBS_GMS_PACKETS # SocketManager.GAME_SEND_MAP_NPCS_GMS_PACKETS # SocketManager.GAME_SEND_MAP_PERCO_GMS_PACKETS # SocketManager.GAME_SEND_MAP_OBJECTS_GDS_PACKETS self.socketManager.send('GDF|', 'GAME_SEND_MAP_OBJECTS_GDS_PACKETS (DEMO)') # SocketManager.GAME_SEND_GDK_PACKET # SocketManager.GAME_SEND_MAP_FIGHT_COUNT # SocketManager.SEND_GM_PRISME_TO_MAP # SocketManager.GAME_SEND_MERCHANT_LIST # Fight.FightStateAddFlag # SocketManager.GAME_SEND_Rp_PACKET # SocketManager.GAME_SEND_GDO_OBJECT_TO_MAP # SocketManager.GAME_SEND_GM_MOUNT # sendFloorItems # verifDoor # World.showPrismes # for (final Player player : this.perso.getCurMap().getPersos()) # player.send(String.valueOf(packet) + data) # this.perso.send(String.valueOf(packet) + data) pass except Exception as e: self.log.warning('[{}][ACC:{}] GameHandler.get_extra_informations_two Exception: {}'.format(str(self.gameClient.get_addr()[0]), str(self.acc_display_number()), str(e))) def action_ack(self, packet): self.log.warning('actionAck') def toggle_wings(self, packet): self.log.warning('toggleWings') def set_player_position(self, packet): self.log.warning('setPlayerPosition') def leave_fight(self, packet): self.log.warning('leaveFight') def ready_fight(self, packet): self.log.warning('readyFight') def get_fight_player_pass(self, packet): self.log.warning('get_fight().playerPass') # -------------------------------------------------------------------- def parse(self, recPacked): packetParse = { 'AA' : self.add_character, 'AB' : self.boost, 'AD' : self.delete_character, 'Af' : self.get_queue_position, 'Ag' : self.get_gifts, 'AG' : self.attribute_gift_to_character, 'Ai' : self.send_identity, 'AL' : self.get_characters, 'AM' : self.parse_migration, 'AS' : self.set_character, 'AT' : self.send_ticket, 'AV' : self.request_regional_version, 'AP' : self.realm_send_required_apk, 'BD' : self.get_date, 'GA' : self.send_actions, 'GC' : self.send_game_create, 'GD' : self.delete_character_GD, 'Gd' : self.show_monster_target, 'Gf' : self.set_flag, 'GF' : self.set_ghosts, 'GI' : self.get_extra_informations, 'GK' : self.action_ack, 'GP' : self.toggle_wings, 'Gp' : self.set_player_position, 'GQ' : self.leave_fight, 'GR' : self.ready_fight, 'Gt' : self.get_fight_player_pass, } try: packetParse[recPacked[:2]](recPacked) except KeyError: self.log.warning('UNKNOWN PACKAGE {}({})'.format(recPacked[:2],recPacked))
class ExchangeHandler(): def __init__(self): self.log = Logging() def recv_loop(self, exClient, hostList): while True: try: data = exClient.get_io_session().recv(2048) except ConnectionResetError: exClient.kick() packet = data.decode() packetPrint = packet.replace('\n', '[n]') self.log.debug('[{}:{}][<-EX-RECV] {}'.format( str(exClient.get_addr()[0]), str(exClient.get_addr()[1]), packetPrint)) if not data: self.log.debug('[SERVER-NAME] PacketLoop no data') exClient.kick() break ExchangeHandler().parse(exClient, packet, hostList) def parse(self, exClient, packet, hostList): if packet[0] == 'F': #F # org.cestra.exchange.ExchangePacketHandler @ parser # F + getPlayerNumber return elif packet[0] == 'S': if packet[1] == 'H': #SH # SH Ip ; Port s = packet[2:].split(';') ip = str(s[0]) port = int(s[1]) for i in hostList: if exClient.get_id() == i.get_id(): i.set_ip(ip) i.set_port(port) i.set_status(1) self.log.debug('[{}:{}] Status to 1'.format( str(exClient.get_addr()[0]), str(exClient.get_addr()[1]))) exClient.send('SHK') self.log.info( 'World-Server (ID:{}) has successfully registered'.format( exClient.get_id())) return elif packet[1] == 'K': #SK # 'SK id; key; freePlaces' s = packet[2:].split(';') id = int(s[0]) key = str(s[1]) freePlaces = int(s[2]) exClient.set_id(id) for serverObject in hostList: if serverObject.get_key() == key: serverObject.set_ex_client(exClient) serverObject.set_free_places(freePlaces) exClient.send('SKK') return exClient.send('SKR') exClient.kick() return elif packet[1] == 'S': #SS # org.cestra.game.GameServer @ setState # SS0 SS1 SS2 return elif packet[0] == 'M': if packet[1] == 'P': #MP # org.cestra.game.GameClient @ parseMigration # MP + GameClient.this.compte.getGuid return elif packet[1] == 'T': #MT # org.cestra.exchange.ExchangePacketHandler @ parser # MT" + account + "|" + server return elif packet[1] == 'D': #MD return elif packet[1] == 'O': #MO # org.cestra.game.GameClient @ parseMigration # MO + split[0] + "|" + server2 return self.log.warning('[' + str(exClient.get_id()) + '] Packet undefined: ' + packet) exClient.kick()
def main(): # ====================================================== # start message log = Logging() console = Console() console.clear() def wel(): welmsg = [ 58 * '─', '| 0.01 |' + 12 * ' ' + 'pyCestra - Logon Server' + 12 * ' ' + '|', 58 * "─" ] for x in welmsg: print(bcolors.blue + x + bcolors.cend) wel() # ====================================================== # preload data config = Config() config.initialize() log.info('Connection Test...') database = dataSource.Database() if database.get_connection(): log.info('Connection Successfully') else: log.warning('Connection ERROR') sys.exit(0) hostList = dataSource.ServerData() hostList.load() hostList = hostList.get_server_data() log.info('ServerData were loaded') accountData = dataSource.AccountData() accountData.load() accountDataDic = accountData.get_account_data() log.info('AccountData were loaded') ipbans = dataSource.IpBans().load() log.info('IP Bans were loaded') dataSource.DatabaseUpdateService().start(accountDataDic, config.get_update_time()) # ====================================================== # socket tests print(58 * '-') game_client_dic = {} LoginServer(config.get_login_ip(), config.get_login_port(), game_client_dic, accountDataDic, hostList, ipbans) ExchangeServer().start(config.get_exchange_ip(), config.get_exchange_port(), hostList) while True: time.sleep(15) if game_client_dic: log.warning('---- game_client_dic ----') for x in game_client_dic: log.warning(str(x)) log.warning('-------------------------')
class ServerSelected(): def __init__(self, client, packet, accountDataDic, hostList): self.log = Logging() account = client.get_account() packet = packet.replace('\n\x00', '') packet = int(packet) server = None def get_free_server(hostList): msg = 'AXEf' for s in hostList: try: fp = s.get_free_places() except AttributeError: fp = 0 if s.get_sub() != 0 or fp > 0: continue msg += str(s.get_id()) + '|' return msg try: # server is searched from the host list for i in hostList: if i.get_id() == packet: server = i self.log.debug('[{}:{}][{}] Server {} has been selected'.format( str(client.get_address()[0]), str(client.get_address()[1]), str(client.get_status().name), packet)) # client is kicked if this server id does not exist if server is None: self.log.debug( '[{}:{}][{}] The selected server does not exist for the account' .format(str(client.get_address()[0]), str(client.get_address()[1]), str(client.get_status().name))) # clinet msg: You are not allowed to connect to this server. client.write('AXEr') return # the selected server is not in the correct status for the account if server.get_status() != 1: self.log.debug( '[{}:{}][{}] The status of the selected server is unavailable for the account' .format(str(client.get_address()[0]), str(client.get_address()[1]), str(client.get_status().name))) # clinet msg: The server you selected is unavailable at this time. client.write('AXEd') return # the selected server is only available to subscribers if account.is_subscribes() == 0 and server.get_sub() == 1: self.log.debug( '[{}:{}][{}] The selected server is full or you must be subscribed for the account' .format(str(client.get_address()[0]), str(client.get_address()[1]), str(client.get_status().name))) # clinet msg: Server:FULL Maximum number of players reached. # To get priority access, please becomme a full member by subscribing.. client.write(get_free_server(hostList)) ServerList().get_list(client) return account.set_server(server.get_id()) # all important account data are sent to the game server for __i in accountDataDic: if __i['id'] == account.get_id(): lastConnectionDate = __i['lastConnectionDate'] lastIP = __i['lastIP'] server.get_ex_client().send('WA#{}#{}#{}#{}#{}#{}#{}'.format( str(account.get_id()), account.get_nickname(), account.get_question(), account.get_reponse(), account.get_subscribe(), lastConnectionDate, lastIP)) # the address of the world server is sent to the client client.write('AYK{}:{};{}'.format(str(server.get_ip()), str(server.get_port()), str(account.get_id()))) # set client status to WAIT_VERSION account.set_state(0) self.log.info( '[{}:{}][{}] Client connects to World-Server:{}'.format( str(client.get_address()[0]), str(client.get_address()[1]), str(client.get_status().name), str(server.get_id()))) except Exception as e: self.log.warning( '[{}:{}][{}] The server selection failed\n{}'.format( str(client.get_address()[0]), str(client.get_address()[1]), str(client.get_status().name), e)) client.write('AXEr') client.kick() return