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 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 ExchangeClient(): def __init__(self): self.log = Logging() def send(self, i): msg = bytes(i, 'utf-8') self.log.debug('[{}:{}][EX-SEND->] {}'.format(str(self.addr[0]), str(self.addr[1]), i)) self.IoSession.send(msg) def kick(self): self.log.info('[{}:{}] Exchange Client has disconnected'.format(str(self.addr[0]), str(self.addr[1]))) sys.exit(0) def set_addr(self, addr): self.addr = addr def get_addr(self): return self.addr def get_id(self): return self.id def set_id(self, i): self.id = i def get_io_session(self): return self.IoSession def set_io_session(self, s): self.IoSession = s
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 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 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 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 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 GameClient: def __init__(self, socket, addr): self.log = Logging() self.session = socket self.addr = addr # self.account = account # self.actions = self.timeLastChatMsg = 0 self.timeLastIncarnamMsg = 0 self.timeLastAlignMsg = 0 self.timeLastRecrutmentMsg = 0 self.timeLastTradeMsg = 0 self.walk = False # self.waiter = def kick(self): self.log.info('[{}][ACC:{}] Client kick'.format( str(self.addr[0]), str('X'))) sys.exit(0) def get_session(self): return self.session def get_addr(self): return self.addr def set_character(self, character): self.character = character def get_character(self): return self.character def set_account(self, account): self.account = account def get_account(self): return self.account
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 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
class World: def __init__(self): self.log = Logging() self.constant = Constant() self.maps = {} # ID(int), MAP(object) def createWorld(self): self.log.info(35 * '-') self.log.info('Creation of the world begins:') # -------------------------------------------------------------------- # Players data are loading here self.playersData = dataSource.PlayersData() self.playersData.load_in_to_class() self.playersData = self.playersData.get_player_data() self.log.info('Player were loaded') # -------------------------------------------------------------------- # Maps data are loaded here __mapData = dataSource.MapData() __mapData.load_in_to_class() __mapData = __mapData.get_map_data() for __mapId, __mapObject in __mapData.items(): self.add_map(__mapId, __mapObject) del __mapData, __mapId, __mapObject self.log.info('Maps were loaded') self.log.info('The world-server has finished loading') self.log.info(35 * '-') def add_map(self, id, mapObject): self.maps[id] = mapObject def get_map(self, id): return self.maps.get(id) def get_players(self): return self.playersData def get_players_by_accid(self, accId): __playerList = {} __position = 1 for player in self.playersData: if player.get_account_id() == accId: __playerList[__position] = player __position += 1 return __playerList def create_player(self, accId, name, pClass, sex, color1, color2, color3): __playerID = 0 for player in self.playersData: if player.get_id() > __playerID: __playerID = player.get_id() __playerID = __playerID + 1 __startMapCellList = self.constant.get_start_map_incarnam(pClass) player = Player( __playerID, name, accId, -1, # id, name, account, group, sex, pClass, color1, color2, color3, # sexe, pClass, color1-3, 0, 1, '', 10000, 1, # kamas, spellboost, capital, energy, level, #0, 100, pClass * 10 + sex, # xp, size, gfx, 0, 100, (pClass * 10 + sex), # xp, size, gfx, 0, 0, 0, 0, # alignement, honor, deshonor, alvl, [0, 0, 0, 0, 0, 0], 1, 0, # stats(list), seeFriend, seeAlign, 0, '*#$p^', __startMapCellList[0], # seeSeller, channel, map, __startMapCellList[1], 100, # cell, pdvper, '141;', # spells <-- TODO placeholder '', '', # objets, storeObjets, str(__startMapCellList[0]) + ':' + str(__startMapCellList[1]), # savepos '', '', 0, # zaaps, jobs, mountxpgive, 0, 0, '0;0', # title, wife, morphMode, '', 0, 1, # emotes, prison, server, <-- TODO placeholder True, '', # logged allTitle '118,0;119,0;123,0;124,0;125,0;126,0', 0, 0, ) # parcho, timeDeblo, noall del __startMapCellList self.playersData.append(player) def delete_player(self, __playerID): # TODO remove player from his guild # TODO remove all his objets # determination of the list position __listPosition = 0 for player in self.playersData: if player.get_id() == __playerID: break else: __listPosition += 1 # delete list entry (in self.playersData) del self.playersData[__listPosition]