#api-client #ii #starcraft #difference #future #idiomatic #game-client

nightly sc2

StarCraft II 客户端 API 的 Rust 实现

14 个不稳定版本 (3 个破坏性版本)

使用旧的 Rust 2015

0.4.0-alpha.22018年4月15日
0.4.0-alpha.02018年4月14日
0.3.3 2018年4月15日
0.3.2 2018年3月6日
0.1.7 2018年1月12日

#692 in 异步

每月 32 次下载

MIT 许可证

10MB
7K SLoC

Build Status Crates Version License: MIT Documentation

文档(master)

这是我对StarCraft II 客户端 API的 Rust 实现。

这个软件包仍在积极开发中,我刚刚决定关于 futures 和 streams 的方向。它目前依赖于 nightly #[async]/await!,但如果足够的人支持稳定 futures,我会考虑将其作为一个特性来引入,但到目前为止,使用实验性功能而不是稳定组合器是非常方便的。

我尽量使其与 s2client-api 在功能划分上保持一致,例如 Action 接口和 Observer 接口,但也有一些不同,因为 C++ 的惯用语法和 Rust 的惯用语法并不兼容(而且有充分的理由),我还非常感兴趣于 futures-rs 的工作,并认为优雅的异步编程非常适合这个库。特别是,s2client-api 和这个库之间核心区别之一是创建机器人和事件消费。

s2client-api 使用多态来定义机器人,而 sc2-rs 则使用通道在机器人和 API 之间进行通信。让我们看看如何创建一个简单的裸机机器人。

#![feature(proc_macro, generators)]

extern crate futures_await as futures;
extern crate tokio_core;
extern crate sc2;

use futures::prelude::*;
use futures::unsync::mpsc;
use sc2::{
    agent::{AgentBuilder},
    ai::{OpponentBuilder},
    data::{GameSetup, Map, Race},
    observer::{Event, EventAck},
    
    LauncherSettings,
    MeleeBuilder,

    Result,
    Error,
};
use tokio_core::reactor;

struct SimpleBot;

impl SimpleBot {
    fn new() -> Self {
        Self { }
    }

    /// Spawn our bot's coroutine on the event loop.
    fn spawn(
        self,
        handle: &reactor::Handle,
        rx: mpsc::Receiver<(Event, EventAck)>,
    ) -> Result<()> {
        handle.spawn(self.run(rx).map_err(|e| panic!("{:#?}", e)));

        Ok(())
    }

    /// Run the bot.
    #[async]
    fn run(mut self, rx: mpsc::Receiver<(Event, EventAck)>) -> Result<()> {
        // Loop over the game events.
        #[async]
        for (e, ack) in rx.map_err(|_| -> Error { unreachable!() }) {
            match e {
                // Triggered once at the start of every game.
                Event::GameStarted => println!("Started a new game!"),
                // Triggered every time the game updates.
                Event::Step => println!("Game Stepped!"),
            
                // Ignore the other events for now.
                _ => (),
            }

            // Notify the coordinator that we have consumed this event.
            await!(ack.done())?;
        }

        Ok(())
    }
}

这个机器人简单地设计为接收游戏事件流,并打印 GameStarted 和 GameStepped 的事件消息。通常,你会使用这些事件来观察游戏状态和/或向单位下达命令。但现在,一条消息就足够了。

fn main() {
    // Create a new event loop.
    let mut core = reactor::Core::new().unwrap();
    let handle = core.handle();
    
    // Create a new Agent and set the Race to Terran.
    let mut agent = AgentBuilder::new().race(Race::Terran);

    // Instantiate our simple bot.
    let bot = SimpleBot::new();

    // Get the event stream from the Agent and spawn our bot's coroutine.
    bot.spawn(&handle, agent.take_event_stream().unwrap()).unwrap();

    // Create a match between our bot and a default SC2 built-in AI Opponent.
    let melee = MeleeBuilder::new()
        .add_player(agent)
        .add_player(OpponentBuilder::new())
        .launcher_settings(LauncherSettings::new())
        .one_and_done(GameSetup::new(Map::LocalMap(
            "maps/Ladder/(2)Bel'ShirVestigeLE (Void).SC2Map".into()
        )))
        .step_interval(1)
        .handle(&handle)
        .create()
        .unwrap();

    // Run the match to completion on the event loop.
    core.run(melee.into_future()).unwrap();
}

在这里,我们创建一个事件循环,将我们的机器人作为协程启动,并监听来自内置 SC2 AI 对手的肉搏(PvP)比赛的事件。

需要注意的是,默认的LauncherSettings只会在Windows上找到你的SC2。然而,由于无头Linux版本在调试方面并不理想,我为所有像我一样懒得双启动(或者只是更喜欢Linux)的人添加了库中对Wine的支持。好消息是,Wine确实支持SC2,坏消息是,我上次检查的时候,支持需要较新的(可能为预发布版本)Wine。

以下是一些有用的链接,可以帮助你开始使用它

依赖项

~23–32MB
~553K SLoC