LinSoap

LinSoap

Null

Linux also needs Arknights one-click harvesting.

Recently, I fully switched from Windows to the Manjaro system, and I have to say it is really user-friendly. After switching to Manjaro, an important issue was how to run multiple instances of MAA Arknights for harvesting, as I need to harvest twice a day, and manually managing multiple accounts is too cumbersome.

Emulator#

First, MAA supports three types of Linux emulators: one is AVD, one is Waydroid, and one is redroid. I chose to use AVD since it has Google support and is relatively easier to use. The concept of containerization in Waydroid is good, but it seems to have no support for NVIDIA cards, so I passed on that.
AVD is integrated into Android Studio. First, download Android Studio from the AUR repository (do not use the flatpak repository, as containerization will make subsequent command line launches of the emulator very troublesome), configure the proxy, and after downloading the SDK, select

virtualdevice

Of course, you can also choose to use AVD directly without Android Studio, but Android Studio provides a graphical interface that saves a lot of trouble.
Create a new device, set the resolution to 16:9 and greater than 720p, select the framework (R - 30 - x86 - Android 11.0), allocate appropriate configurations for each emulator based on your setup, and remember to enable hardware acceleration. At this point, you have successfully created an emulator supported by MAA, and you can install Arknights via adb.

newdevice

selectimage

detailsetting

Opening Android Studio every time to launch the emulator is very troublesome; in fact, you can directly open the emulator from the command line.

~/Android/Sdk/emulator/emulator -list-avds // Get the list of emulators
~/Android/Sdk/emulator/emulator -avd emulator_name // Start the specified emulator 

MAA Configuration#

After downloading and extracting MAA from the official website, several methods are provided to call MAA: one is maa-cli, and the other is the Python interface, which are the AppImage file and the Python folder in the root directory of the extracted package. I looked at the configuration of maa-cli, and configuring tasks and running multiple instances is quite troublesome, so I chose to use the Python interface to start MAA. Open the sample.py file in the Python folder and modify it to complete the task configuration. First, configure the adb address and adb device name, then add tasks and set task parameters according to the documentation based on your needs. You can directly run python sample.py to start harvesting.
Every time a task is executed, having to modify the py file is very troublesome, so you can accept parameters when executing Python to choose which tasks to execute. Modify this sample file; below is my task configuration.

import json
import pathlib
import time
import argparse

from asst.asst import Asst
from asst.utils import Message, Version, InstanceOptionType
from asst.updater import Updater
from asst.emulator import Bluestacks

@Asst.CallBackType
def my_callback(msg, details, arg):
    m = Message(msg)
    d = json.loads(details.decode('utf-8'))

    print(m, d, arg)

if __name__ == "__main__":
    # Create ArgumentParser object
    parser = argparse.ArgumentParser(description='Arknights Assistant Script')

    # Add enable options for each task
    parser.add_argument('--start-up', action='store_true', help='Enable StartUp task')
    parser.add_argument('--recruit', action='store_true', help='Enable Recruit task')
    parser.add_argument('--infrast', action='store_true', help='Enable Infrast task')
    parser.add_argument('--visit', action='store_true', help='Enable Visit task')
    parser.add_argument('--mall', action='store_true', help='Enable Mall task')
    parser.add_argument('--fight', action='store_true', help='Enable Fight task')
    parser.add_argument('--award', action='store_true', help='Enable Award task')
    parser.add_argument('--stage', type=str, default=None, help='Specify the stage for Fight task')

    args = parser.parse_args()

    # Set the path for storing dll files and resources
    path = pathlib.Path(__file__).resolve().parent.parent

    # Set the updater's path and target version and update
    # Updater(path, Version.Stable).update()

    Asst.load(path=path)

    asst = Asst()

    asst.set_instance_option(InstanceOptionType.touch_type, 'maatouch')

    # Please configure adb environment variables or modify to the path of the adb executable
    if asst.connect('/home/linsoap/Android/Sdk/platform-tools/adb', 'emulator-5554'):
        print('Connection successful')
    else:
        print('Connection failed')
        exit()

    # Please refer to docs/integration_document.md for tasks and parameters

    if args.start_up:
        asst.append_task('StartUp', {
            'client_type': 'Official',
            'start_game_enabled': True
        })

    if args.recruit:
        asst.append_task('Recruit', {
            'enable': True,
            'select': [4],
            'confirm': [3, 4],
            'times': 4
        })

    if args.infrast:
        asst.append_task('Infrast', {
            'enable': True,
            'facility': [
                "Mfg", "Trade", "Control", "Power", "Reception", "Office", "Dorm"
            ],
            'drones': "Money"
        })

    if args.visit:
        asst.append_task('Visit')

    if args.mall:
        asst.append_task('Mall', {
            'shopping': True,
            'buy_first': ['Recruit Permit', 'Lungmen Coins'],
            'blacklist': ['Furniture', 'Carbon'],
        })

    if args.fight:
        fight_params = {'enable': True}

        if args.stage:
            fight_params['stage'] = args.stage

        asst.append_task('Fight', fight_params)

    if args.award:
        asst.append_task('Award', {
            'enable': True,
        })

    asst.start()

    while asst.running():
        time.sleep(0)

