def send_char_list(self, conn: Connection): session = self.server.handle_until_return('session:get_session', conn.get_address()) characters = self.server.handle_until_return('char:characters', session.account) front_char = self.server.handle_until_return('char:front_char', characters) serializable_characters = [] front_char_id = 0 for idx, character in enumerate(characters): if character.objid == front_char.objid: front_char_id = idx serializable_character = Character( character.objid, character.name, character.unapproved_name, character.is_name_rejected, character.account.free_to_play, character.shirt_color, character.shirt_style, character.pants_color, character.hair_style, character.hair_color, character.lh, character.rh, character.eyebrows, character.eyes, character.mouth, character.last_zone, character.last_instance, character.last_clone, character.last_login, []) serializable_characters.append(serializable_character) res = CharacterListResponse(serializable_characters, front_char_id) conn.send(res) return True
def destroy_session(self, conn: Connection): """ Destroys a session """ address = conn.get_address() Session.objects.filter(ip=address[0], port=address[1]).delete() conn.close()
def mission_accept(self, packet, conn: Connection, stream: ReadStream): """ Handles the mission dialogue ok game message """ complete = stream.read(c_bit) state = stream.read(c_int) mission_id = stream.read(c_int) responder_objid = stream.read(c_int64) print(f'Mission {mission_id} accepted') print(f'Complete: {complete}') print(f'State: {state}') print(f'Responder: {responder_objid}') session = self.server.handle_until_return('session:get_session', conn.get_address()) char = self.server.handle_until_return( 'char:characters', session.account.user.id)[session.account.front_character] if complete: self.server.handle('char:complete_mission', char.pk, mission_id) wstr = WriteStream() wstr.write(c_int(mission_id)) wstr.write(c_int(8)) wstr.write(c_bit(False)) msg = ServerGameMessage(responder_objid, GameMessageID.NOTIFY_MISSION, wstr) else: self.server.handle('char:activate_mission', char.pk, mission_id) # tasks = self.server.handle_until_return('world:get_mission_tasks', mission_id) # for task in tasks: # wstr = WriteStream() # wstr.write(c_int(mission_id)) # wstr.write(c_int(1 << (task[2] + 1))) # wstr.write(c_uint8(0)) # msg = ServerGameMessage(packet.objid, GameMessageID.NOTIFY_MISSION_TASK, wstr) # conn.send(msg) wstr = WriteStream() wstr.write(c_int(mission_id)) wstr.write(c_int(2)) wstr.write(c_bit(False)) msg = ServerGameMessage(responder_objid, GameMessageID.NOTIFY_MISSION, wstr) conn.send(msg)
def load_world(self, session, conn: Connection): zone_id = ZONE_IDS[self.server.type] self.server.handle('world:zone_entered', session, zone_id) res = WorldInfo( zone_id, 0, # Instance 0, # Clone ZONE_CHECKSUMS[zone_id], Vector3(*ZONE_SPAWNPOINTS[zone_id]), 0) # Activity conn.send(res)
def collected(self, packet, conn: Connection, stream: ReadStream): """ Handles the has been collected game message """ objid = stream.read(c_int64) print(f'Collected object') print(f'ID: {packet.objid}') print(f'Player: {objid}') session = self.server.handle_until_return('session:get_session', conn.get_address()) char = self.server.handle_until_return( 'char:characters', session.account.user.id)[session.account.front_character] clone = self.server.handle_until_return('world:get_clone', session.clone) char_missions = self.server.handle_until_return( 'char:get_missions', char.pk) objs = [x for x in clone.objects if x.objid == packet.objid] if objs: obj = objs[0] for char_mission in [x for x in char_missions if x.state == 2]: tasks = self.server.handle_until_return( 'world:get_mission_tasks', char_mission.mission) for task in tasks: if task[3] == obj.lot and task[2] == 3: char_mission.progress += 1 char_mission.save() wstr = WriteStream() wstr.write(c_int(char_mission.mission)) wstr.write(c_int(1 << (tasks.index(task) + 1))) wstr.write(c_uint8(1)) wstr.write( c_float(char_mission.progress + (clone.zone << 8))) msg = ServerGameMessage( objid, GameMessageID.NOTIFY_MISSION_TASK, wstr) conn.send(msg) return
def join_world_request(self, packet: 'JoinWorldRequest', conn: Connection): """ Handles initial redirect from char list """ session = self.server.handle_until_return('session:get_session', conn.get_address()) # One of the plugins listening is expected to set session.character self.server.handle('session:char_selected', session, packet.character_id) last_zone = self.server.handle_until_return('char:initial_zone', session.character) zone_conf = self.server.config.servers.to_dict()[ZONE_NAMES[last_zone]] res = RedirectToServer(zone_conf['public_host'], zone_conf['public_port']) conn.send(res)
def client_load_complete(self, packet, conn: Connection): session = self.server.handle_until_return('session:get_session', conn.get_address()) char_info = DetailedUserInfo(session.account.user.pk, session.character.name, ZONE_IDS[self.server.type], session.character.pk, missions=[ Mission(mission=1727, character=session.character, state=8, times_completed=1, last_completion=0) ]) conn.send(char_info) self.server.repman.add_participant(conn) player = Player(session.character, Vector3(*ZONE_SPAWNPOINTS[ZONE_IDS[self.server.type]]), Vector4(0, 0, 0)) self.server.repman.construct(player, True) obj_load = ServerGameMessage(session.character.pk, GameMessageID.DONE_LOADING_OBJECTS) conn.send(obj_load) player_ready = ServerGameMessage(session.character.pk, GameMessageID.PLAYER_READY) conn.send(player_ready)
def allow_packet(self, data: ReadStream, conn: Connection): """ Allows a packet """ packet = Packet.deserialize(ReadStream(data), self.server.packets) if not getattr(packet, 'allow_without_session') and not self.get_session( conn.get_address()): self.destroy_session(conn)
def login_request(self, packet: 'LoginRequest', conn: Connection): """ Handles a login request """ token = '' account = self.server.handle_until_return('auth:login_user', packet.username, packet.password) if not account: auth_status = 'bad_credentials' new_subscriber = False ftp = False else: if self.server.handle_until_value('auth:check_banned', True, account, conn.get_address()): auth_status = 'banned' elif self.server.handle_until_value('auth:check_permission', False, 'login', account): auth_status = 'not_permitted' elif self.server.handle_until_value('auth:check_locked', True, account): # User has failed entering their password too many times auth_status = 'locked' elif self.server.handle_until_value('auth:check_activated', False, account): # User needs to take some step to activate their account (ex, confirm email) auth_status = 'not_activated' elif self.server.handle_until_value('auth:check_schedule', False, account): # Schedule set up by parent for time allowed to play does not allow play at this time auth_status = 'schedule_blocked' else: auth_status = 'success' if auth_status == 'success': token = self.server.handle_until_return('session:new_session', account, conn.get_address()) new_subscriber = self.server.handle_until_value('auth:new_subscriber', True, account) ftp = self.server.handle_until_value('auth:free_to_play', True, account) permission_error = 'You do not have permission to log in to this server' if auth_status == 'not_permitted' else '' char_ip = self.server.config['servers']['char']['public_host'] chat_ip = self.server.config['servers']['chat']['public_host'] char_port = self.server.config['servers']['char']['public_port'] chat_port = self.server.config['servers']['chat']['public_port'] res = LoginResponse(auth_status, token, char_ip, chat_ip, char_port, chat_port, new_subscriber, ftp, permission_error) conn.send(res)
def verify_session(self, packet: 'SessionInfo', conn: Connection): """ Verifies a session """ try: session = Session.objects.get( account__user__username=packet.username) self.session_cache[conn.get_address()] = session except Session.DoesNotExist: session = None if not session or \ not bcrypt.checkpw(packet.session_key.encode('latin1'), session.token) or \ now() - session.created > timedelta(days=1): self.destroy_session(conn) else: # Client address may change when switching servers session.ip = conn.get_address()[0] session.port = conn.get_address()[1] session.save() self.server.handle('session:verify_success', session, conn)
def _on_new_conn(self, data: ReadStream, conn: Connection) -> None: log(LOGGINGLEVEL.WORLD, (" [" + self.zone_id + "] New Connection from: " + conn.get_address()[0] + ":" + str( conn.get_address()[1]))) session = Session() session.ip = conn.get_address()[0] session.port = conn.get_address()[1] session.connection = conn session.first_validate = True address = (str(conn.get_address()[0]), int(conn.get_address()[1])) uid = str(uuid3(NAMESPACE_DNS, str(address))) self._sessions[uid] = session
def add_participant(self, server, conn: Connection) -> None: log(LOGGINGLEVEL.REPLICADEBUG, " added connection: " + str(conn.get_address()[0])) self._participants.add(conn) for obj in self._network_ids: if obj.important: self._construct(obj, new=False, recipients=[conn]) address = (str(conn.get_address()[0]), int(conn.get_address()[1])) uid = str(uuid3(NAMESPACE_DNS, str(address))) session = server.get_session(uid) obj_load = ServerDoneLoadingAllObjects.ServerDoneLoadingAllObjects( objid=int(session.current_character.object_id), message_id=0x66a) conn.send(obj_load, reliability=Reliability.ReliableOrdered) player_ready = PlayerReady.PlayerReady(objid=int(session.current_character.object_id), message_id=0x1fd) conn.send(player_ready, reliability=Reliability.ReliableOrdered) for obj in self._network_ids: if obj.important is not True: self._construct(obj, new=False, recipients=[conn], reliability=Reliability.Reliable)
def request_use(self, packet, conn: Connection, stream: ReadStream): """ Handles the request use game message """ session = self.server.handle_until_return('session:get_session', conn.get_address()) clone = self.server.handle_until_return('world:get_clone', session.clone) char = self.server.handle_until_return( 'char:front_char', session.account.character_set.all()) char_missions = self.server.handle_until_return( 'char:get_missions', char.pk) multiinteract = stream.read(c_bit) multiinteract_id = stream.read(c_uint32) multiinteract_type = stream.read(c_int) objid = stream.read(c_int64) secondary = stream.read(c_bit) print(f'Multi interact: {multiinteract}') print(f'Multi interact ID: {multiinteract_id}') print(f'Multi interact type: {multiinteract_type}') print(f'Object ID: {objid}') print(f'Secondary: {secondary}') objs = [x for x in clone.objects if x.objid == objid] if objs: obj = objs[0] if char_missions: missions = self.server.handle_until_return( 'world:missions_for_lot_target', obj.lot) for char_mission in [x for x in char_missions if x.state == 2]: missions2 = [ x for x in missions if x[0] == char_mission.mission ] if missions2: mission = missions2[0] self.server.handle('char:complete_mission', char.pk, mission[0]) msg = ServerGameMessage( packet.objid, GameMessageID.OFFER_MISSION, c_int(mission[0]) + c_int64(objid)) conn.send(msg) return missions = self.server.handle_until_return( 'world:missions_for_lot', obj.lot) missions = [ x for x in missions if x[0] not in [y.mission for y in char_missions if y.state == 8] ] if missions: mission = missions[0] msg = ServerGameMessage(packet.objid, GameMessageID.OFFER_MISSION, c_int(mission[0]) + c_int64(objid)) conn.send(msg)
def handshake(self, packet: 'HandshakePacket', conn: Connection): """ Makes a handshake with a client """ remote_conn_type = 0x01 if self.server.type == 'auth' else 0x04 conn.send(HandshakePacket(remote_conn_type))