Example #1
0
def handle_chat(pak, state):
    data = json.loads(pak.json_data)

    if pak.position == clientbound.play.ChatMessagePacket.Position.SYSTEM and (
            data.get("translate", "") == "commands.message.display.incoming"
            or data.get("translate", "") == "chat.type.announcement"):
        # Whispers and such
        name = data["with"][0]["text"]
        message = data["with"][1]["text"]
    elif pak.position == clientbound.play.ChatMessagePacket.Position.CHAT:
        # Chat message
        name = data["with"][0]["insertion"]
        message = data["with"][1]
    else:
        return

    if message != state["sleep_command"]:
        return

    print_timestamped("Sleep requested by " + name)

    # Notify main loop that sleep has been requested
    state["sleep_requested"] = True

    # Disconnected from server
    state["connection"].disconnect(immediate=True)
    state["connected"] = False
Example #2
0
def setup_connection(address, port, version, auth_token, state, username=None):
    connection = Connection(
        address,
        port,
        auth_token=auth_token,
        initial_version=version,
        username=username,
        handle_exception=partial(handle_exception, state=state),
    )
    print_timestamped(f"Connecting to {address}:{port}")

    # Cast rod on join
    connection.register_packet_listener(partial(handle_join_game, state=state),
                                        clientbound.play.JoinGamePacket)

    # Reel in and recast rod on bobber splash
    connection.register_packet_listener(
        partial(handle_sound_play, state=state),
        clientbound.play.SoundEffectPacket)

    if state["sleep_helper"]:
        # Disconnect for a while when people need to sleep
        connection.register_packet_listener(partial(handle_chat, state=state),
                                            clientbound.play.ChatMessagePacket)

    # Handle disconnects
    connection.register_packet_listener(partial(handle_dc, state=state),
                                        clientbound.play.DisconnectPacket)
    connection.register_packet_listener(partial(handle_dc, state=state),
                                        clientbound.login.DisconnectPacket)

    return connection
Example #3
0
def handle_exception(exc, sysstat, state):
    """Handle exceptions in the connection"""
    if isinstance(exc, KeyboardInterrupt):
        return
    print_timestamped("Exception handled: ", exc)
    print_timestamped(sysstat)

    # Disconnected from server - restart connection
    state["connection"].disconnect(immediate=True)
    state["connected"] = False
Example #4
0
def handle_sound_play(pak, state):
    if pak.sound_id != state["bobber_splash_id"]:
        return

    # Reel in and cast
    use_item(state)
    use_item(state)

    state["recently_cast"] = True
    state["amount_caught"] += 1

    if state["print_output"]:
        print_timestamped("Caught one!")
Example #5
0
def handle_join_game(pak, state):
    print_timestamped("Connection established")

    # Cast the rod
    use_item(state)

    # Greet the server
    if state["greet_message"] != "" and state["greet_message"] is not None:
        greet_packet = serverbound.play.ChatPacket()
        greet_packet.message = state["greet_message"]
        state["connection"].write_packet(greet_packet)

    # Inform the server of the sleep command
    if state["sleep_helper"]:
        sleep_packet = serverbound.play.ChatPacket()
        sleep_packet.message = state["sleep_message"]
        state["connection"].write_packet(sleep_packet)
Example #6
0
def loop_realm_address(auth_token, realm_name):
    # Getting ip and port of realm until successful
    while True:
        try:
            address, port = get_realm_address(
                name=auth_token.profile.name,
                uuid=auth_token.profile.id_,
                access_token=auth_token.access_token,
                realm_name=realm_name,
            )
        except ValueError as e:
            # Could not find realm with given name
            print_timestamped(str(e))
            sys.exit(1)
        except RuntimeError as e:
            # Error in request
            print_timestamped(str(e))
            sleep(5)
        else:
            # Got ip and port
            return address, port