The Updater class currently has some issues, so it is recommended to comment it out for now and uncomment it once the bug is fixed.
After installing the above configuration, you can use the following command to start MAA.

python emulator-54.py --start-up --recruit --infrast --visit --mall --fight --stage AP-5 --award

One-Click Script#

One-Click Start Emulator#

To achieve one-click harvesting, a script is needed to start multiple emulators and MAA with one click.
First, copy multiple sample.py files and modify the adb names within them.
The first issue encountered is that the adb names for AVD are not fixed but are assigned based on the launch order. I have two official accounts and one B server account, and random adb names can cause the StartUp task to fail. Therefore, when running multiple instances, it is necessary to specify ports so that the corresponding clients can execute the respective tasks.

#!/bin/bash

while [ "$#" -gt 0 ]; do
  case "$1" in
    --start)
      shift
      while [ "$#" -gt 0 ]; do
        case "$1" in
          --all)
            echo "Starting all emulators..."
            /home/linsoap/Android/Sdk/emulator/emulator -avd aknz -ports 5554,5555 &
            /home/linsoap/Android/Sdk/emulator/emulator -avd aknz_1 -ports 5556,5557 &
            /home/linsoap/Android/Sdk/emulator/emulator -avd mrfz -ports 5558,5559 &
            shift
            ;;
          --list)
            echo "Available emulators:"
            /home/linsoap/Android/Sdk/emulator/emulator -list-avds
            shift
            ;;
          -*)
            echo "Unknown option: $1"
            exit 1
            ;;
          *)
            echo "Starting emulator: $1"
            /home/linsoap/Android/Sdk/emulator/emulator -avd "$1" &
            shift
            ;;
        esac
      done
      ;;
    --stop)
      shift
      while [ "$#" -gt 0 ]; do
        case "$1" in
          --all)
            echo "Stopping all emulators..."
            /home/linsoap/Android/Sdk/platform-tools/adb -s emulator-5554 emu kill
            /home/linsoap/Android/Sdk/platform-tools/adb -s emulator-5556 emu kill
            /home/linsoap/Android/Sdk/platform-tools/adb -s emulator-5558 emu kill
            shift
            ;;
          -*)
            echo "Unknown option: $1"
            exit 1
            ;;
          *)
            echo "Stopping emulator: $1"
            /home/linsoap/Android/Sdk/platform-tools/adb -s "$1" emu kill
            shift
            ;;
        esac
      done
      ;;
    -*)
      echo "Unknown option: $1"
      exit 1
      ;;
  esac
done

The above is a one-click start script generated by ChatGPT. You can let GPT generate scripts according to your own needs.

  • Start all emulators: ./your_script.sh --start --all
  • Start a specific emulator: ./your_script.sh --start <emulator_name>
  • View the list of available emulators: ./your_script.sh --start --list
  • Stop all emulators: ./your_script.sh --stop --all
  • Stop a specific emulator: ./your_script.sh --stop <emulator_name>

One-Click Start MAA#

After modifying sample.py to accept parameters for selecting enabled tasks, writing a one-click start MAA script becomes easy. You can also use ChatGPT to generate the script based on your requirements. Below is my script.

#!/bin/bash

# Set the list of Python script files to execute
python_scripts=("emulator-54.py" "emulator-56.py" "emulator-58.py")

# Default parameter values
all_flag=false
only_fight_flag=false
unfight_flag=false
stage_value=""

# Parse command line parameters
while [ "$#" -gt 0 ]; do
  case "$1" in
    --all)
      all_flag=true
      ;;
    --only-fight)
      only_fight_flag=true
      ;;
    --unfight)
      unfight_flag=true
      ;;
    -stage|--stage)
      shift
      stage_value="$1"
      ;;
    *)
      echo "Unknown option: $1"
      exit 1
      ;;
  esac
  shift
done

# Check parameter combinations
if [ "$all_flag" = true ] && [ "$only_fight_flag" = true ]; then
  echo "Cannot use --all and --only-fight together."
  exit 1
fi

# Construct command line argument string
args="--start-up"

if [ "$all_flag" = true ] || [ "$only_fight_flag" = true ]; then
  args+=" --recruit --infrast --visit --mall --award --fight"
fi
if [ "$only_fight_flag" = true ]; then
  args+=" --fight"
fi

if [ -n "$stage_value" ]; then
  args+=" --stage $stage_value"
fi

# Execute three Python commands serially
for script in "${python_scripts[@]}"; do
  # Output the current task being executed
  echo "Executing tasks in $script"

  # Execute serially
  python "$script" $args & echo "Finished tasks in $script" || echo "Failed to execute tasks in $script"
done

echo "All tasks completed"

This script supports the following commands:

  • --all: Start all tasks, including --start-up, --recruit, --infrast, --visit, --mall, --award, and --fight.
  • --only-fight: Start all tasks, including --start-up and --fight.
  • --unfight: Start all tasks but exclude --fight.
  • --stage <value> or -stage <value>: Specify the value for the task stage.

Playing Arknights#

id

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.