def connectToServer(self, hostname, port, username, password, arena='#master'): """Connect to a server using the Subspace protocol. hostname and port specify the hostname/IP address and port of the server to connect to. username is the user to connect as. password is the combined password and SMod+ password seperated by an asterisk. For example, 'bot_password*smod_password'. Arena is the name of the arena to join upon entering the zone.""" CoreStack.connectToServer(self, hostname, port) self._queueSyncRequest() self.flushOutboundQueues() self.__queueLoginPacket(username, password) self.flushOutboundQueues() self.arena = arena self.__connected = True self.__last_pos_update_sent_tick = GetTickCountHs()
def waitForEvent(self): """Wait for an event. A GameEvent class instance is returned, and its type can be found in GameEvent.type. The type will be one of EVENT_Xxx. If the bot is disconnected None will be returned.""" #give the core the chance to post process the last event generated if self.__last_event_generated is not None: postprocessor = self.__event_postprocessors.get(self.__last_event_generated.type, None) if postprocessor: postprocessor(self.__last_event_generated) self.__last_event_generated = None if self.__connected is False: return None #xxx make sure large event lists dont starve the core, and i/o should probably be done between events... while True: if len(self.__event_list) > 0: # give the core the chance to preprocess events, this is needed # because if the changes were made immediately when the event was received (as opposed to when the packet is removed from queue for processing) # the core's view of the game state might be incorrect event = self.__event_list.pop(0) preprocessor = self.__event_preprocessors.get(event.type, None) if preprocessor: event = preprocessor(event) if event is None: continue self.__last_event_generated = event return event # there are no more bot-level events to process, so call the core's # own wait for event handler event = CoreStack.waitForEvent(self) if event.type == SubspaceCoreStack.EVENT_GAME_PACKET_RECEIVED: try: game_type, = struct.unpack_from("<B", event.packet) handler = self.__packet_handlers.get(game_type, None) if handler: handler(event.packet) except (IndexError, struct.error): if game_type: print 'Structure error in SubspaceBot packet handler: %02X' % game_type print event.packet.encode('hex') # map core stack events to game stack events elif event.type == SubspaceCoreStack.EVENT_TICK: self.__addPendingEvent(GameEvent(EVENT_TICK)) elif event.type == SubspaceCoreStack.EVENT_DISCONNECT: self.__addPendingEvent(GameEvent(EVENT_DISCONNECT))
def __init__(self, owners_list=None, description=None, debug=False): """Initialize the CoreStack class. If debug is set debugging messages will be displayed.""" CoreStack.__init__(self, debug) self.__debug = debug self.__players_by_pid = {} # pid : Player self.__players_by_name = {} # name: Player self.__event_list = [] # make the argument into a list if it isnt, xxx, maybe there is a cleaner way to do this if type(owners_list) == type(''): owners_list = [owners_list] self.__owners_list = owners_list # generate a valid mid hash_string = os.name + sys.platform + socket.getfqdn() self.machine_id, self.permission_id = struct.unpack_from('II', hashlib.md5(hash_string).digest()) self.machine_id = self.__makeValidMachineID(self.machine_id) self.players_here = [] self.__players_by_name = {} self.__players_by_pid = {} self.__last_event_generated = None self.pid = None self.name = None self.__cmd_about_description = description self.arena = None self.__command_dict = {} # the ships position data self.ship = None self.x_pos = 512 * 16 self.y_pos = 512 * 16 self.x_vel = 0 self.y_vel = 0 self.status = 0 self.bounty = 0 self.energy = 0 self.rotation = 0 self.__timer_list = [] # Timer() self.__next_timer_id = 0 self.__last_timer_expire_tick = GetTickCountHs() self.__command_die_id = self.registerCommand('!die', 'Stop the bot', owners_list) self.__command_help_id = self.registerCommand('!help', 'Show help', None) if description: self.__command_about_id = self.registerCommand('!about', 'Show information about the bot', None) #: Event preprocessors can return a new event to pass on to the bot, or None if no event should be generated self.__event_preprocessors = { EVENT_ENTER : self.__eventEnterPreprocessor, EVENT_LEAVE : self.__eventLeavePreprocessor, EVENT_TICK : self.__eventTickPreprocessor, EVENT_CHANGE: self.__eventChangePreprocessor, EVENT_DISCONNECT : self.__eventDisconnectPreprocessor, EVENT_COMMAND : self.__eventCommandPreprocessor, EVENT_ARENA_LIST : self.__eventArenaListPreprocessor, } # event post processors self.__event_postprocessors = { # empty for now } # setup the appropriate handlers self.__packet_handlers = { 0x03 : self.__handlePlayerEnteredPacket, 0x04 : self.__handlePlayerLeftPacket, 0x05 : self.__handleLargePositionUpdatePacket, 0x06 : self.__handleKillPacket, 0x07 : self.__handleMessagePacket, 0x0A : self.__handleLoginResponsePacket, 0x0B : self.__handleGoalPacket, 0x0D : self.__handleFreqchangePacket, 0x1C : self.__handleShipChangePacketSelf, 0x1D : self.__handleShipchangePacket, 0x27 : self.__handlePositionUpdateRequest, 0x28 : self.__handleSmallPositionUpdatePacket, 0x2F : self.__handleArenaListPacket, 0x31 : self.__handleLoginPacket, }