예제 #1
0
 def _process_inventory_transaction(self, packet: GamePacket,
                                    addr: Address) -> None:
     player = self._session_manager[addr]
     if packet.transaction_type == InventoryTransactionType.USE_ITEM:
         if packet.data.action_type == UseItemActionType.BREAK_BLOCK:
             self._world.perform(
                 action_factory.create(ActionType.BREAK_BLOCK,
                                       player.entity_runtime_id,
                                       packet.data.position))
         elif packet.data.action_type == UseItemActionType.CLICK_BLOCK:
             if packet.data.item_in_hand.type != ItemType.AIR:
                 self._world.perform(
                     action_factory.create(
                         ActionType.PUT_ITEM, player.entity_runtime_id,
                         packet.data.position, packet.data.click_position,
                         packet.data.face, packet.data.hotbar_slot,
                         packet.data.item_in_hand))
     if packet.transaction_type == InventoryTransactionType.NORMAL:
         is_creative = False
         for action in packet.actions:
             if action.source_type == SourceType.CREATIVE:
                 is_creative = True
                 continue
             if action.source_type == SourceType.CONTAINER:
                 assert is_creative, packet
                 assert action.window_type == WindowType.INVENTORY, action.window_type
                 self._world.perform(
                     action_factory.create(ActionType.SET_INVENTORY,
                                           player.entity_runtime_id,
                                           action.inventory_slot,
                                           action.new_item))
예제 #2
0
    def disconnect(self, addr: Address) -> None:
        player = self._session_manager[addr]
        del self._session_manager[addr]

        if not player.has_identity:
            return

        self._world.perform(
            action_factory.create(ActionType.LOGOUT_PLAYER,
                                  player.entity_runtime_id))

        text_packet = game_packet_factory.create(
            GamePacketType.TEXT, EXTRA_DATA, TextType.TRANSLATION, False, None,
            EscapeSequence.YELLOW.value + '%multiplayer.player.left',
            (player.name, ), '')
        remove_entity_packet = game_packet_factory.create(
            GamePacketType.REMOVE_ENTITY, EXTRA_DATA, player.entity_unique_id)
        remove_player_packet = game_packet_factory.create(
            GamePacketType.PLAYER_LIST, EXTRA_DATA, PlayerListType.REMOVE,
            (PlayerListEntry(player.id, None, None, None, None), ))

        for addr, other_player in self._session_manager.find(
                lambda p: p.does_monitor(player.entity_runtime_id)):
            other_player.removed_monitored(player.entity_runtime_id)
            self.send_game_packet(text_packet, addr)
            self.send_game_packet(remove_entity_packet, addr)
            self.send_game_packet(remove_player_packet, addr)
예제 #3
0
 def _process_event_player_moved(self, event: Event) -> None:
     res_packet = game_packet_factory.create(
         GamePacketType.MOVE_PLAYER,
         EXTRA_DATA,
         event.entity_runtime_id,
         event.position,
         event.pitch,
         event.yaw,
         event.head_yaw,
         event.mode,
         event.on_ground,
         event.riding_eid,
         0 if event.mode is MoveMode.TELEPORT else None,  # TODO set value
         0 if event.mode is MoveMode.TELEPORT else None  # TODO set value
     )
     for addr, player in self._session_manager.find(lambda p: p.is_living):
         if player.entity_runtime_id != event.entity_runtime_id:
             if player.does_monitor(event.entity_runtime_id,
                                    event.position):
                 self.send_game_packet(res_packet, addr)
         else:
             if event.need_response:
                 self.send_game_packet(res_packet, addr)
             player.position = event.position
             player.yaw = event.yaw
             required_chunk = player.next_required_chunk()
             if len(required_chunk) > 0:
                 self._world.perform(
                     action_factory.create(ActionType.REQUEST_CHUNK,
                                           required_chunk, None))
예제 #4
0
 def _process_mob_spawn(self, action: MobSpawn) -> None:
     self._process_spawn_mob(
         action_factory.create(ActionType.SPAWN_MOB, action.type,
                               action.position, action.pitch, action.yaw,
                               action.name, None),
         action.mob_id,
         # TODO pass action.monitor_nearby_chunks
     )
예제 #5
0
 def _process_move_player(self, packet: GamePacket, addr: Address) -> None:
     assert packet.entity_runtime_id == self._session_manager[
         addr].entity_runtime_id
     assert packet.mode != MoveMode.TELEPORT
     self._world.perform(
         action_factory.create(ActionType.MOVE_PLAYER,
                               packet.entity_runtime_id, packet.position,
                               packet.pitch, packet.yaw, packet.head_yaw,
                               packet.mode, packet.on_ground,
                               packet.riding_eid, False))
예제 #6
0
 def _process_mob_equipment(self, packet: GamePacket,
                            addr: Address) -> None:
     assert packet.entity_runtime_id == self._session_manager[
         addr].entity_runtime_id
     if packet.window_type == WindowType.INVENTORY:
         self._world.perform(
             action_factory.create(
                 ActionType.EQUIP, packet.entity_runtime_id,
                 packet.inventory_slot - HOTBAR_SIZE
                 if packet.inventory_slot != _NONE_INVENTORY_SLOT else None,
                 packet.hotbar_slot, packet.item))
예제 #7
0
 def _process_request_chunk_radius(self, packet: GamePacket,
                                   addr: Address) -> None:
     player = self._session_manager[addr]
     player.update_required_chunk(packet.radius)
     required_chunk = player.next_required_chunk()
     if len(required_chunk) > 0:
         self._world.perform(
             action_factory.create(ActionType.REQUEST_CHUNK, required_chunk,
                                   None))
     res_packet = game_packet_factory.create(
         GamePacketType.CHUNK_RADIUS_UPDATED, EXTRA_DATA, packet.radius)
     self.send_game_packet(res_packet, addr)