Example #7
0
def main():
    options = get_options()

    try:
        CONFIG = read_config(fp=options.config)
    except RuntimeError as e:
        print(e)
        sys.exit(1)
    finally:
        options.config.close()

    OPTIONS = CONFIG["options"]
    HOST = CONFIG["host"]

    # Get sound id and close file pointer
    splash_id = get_bobber_splash_id(HOST["version"], fp=options.gamedata)

    # Read stored profile
    has_token, user_data = read_profile(OPTIONS["profile_path"])

    if not HOST["offline"]:
        # Validate/refresh token
        if has_token:
            auth_token = create_auth_token(user_data)

        # Client has no token, or the token was invalid
        if not has_token or not auth_token:
            print("Authenticate with username+password")
            auth_token = authenticate_user(user_data)

        # Update profile and write to disk
        update_profile(OPTIONS["profile_path"], user_data, auth_token)
        username = auth_token.profile.name
    else:
        print("Playing in offline mode - skipping authentication")
        if OPTIONS.get("username", None) is None:
            OPTIONS["username"] = input(
                "What username do you want to play with? ")
        auth_token = None
        username = OPTIONS["username"]

    # Program state
    start_time = datetime.now()
    timeouts = []

    # Stores the potential durability that has been taken off the rod due to timeouts
    # minus the durability recovered by mending
    durability_count = 0

    state = {
        "amount_caught": 0,
        "recently_cast": False,
        "sleep_requested": False,
        "connection": None,
        "connected": False,
        "bobber_splash_id": splash_id,
    }

    state.update(OPTIONS)

    try:
        # Reconnect indefinitely
        while True:
            try:
                address, port = get_host_address(HOST, auth_token)
            except RuntimeError as e:
                print(e)
                sys.exit(1)

            # Establish connection
            state["connection"] = setup_connection(
                address=address,
                port=port,
                version=HOST["version"],
                auth_token=auth_token,
                state=state,
                username=username,
            )
            try:
                state["connection"].connect()
            except ConnectionRefusedError as e:
                print(e)
                sys.exit(1)

            state["connected"] = True

            while state["connected"]:
                # Check for timeouts, fishing is handled by eventlisteners
                state["recently_cast"] = False
                check_for_sleep(OPTIONS["fish_timeout"], state)
                if not state["recently_cast"]:
                    # Timed out
                    if durability_count >= OPTIONS["durability_threshold"]:
                        # Log out to save the rod
                        print_timestamped(
                            "Too many timeouts; rod has, at worst, taken "
                            f"~{durability_count} "
                            "points of durability. Logging out to save it.")

                        # Ugly hack to display results of session before exiting
                        raise EndFishingSession

                    print_timestamped(
                        f"Timed out; more than {OPTIONS['fish_timeout']} seconds "
                        "since last catch. Using the rod once.")
                    timeouts.append(datetime.now())
                    use_item(state)

                    # Reeling in a mob costs 5 durability
                    # This can be done at most every other use of the rod
                    durability_count += 5 / 2
                else:
                    # Fishing grants 1-6 exp which each gives 2 durability
                    # The rod cannot be repaired past fully repaired
                    durability_count = max(0, durability_count - 2)

    except (KeyboardInterrupt, EndFishingSession):
        print_timestamped("Ending session")
        state["connection"].disconnect()

        time_diff = datetime.now() - start_time
        seconds = time_diff.days * 24 * 60 * 60 + time_diff.seconds

        print("Time elapsed:", time_diff)
        print("Fish caught: " + str(state["amount_caught"]))
        print("Fish/minute: " + str(state["amount_caught"] / seconds * 60))

        if state["amount_caught"] != 0:
            print("Seconds/fish: " + str(seconds / state["amount_caught"]))
        if len(timeouts) != 0:
            print("Timeouts:")
            for t in timeouts:
                print("\t" + str(t))
        sys.exit()
Example #8
0
def handle_dc(pak, state):
    print_timestamped("DC-packet recieved, id: " + str(pak.id))

    # Disconnected from server - restart connection
    state["connection"].disconnect(immediate=True)
    state["connected"] = False