#gsi #networking #api-bindings #cs2 #cs2-gsi

gsi-cs2

提供用于序列化Counter Strike 2 GSI数据的结构

2个版本

0.1.1 2023年11月3日
0.1.0 2023年11月3日

#1194 in 编码

MIT 许可证

26KB
488

gsi-cs2-rs

提供用于序列化Counter Strike 2 GSI数据的结构

信息

文档可以在这里找到。

示例可以在这里找到。

GSI 维基指南,它有些过时,但“这没问题”。

示例

仓库中的所有示例都使用 poem 框架服务器。但您可以使用任何其他替代方案,例如 axum :)

您可能首先想做的第一件事是启用Counter Strike 2中的GSI。在(cs2)/game/csgo/cfg文件夹中有两个文件,第一个文件以“fast”开头,如果您想在本地机器上非常快速地接收数据,则使用它;另一个文件“normal”会延迟发送数据,它可用于通过网络传输。将其中一个文件复制到(cs2)/game/csgo/cfg。然后重启游戏。

为了运行示例,您需要将其添加到Cargo.toml

[dependencies]
gsi-cs2 = "0.1.1"
poem = { version = "1.3.48", features = ["server"] }
serde_json = "1.0.87"
tokio = { version = "1.21.2", features = ["rt-multi-thread", "macros"] }
tracing-subscriber = { version = "0.3.16" }

在这个示例中,我们可以看到cs2的序列化数据

example/payload.rs | cargo run --example payload

use poem::{
    handler, listener::TcpListener, post,
    Route, Server, web::Json
};
use gsi_cs2::Body;

#[handler]
fn update(data: Json<Body>) {
    println!("{:#?}", data);
}

#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
    tracing_subscriber::fmt::init();

    let app = Route::new().at("/", post(update));

    Server::new(TcpListener::bind("127.0.0.1:3000"))
        .run(app)
        .await
}

这个示例展示了如何获取您活动武器的状态。

example/weapons.rs | cargo run --example weapons

use poem::{
    handler, listener::TcpListener, post,
    Route, Server, web::Json
};
use gsi_cs2::{
    Body, weapon::{
        WeaponState, WeaponType::*, WeaponName
    }
};

#[handler]
fn update(data: Json<Body>) {
    let map = data.map.as_ref();

    if let None = map {
        println!("You need to load map");
        return;
    }

    let player_data = data.player.as_ref();

    if let None = player_data {
        return;
    }

    let player = player_data.unwrap();
    let weapons = &player.weapons;

    print!("\x1B[2J\x1B[1;1H"); //clear

    // A loop through all weapons
    for (_k, weapon) in weapons.iter() {

        // Check if the weapon is currently active
        if let WeaponState::Active = weapon.state {
            // There is no ammunition for these types of weapons
            match weapon.r#type {
                Some(Knife)         => println!("Knife"),
                Some(Melee)         => println!("Melee"),
                Some(Fists)         => println!("Fists"),
                Some(C4)            => println!("C4"),
                Some(Grenade)       => println!("Grenade"),
                Some(Tablet)        => println!("Tablet"),
                Some(StackableItem) => println!("StackableItem"),
                _ => {
                    let deserialized_name = serde_json::to_string(&weapon.name).unwrap();
                    let weapon_type = weapon.r#type.as_ref().unwrap();

                    println!("Name: {}\nType: {:?}\nAmmo: ( {} / {} )",
                        deserialized_name, weapon_type, weapon.ammo_clip,
                        weapon.ammo_reserve
                    );

                    if weapon.ammo_clip < weapon.ammo_clip_max / 5 {
                        println!("Low on ammo. Reload.");
                    }
                }
            }
            // Check if the name of the weapon is "weapon_glock"
            if let WeaponName::Glock = weapon.name {
                println!("\nWow, is that a Glock?");
            }

            // The same, but for "weapon_usp_silencer"
            if let WeaponName::USPS = weapon.name {
                println!("\nWow, is that a USP-S?");
            }
            return;
        }

        // Checking if the weapon is reloading
        if let WeaponState::Reloading = weapon.state {
            println!("Reloading...");
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
    tracing_subscriber::fmt::init();

    let app = Route::new().at("/", post(update));

    Server::new(TcpListener::bind("127.0.0.1:3000"))
        .run(app)
        .await
}

有时,cs2可能不会在约30秒内向服务器发送数据。

依赖项

~0.4–1MB
~23K SLoC