예제 #8
0
 def _process_mob_move(self, action: MobMove) -> None:
     entity_runtime_id = self._mob_id_to_entity_id[action.mob_id]
     self._process_move_mob(
         action_factory.create(
             ActionType.MOVE_MOB,
             entity_runtime_id,
             action.position,
             action.pitch,
             action.yaw,
             0.0,
             True  # TODO set value
         ))
예제 #9
0
 def _process_player_hotbar(self, packet: GamePacket,
                            addr: Address) -> None:
     player = self._session_manager[addr]
     if packet.window_type == WindowType.INVENTORY:
         self._world.perform(
             action_factory.create(
                 ActionType.SET_HOTBAR, player.entity_runtime_id,
                 packet.selected_hotbar_slot,
                 tuple(
                     self._to_internal_format_hotbar(slot)
                     for slot in packet.slots)))
     else:
         raise NotImplementedError()
예제 #10
0
 def _process_resource_pack_client_response(self, packet: GamePacket,
                                            addr: Address) -> None:
     if packet.status == ResourcePackStatus.SEND_PACKS:
         pass  # TODO do something?
     elif packet.status == ResourcePackStatus.HAVE_ALL_PACKS:
         res_packet = game_packet_factory.create(
             GamePacketType.RESOURCE_PACK_STACK, EXTRA_DATA, False, (), ())
         self.send_game_packet(res_packet, addr)
     elif packet.status == ResourcePackStatus.COMPLETED:
         player = self._session_manager[addr]
         self._world.perform(
             action_factory.create(ActionType.LOGIN_PLAYER, player.id,
                                   player.xuid == GUEST_XUID))
예제 #11
0
 def _process_event_full_chunk_loaded(self, event: Event) -> None:
     res_packet = game_packet_factory.create(GamePacketType.FULL_CHUNK_DATA,
                                             EXTRA_DATA, event.position,
                                             event.data)
     for addr, player in self._session_manager:
         if player.did_request_chunk(event.position):
             self.send_game_packet(res_packet, addr)
             player.discard_chunk_request(event.position)
             if player.next_login_sequence(event):
                 self._world.perform(
                     action_factory.create(ActionType.REQUEST_ENTITY,
                                           player.entity_runtime_id))
         elif player.entity_runtime_id == event.player_runtime_id:
             self.send_game_packet(res_packet, addr)
예제 #12
0
파일: client.py 프로젝트: nosix/PyMineHub
    def _test_perform_action(self, client: Client):
        self.assertEqual('§e%multiplayer.player.joined (Taro)', client.next_message())
        self.assertEqual(1, client.entity_runtime_id)

        expected_entities = (
            EntityInfo(
                entity_runtime_id=1,
                name='Taro',
                position=Vector3(0.5, 64.625, 0.5),
                pitch=0.0,
                yaw=0.0,
                head_yaw=0.0,
                owner_runtime_id=None
            ),
        )
        self.assertEqual(expected_entities, client.entities)

        _perform_action(client, action_factory.create(
            ActionType.MOVE_PLAYER,
            1,
            Vector3(256.0, 65.0, 256.0),
            0.0,
            0.0,
            0.0,
            MoveMode.NORMAL,
            True,
            0,
            True
        ))

        client.wait_response(60)
        expected_entity = EntityInfo(
            entity_runtime_id=1,
            name='Taro',
            position=Vector3(256.0, 64.625, 256.0),
            pitch=0.0,
            yaw=0.0,
            head_yaw=0.0,
            owner_runtime_id=None
        )
        self.assertEqual(expected_entity, client.get_entity(1))

        _perform_action(client, action_factory.create(
            ActionType.SPAWN_MOB,
            EntityType.CHICKEN,
            Vector3(256.0, 65.0, 256.0),
            0.0,
            0.0,
            None,
            1
        ))

        client.wait_response(60)
        expected_entities = (
            EntityInfo(
                entity_runtime_id=1,
                name='Taro',
                position=Vector3(256.0, 64.625, 256.0),
                pitch=0.0,
                yaw=0.0,
                head_yaw=0.0,
                owner_runtime_id=None
            ),
            EntityInfo(
                entity_runtime_id=2,
                name='anonymous:CHICKEN',
                position=Vector3(256.0, 63.0, 256.0),  # height is adjusted
                pitch=0.0,
                yaw=0.0,
                head_yaw=0.0,
                owner_runtime_id=1
            )
        )
        self.assertEqual(expected_entities, client.entities)

        _perform_action(client, action_factory.create(
            ActionType.MOVE_MOB,
            2,
            Vector3(257.0, 63.0, 254.0),
            45.0,
            90.0,
            0.0,
            True
        ))

        client.wait_response(60)
        expected_entity = EntityInfo(
            entity_runtime_id=2,
            name='anonymous:CHICKEN',
            position=Vector3(257.0, 63.0, 254.0),
            pitch=45.0,
            yaw=90.0,
            head_yaw=0.0,
            owner_runtime_id=1
        )
        self.assertEqual(expected_entity, client.get_entity(2))
예제 #13
0
 def perform_action(self, action_type: ActionType, *args, **kwargs) -> None:
     self._world.perform(action_factory.create(action_type, *args,
                                               **kwargs))
예제 #14
0
 def perform_action(self, action_or_type: Union[Action, ActionType], *args,
                    **kwargs) -> None:
     action = action_factory.create(action_or_type, *args, **kwargs) \
         if isinstance(action_or_type, ActionType) else action_or_type
     data = hexlify(dumps(action)).decode()
     self.client.execute_command('/perform {}'.format(data))