Пример #1
0
    def test_basic(self):

        emitter = Emitter()
        obs = SpyObserver()

        emitter.bind(obs)

        emitter(index=1)

        self.assertEqual(len(obs.events), 1)
        self.assertEqual(obs.events[0][0], 'on_basic')
Пример #2
0
    def test_key(self):

        emitter = Emitter()
        obs = SpyObserver()

        emitter.bind(obs)

        emitter(key='key_1', index=1)

        self.assertEqual(len(obs.events), 1)
        self.assertEqual(obs.events[0][0], 'on_key')
Пример #3
0
    def test_subscribe_basic(self):

        emitter = Emitter()
        obs = SpyObserver()

        emitter.subscribe(obs.on_no_listener)

        emitter(index=1)

        self.assertEqual(len(obs.events), 1)
        self.assertEqual(obs.events[0][0], 'on_no_listener')
Пример #4
0
    def test_both(self):

        emitter = Emitter(area='area_2')
        obs = SpyObserver()

        emitter.bind(obs)

        emitter(key='key_2', index=1)

        self.assertEqual(len(obs.events), 1)
        self.assertEqual(obs.events[0][0], 'on_both')
Пример #5
0
    def test_custom_event(self):

        emitter = Emitter(event=MyEvent)
        obs = SpyObserver()

        emitter.bind(obs)

        emitter(index=1)

        self.assertEqual(len(obs.events), 1)
        self.assertEqual(obs.events[0][0], 'on_my_event')
Пример #6
0
    def test_area(self):

        emitter = Emitter(area='area_1')
        obs = SpyObserver()

        emitter.bind(obs)

        emitter(index=1)

        self.assertEqual(len(obs.events), 1)
        self.assertEqual(obs.events[0][0], 'on_area')
Пример #7
0
    def test_subscribe_key(self):
        '''Test subscription with a key - events with keys
        other than what we subscribed to must be filtered out.'''

        emitter = Emitter(area='area_1')
        obs = SpyObserver()

        emitter.subscribe(obs.on_basic, key='a')

        emitter(key='a', index=1)
        emitter(key='b', index=2)

        self.assertEqual(len(obs.events), 1)
        self.assertEqual(obs.events[0][0], 'on_basic')
        self.assertEqual(obs.events[0][1].data['index'], 1)
Пример #8
0
    def __init__(self, server, port):

        self.server = server
        self.port = port

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.compression_threshold = -1

        self.raw_packet_emitter = Emitter(RawPacketEvent)
Пример #9
0
    def __init__(self, packet_factory, connection):

        self.packet_factory = packet_factory
        self.connection = connection

        self._state = State.HANDSHAKING

        self.keep_alive_packet = packet_factory.get_by_name(
            State.PLAY, Direction.TO_SERVER, 'keep_alive')

        self.play_state_emitter = Emitter(PacketEvent, area=State.PLAY)
        self.login_state_emitter = Emitter(PacketEvent, area=State.LOGIN)
        self.handshake_state_emitter = Emitter(
            PacketEvent, area=State.HANDSHAKING)

        self.state_change_emitter = Emitter(StateChangeEvent)

        self.play_state_emitter.bind(self)
        self.login_state_emitter.bind(self)
        self.handshake_state_emitter.bind(self)
Пример #10
0
    def __init__(self, packet_factory, connection):

        self.factory = packet_factory
        self.connection = connection

        self.tick_emitter = Emitter(TickEvent)
        self.stop_emitter = Emitter(StopEvent)

        RESPONSE_PACKETS = ('client_command', 'teleport_confirm', 'flying',
                            'position_look', 'block_dig', 'entity_action',
                            'block_place', 'chat', 'use_entity')

        for name in RESPONSE_PACKETS:

            prop_name = name + '_packet'

            packet = packet_factory.get_by_name(State.PLAY,
                                                Direction.TO_SERVER, name)

            setattr(self, prop_name, packet)

        self.dead = True
        self.respawn_timer = None

        self.facing = Facing()

        self.position = Position()
        self.velocity = Velocity()

        self.last_time = None
        self.tick_counter = 0

        self.game_info = GameInfo()

        self.dig_ticks_remaining = None

        self.respond = True
        self.responder_thread = threading.Thread(target=self.responder)

        # map of (x,z) --> chunk data
        self.chunks = {}
