#minecraft #mc #mcmodern

ozelot

处理与 MCMODERN 相关的所有网络功能

8 个重大版本发布

使用旧的 Rust 2015

0.9.0 2020年4月23日
0.8.0 2018年11月28日
0.7.0 2018年5月9日
0.5.0 2017年9月20日
0.3.0 2017年6月10日

#314游戏

每月43 次下载

CC0 许可证

175KB
3.5K SLoC

Rust 2.5K SLoC // 0.0% comments Clojure 1K SLoC // 0.0% comments

猫头鹰

猫头鹰(拼写故意)是一个 Rust 库,其目标是处理与 MCMODERN 相关的所有网络功能。为了避免重复,这里的说明保持非常基本,阅读 rustdocs 获取更多信息。


lib.rs:

(链接到仓库页面.)

这是一个用于与 Minecraft 协议(仅限 MCMODERN,不包括 MCPE)交互的库。

它主要是一个低级库,其目标是处理所有网络相关功能,但仅限于此。例如,这个库不支持 Rust 标准中未找到的任何类型,这导致包含复合数据类型的某些数据包的复杂字段未由该库序列化,而是将原始二进制数据交给该库的消费者进行解析。一个例子是包含 NBT 数据的数据包,数据包被读取,但 NBT 数据以任何方式都不由该库解析。你可能想查看每个数据包的含义,这些信息已在 wiki.vg 上记录。特别是 协议文档 可能是使用此库的必要伴侣。

目前库完全同步,要求消费者按照他们希望的任何方式处理并发。添加异步 API 会很酷,也许会使用 mio。

该库名义上支持 MCMODERN 中使用的每个数据包,但目标仍然是添加更多辅助函数和其他有用功能。库中仍然存在许多错误和不便之处,其中添加更改或辅助函数会很好。如果你发现任何错误或改进建议,无论多么微不足道,请将其发布在错误跟踪器上。

该库尚未发布任何稳定版本,不是因为它可能包含错误(它肯定包含错误),而是因为 API 可能会未经警告地进行重大重构。

示例

以认证用户身份连接到远程服务器,打印所有聊天消息,然后回显看似不是我们写的消息(否则我们会进入无限回声循环。)

(请参阅 textclient 示例以获取完整版本。)

use std::thread;
use std::time::Duration;
use ozelot::{mojang, Client, serverbound, utils};
use ozelot::clientbound::ClientboundPacket;

let auth = mojang::Authenticate::new("[email protected]".to_string(),
                                     "my_password".to_string())
    .perform().unwrap();


/* By using connect_authenticated, auto_handle will be true and thus ozelot
 * will respond to keepalives automatically */
let mut client = Client::connect_authenticated("minecraft.example.com",
                                               25565, &auth).unwrap();

let username = auth.selectedProfile.name;

'main: loop {
    let packets = client.read().unwrap();
    for packet in packets {
        match packet {
        ClientboundPacket::PlayDisconnect(ref p) => {
            println!("Disconnected, reason: {}",
                     utils::chat_to_str(p.get_reason()).unwrap());
            break 'main;
        },
        ClientboundPacket::ChatMessage(ref p) => {
            let msg = utils::chat_to_str(p.get_chat()).unwrap();
            println!("{}", msg);
            if !msg.contains(&username) {
                /* Since we don't want an infinite loop, we don't echo back
                 * our own messages. We say that a received message wasn't
                 * written by us if it doesn't contain our username
                 *
                 * Note that this echoes back the raw chat message, that is
                 * playername and everything, and also non-chat messages. */
                let response = serverbound::ChatMessage::new(msg);
                let _: usize = client.send(response).unwrap();
            }
        },
        /* We throw away all other packets */
        _ => (),
        }
    }
    /* Make sure we don't consume the entire CPU trying to check if new packets have arrived */
    thread::sleep(Duration::from_millis(50));
}

依赖关系

~12–22MB
~352K SLoC