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))
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)
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))
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 )
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))
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))
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)
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 ))
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()
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))
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)
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))
def perform_action(self, action_type: ActionType, *args, **kwargs) -> None: self._world.perform(action_factory.create(action_type, *args, **kwargs))
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))