5个版本
0.1.3 | 2024年4月20日 |
---|---|
0.1.2 | 2024年2月28日 |
0.1.1 | 2024年2月19日 |
0.1.0 | 2024年2月1日 |
0.0.1 | 2024年1月19日 |
在文本处理类别中排名第1306
295KB
7K SLoC
S&F API 🧙🏽♂️
概述
这是一个正在进行的非官方API,用于与Shakes & Fidget服务器通信。
使用此API的基本示例可能是
// The session is what manages any data relevant to communicating with the
// server accross commands
let mut session = CharacterSession::new(
"username",
"password",
ServerConnection::new("f1.sfgame.net").unwrap(),
);
// The login response will contain information about our character and the
// server
let login_respone = session.login().await.unwrap();
// The game state is what we can use to look at all the data from the
// server in a more comprehensible way.
let mut game_state = GameState::new(login_respone).unwrap();
// Now we are all set to do whatever we want.
let best_description = "I love sushi!".to_string();
// Just like above we get a response. This time however, it will only
// contain a partial response with things, that might have changed
let response = session
.send_command(&Command::SetDescription {
description: best_description.clone(),
})
.await
.unwrap();
// As such, we should use update on our existing game state
game_state.update(response).unwrap();
// Lets make sure the server actually did what we told him
assert!(game_state.character.description == best_description);
println!("YAY, it worked! 🎉🍣🍣🍣🎉");
如果您使用的是单点登录的S&F账户,可以像这样使用它
let account = SFAccount::login(
"username".to_string(),
"password".to_string()
).await.unwrap();
for mut session in account.characters().await.unwrap().into_iter().flatten()
{
// You can use the sessions, that the account returns like
// a normal (logged out) session now
let response = session.login().await.unwrap();
let mut game_state = GameState::new(response).unwrap();
}
安装
您只需在您的Rust项目中运行以下命令
cargo add sf-api
指南
在您的账户被封禁之前,请注意以下几点
- 永远不要无限循环地运行发送命令到服务器的任何操作而不加延迟。这会立即使您的账户/ip在监控流量和系统的危险区域排名第一位。根据您的连接和账户数量,这可能会被分类为DDOS攻击。只需在某个地方放置异步睡眠并在设置的数量后退出。已警告您
- 正常网络客户端会定期向服务器发送更新命令。这是向服务器发出信号,表明您的账户仍然存在,并且应该更新您在公会屏幕上的最后活动时间。请注意,登录本身不会自动更新此时间。正如您所猜测的,如果账户始终活跃但没有发送任何更新命令,那就很奇怪了,因此偶尔发送它们。
- 此库不会检查您的角色应该有权访问哪些API调用。如果您尝试装备尚未解锁的同伴或尚未解锁的堡垒宝箱中的角色,那将是您的责任。命令枚举通过强制通过Rust类型系统进行有效输入来防止您自我伤害,但任何在此之上的逻辑在性能/复杂性/错误方面都是不值得的。
- 类似于前一点,除了处理服务器错误外,解析响应时不会检查响应是否是您请求的正确响应。如果服务器向您发送一个荣誉室响应,当您发送完成任务命令时,这将是服务器错误(我从未见过),将会被默默忽略。在您尝试在接下来的12小时内循环开始新的任务之前,您应该检查一下您的命令是否成功。特别是跨越时区的时间敏感信息可能会让您感到惊讶。
- 原始S&F API从1开始索引而不是0。这非常不直观且容易出错,如果您只想使用现有Vec/Array的索引作为命令输入。因此,我决定隐藏这个事实,并手动在命令中增加提供的索引1。这也使得无法提供过低的输入,但遗憾的是Rust的类型系统无法为值提供上限,所以您仍然可以提供过大的值。请尽量不要这样做,因为这将是任何官方版本中都不存在的错误,并可能导致开发团队对您的账户感兴趣,如果他们想调查以前未见过的错误。
性能
您不需要关心性能,因为您不应该在需要考虑这个问题的规模上运行这个库。忽略这个事实,这个库在构建时考虑了高可扩展性和低资源消耗。在我的机器上解析登录游戏状态将小于1毫秒,之后的完整更新将小于100微秒。
我已经通过重用之前的容器来尽量减少分配。此外,HashMap<&str,&str>
主要被[T;K]
替换,其中U as usize
用于索引vec(主要通过某些get函数大量抽象)。
响应只是原始HTML响应体,包含一个~HashMap<&str,&str>
,该HashMap引用了它。这是完全安全的,每个请求节省数百次分配,并使所有内容都集中在一个地方,便于缓存。
所有内容都解析成期望的确切数据类型,这也捕获了与只是i64化每个int相比奇怪的或意外的错误。请注意,我不期望永远维护这个(我首先不玩这个游戏),所以很多这样的内容都显示为日志警告,并默认为某些值,而不是返回错误。这样,您就不会因为某处蘑菇的价格为负而陷入困境。请随意在杂项函数中将warn!改为panic!来改变这种行为。
Rust功能
这个crate支持serde
(反)序列化角色状态和S&F账户(sso
),位于相应的功能标志之后。请注意,sso
内部依赖于serde crate通过json与服务器通信。
设计
该API已被设计为保持会话和角色状态分离。为什么?主要是因为我可以序列化/反序列化响应并“回放”它们进行独特的事情,并减少服务器请求。
此外,这种架构在您有多个想要使用会话的东西时更容易使用,因为它们不需要等待更新完成就可以再次发送。
请注意,我认为这并不完美。特别是对于基本用例,这比有帮助还让人烦恼。我可能在某个时候添加一个统一的版本。
大约有 ~500 个属性需要解析。这是一笔如此巨大的数据量,所以我选择了直接在 GameState 中提供这些字段的原始访问权限,而不是为所有这些提供 get() 函数。这意味着如果你想,你可以创建带有可变引用的无效游戏状态,但这在我看来,那将是你的错误,而不是我的。
我可能考虑在将来使用类似 derive_getters 的东西,但我并不真正关心这个问题,而且它会增加编译时间,所以现在你只能访问字段。
依赖关系
~8–21MB
~333K SLoC