Пример #11
0
    def __init__(self, packet_factory, connection):

        self.packet_factory = packet_factory
        self.connection = connection

        self._state = State.HANDSHAKING

        self.keep_alive_packet = packet_factory.get_by_name(
            State.PLAY, Direction.TO_SERVER, 'keep_alive')

        self.play_state_emitter = Emitter(PacketEvent, area=State.PLAY)
        self.login_state_emitter = Emitter(PacketEvent, area=State.LOGIN)
        self.handshake_state_emitter = Emitter(PacketEvent,
                                               area=State.HANDSHAKING)

        self.state_change_emitter = Emitter(StateChangeEvent)

        self.play_state_emitter.bind(self)
        self.login_state_emitter.bind(self)
        self.handshake_state_emitter.bind(self)
Пример #12
0
class PacketReactor:
    class HandshakeState(enum.Enum):

        STATUS = 1
        PLAY = 2

    def __init__(self, packet_factory, connection):

        self.packet_factory = packet_factory
        self.connection = connection

        self._state = State.HANDSHAKING

        self.keep_alive_packet = packet_factory.get_by_name(
            State.PLAY, Direction.TO_SERVER, 'keep_alive')

        self.play_state_emitter = Emitter(PacketEvent, area=State.PLAY)
        self.login_state_emitter = Emitter(PacketEvent, area=State.LOGIN)
        self.handshake_state_emitter = Emitter(PacketEvent,
                                               area=State.HANDSHAKING)

        self.state_change_emitter = Emitter(StateChangeEvent)

        self.play_state_emitter.bind(self)
        self.login_state_emitter.bind(self)
        self.handshake_state_emitter.bind(self)

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, new_state):

        # print('State transition {} --> {}'.format(self._state, new_state))

        self.state_change_emitter(old_state=self._state, new_state=new_state)

        self._state = new_state

    @Listener(RawPacketEvent)
    def on_raw_packet(self, event):

        # print('on_raw_packet (state={}, packet_id={})'.format(self.state, event.packet_id))

        packet_clz = self.packet_factory.get_by_id(self.state,
                                                   Direction.TO_CLIENT,
                                                   event.packet_id)

        # TODO need to handle packets with 'switch' field types
        for name, xtype in packet_clz.FIELDS:

            if xtype == 'switch':
                print('Skipping packet "{}" w/ switch field.'.format(
                    packet_clz.NAME))
                return

        packet = packet_clz()
        packet.from_wire(event.data, event.length)

        if self._state == State.PLAY:

            self.play_state_emitter(key=packet.NAME, packet=packet)

        elif self._state == State.LOGIN:

            self.login_state_emitter(key=packet.NAME, packet=packet)

        elif self._state == State.HANDSHAKING:

            self.handshake_state_emitter(key=packet.NAME, packet=packet)

    def login(self, username):

        handshake_pkt = self.packet_factory.get_by_name(
            State.HANDSHAKING, Direction.TO_SERVER, 'set_protocol')()

        handshake_pkt.fields.protocolVersion = self.packet_factory.version
        handshake_pkt.fields.serverHost = self.connection.server
        handshake_pkt.fields.serverPort = self.connection.port
        handshake_pkt.fields.nextState = self.HandshakeState.PLAY.value

        self.connection.send(handshake_pkt)

        self.state = State.LOGIN

        login_pkt = self.packet_factory.get_by_name(State.LOGIN,
                                                    Direction.TO_SERVER,
                                                    'login_start')()

        login_pkt.fields.username = username
        self.connection.send(login_pkt)

    #
    # default handlers
    #
    @Listener(PacketEvent, State.LOGIN, key='encryption_begin')
    def on_encryption_begin(self, packet):

        raise NotImplementedError(
            'Encryption (aka Online Mode) is not supported at this time.')

    @Listener(PacketEvent, State.LOGIN, key='success')
    def on_login(self, event):

        packet = event.packet

        print('LOGIN: Robot "{}:{}" has been logged in.'.format(
            packet.fields.username, packet.fields.uuid))

        self.state = State.PLAY

    @Listener(PacketEvent, State.LOGIN, key='disconnect')
    def on_disconnect(self, packet):

        raise DisconnectException(packet.reason)

    @Listener(PacketEvent, State.LOGIN, key='compress')
    def on_compress(self, event):

        packet = event.packet

        self.connection.set_compression(packet.threshold)

    @Listener(PacketEvent, State.PLAY, key='keep_alive')
    def on_keep_alive(self, event):

        packet = event.packet

        response = self.keep_alive_packet()
        response.fields.keepAliveId = packet.fields.keepAliveId
        self.connection.send(response)

    @Listener(PacketEvent, State.PLAY, key='kick_disconnect')
    def on_kick_disconnect(self, event):

        raise KickedOutException(event.packet.fields.reason)
Пример #13
0
class PacketReactor:

    class HandshakeState(enum.Enum):

        STATUS = 1
        PLAY = 2

    def __init__(self, packet_factory, connection):

        self.packet_factory = packet_factory
        self.connection = connection

        self._state = State.HANDSHAKING

        self.keep_alive_packet = packet_factory.get_by_name(
            State.PLAY, Direction.TO_SERVER, 'keep_alive')

        self.play_state_emitter = Emitter(PacketEvent, area=State.PLAY)
        self.login_state_emitter = Emitter(PacketEvent, area=State.LOGIN)
        self.handshake_state_emitter = Emitter(
            PacketEvent, area=State.HANDSHAKING)

        self.state_change_emitter = Emitter(StateChangeEvent)

        self.play_state_emitter.bind(self)
        self.login_state_emitter.bind(self)
        self.handshake_state_emitter.bind(self)

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, new_state):

        # print('State transition {} --> {}'.format(self._state, new_state))

        self.state_change_emitter(old_state=self._state, new_state=new_state)

        self._state = new_state

    @Listener(RawPacketEvent)
    def on_raw_packet(self, event):

        # print('on_raw_packet (state={}, packet_id={})'.format(self.state, event.packet_id))

        packet_clz = self.packet_factory.get_by_id(
            self.state, Direction.TO_CLIENT, event.packet_id)

        # TODO need to handle packets with 'switch' field types
        for name, xtype in packet_clz.FIELDS:

            if xtype == 'switch':
                print('Skipping packet "{}" w/ switch field.'.format(
                    packet_clz.NAME))
                return

        packet = packet_clz()
        packet.from_wire(event.data, event.length)

        if self._state == State.PLAY:

            self.play_state_emitter(key=packet.NAME, packet=packet)

        elif self._state == State.LOGIN:

            self.login_state_emitter(key=packet.NAME, packet=packet)

        elif self._state == State.HANDSHAKING:

            self.handshake_state_emitter(key=packet.NAME, packet=packet)

    def login(self, username):

        handshake_pkt = self.packet_factory.get_by_name(
            State.HANDSHAKING, Direction.TO_SERVER, 'set_protocol')()

        handshake_pkt.fields.protocolVersion = self.packet_factory.version
        handshake_pkt.fields.serverHost = self.connection.server
        handshake_pkt.fields.serverPort = self.connection.port
        handshake_pkt.fields.nextState = self.HandshakeState.PLAY.value

        self.connection.send(handshake_pkt)

        self.state = State.LOGIN

        login_pkt = self.packet_factory.get_by_name(
            State.LOGIN, Direction.TO_SERVER, 'login_start')()

        login_pkt.fields.username = username
        self.connection.send(login_pkt)

    #
    # default handlers
    #
    @Listener(PacketEvent, State.LOGIN, key='encryption_begin')
    def on_encryption_begin(self, packet):

        raise NotImplementedError(
            'Encryption (aka Online Mode) is not supported at this time.')

    @Listener(PacketEvent, State.LOGIN, key='success')
    def on_login(self, event):

        packet = event.packet

        print('LOGIN: Robot "{}:{}" has been logged in.'.format(
            packet.fields.username, packet.fields.uuid))

        self.state = State.PLAY

    @Listener(PacketEvent, State.LOGIN, key='disconnect')
    def on_disconnect(self, packet):

        raise DisconnectException(packet.reason)

    @Listener(PacketEvent, State.LOGIN, key='compress')
    def on_compress(self, event):

        packet = event.packet

        self.connection.set_compression(packet.threshold)

    @Listener(PacketEvent, State.PLAY, key='keep_alive')
    def on_keep_alive(self, event):

        packet = event.packet

        response = self.keep_alive_packet()
        response.fields.keepAliveId = packet.fields.keepAliveId
        self.connection.send(response)

    @Listener(PacketEvent, State.PLAY, key='kick_disconnect')
    def on_kick_disconnect(self, event):

        raise KickedOutException(event.packet.fields.reason)