Skip to content

Commit ebd984b

Browse files
committed
Initial server detection
1 parent 511d820 commit ebd984b

13 files changed

Lines changed: 545 additions & 162 deletions

File tree

src/core/config/project.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::core::backup::BackupCfg;
2-
use crate::core::mc_server::McType;
2+
use crate::core::mc_server::McChannel::Snapshot;
33
use crate::core::mc_server::McType::Java;
4+
use crate::core::mc_server::McVersion;
45
use crate::core::mc_server::base::McServer;
56
use anyhow::Result;
67
use erased_serde::Deserializer;
@@ -18,30 +19,33 @@ pub struct McServerConfig {
1819
/// 惰性更新,此处储存的值不保证最新
1920
/// 仅在读取时是最新的
2021
/// 导出配置时被最新的值替换(但不更新)
21-
pub(crate) version: Value,
22+
pub(crate) inner: Value,
2223
/// 备份配置
2324
pub backup: BackupCfg,
2425
}
2526

2627
#[derive(Serialize, Deserialize, Clone)]
2728
pub struct ProjectCfg {
2829
/// 名称
29-
name: String,
30+
pub name: String,
3031
/// 描述
31-
description: String,
32+
pub description: String,
3233
/// 创建时间
33-
creation_date: chrono::DateTime<chrono::Local>,
34-
/// 服务端类型
35-
mc_type: McType,
34+
pub creation_date: chrono::DateTime<chrono::Local>,
35+
/// 服务端版本
36+
pub version: McVersion,
3637
}
3738

3839
impl Default for ProjectCfg {
3940
fn default() -> Self {
4041
Self {
4142
name: "Example".to_string(),
42-
description: "A PacMine project".to_string(),
43+
description: "A ToyMine project".to_string(),
4344
creation_date: chrono::Local::now(),
44-
mc_type: Java("vanilla".to_string()),
45+
version: McVersion {
46+
server_type: Java("vanilla".to_string()),
47+
channel: Snapshot("Null".to_string()),
48+
},
4549
}
4650
}
4751
}
@@ -64,7 +68,7 @@ impl McServerConfig {
6468
pub fn new() -> Self {
6569
Self {
6670
project: Default::default(),
67-
version: Value::String("".to_string()),
71+
inner: Value::String("".to_string()),
6872
backup: Default::default(),
6973
}
7074
}
@@ -74,18 +78,18 @@ impl McServerConfig {
7478
file.read_to_string(&mut string).await?;
7579
Ok(toml::from_str(string.as_str())?)
7680
}
77-
pub fn to_string(&self, version: &dyn McServer) -> Result<String> {
81+
pub fn to_string(&self, inner: &dyn McServer) -> Result<String> {
7882
Ok(toml::to_string(&Self {
7983
project: self.project.clone(),
80-
version: Value::try_from(version.to_config()?)?,
84+
inner: Value::try_from(inner.to_config()?)?,
8185
backup: self.backup.clone(),
8286
})?)
8387
}
84-
pub fn load_from_str(config: &str, version: &mut dyn McServer) -> Result<Self> {
88+
pub fn load_from_str(config: &str, inner: &mut dyn McServer) -> Result<Self> {
8589
let cfg = toml::from_str::<Self>(config)?;
86-
let version_cfg = toml::to_string(&cfg.version)?;
90+
let version_cfg = toml::to_string(&cfg.inner)?;
8791
let de = toml::Deserializer::parse(version_cfg.as_str())?;
88-
version.load_config(&mut <dyn Deserializer>::erase(de))?;
92+
inner.load_config(&mut <dyn Deserializer>::erase(de))?;
8993
Ok(cfg)
9094
}
9195
}

src/core/mc_server/base.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
1-
pub(crate) use crate::core::mc_server::McVersion;
1+
pub use crate::core::mc_server::McVersion;
22
use anyhow::Result;
3-
use async_trait::async_trait;
4-
use erased_serde::{Deserializer, Serialize};
3+
use serde::{Deserialize, Serialize};
54
use std::any::Any;
65

76
/// MC 服务端最少实现的 trait
8-
#[async_trait]
97
pub trait McServer: Any {
10-
/// 严格检查是否符合当前类型的服务端
11-
fn check(path: &std::path::Path) -> bool
8+
/// 从版本号创建空实例
9+
fn new() -> Box<dyn McServer>
1210
where
1311
Self: Sized;
14-
/// 获取版本信息
15-
fn version(&self) -> Result<McVersion>;
1612
/// 打印当前平台的运行脚本
13+
/// 若实现了 McServerRuntime Trait ,此函数无效
1714
fn script(&self) -> Result<String>;
18-
/// 需要持久化的内部配置文件
19-
fn to_config(&self) -> Result<Box<dyn Serialize + '_>>;
20-
/// 加载配置文件
21-
/// ```
22-
/// let cfg = erased_serde::deserialize::<YourConfig>(de)?;
23-
/// ```
24-
fn load_config(&mut self, de: &mut dyn Deserializer) -> Result<()>;
2515
/// 启动实例
2616
fn start(&self) -> Result<tokio::process::Command>;
17+
18+
/// 需要持久化的内部配置信息
19+
fn to_config(&self) -> Result<Box<dyn erased_serde::Serialize + '_>> {
20+
#[derive(Serialize)]
21+
struct NoConfig;
22+
Ok(Box::new(NoConfig))
23+
}
24+
/// 加载配置信息
25+
fn load_config(&mut self, de: &mut dyn erased_serde::Deserializer) -> Result<()> {
26+
#[derive(Deserialize)]
27+
struct NoConfig;
28+
let _cfg = erased_serde::deserialize::<NoConfig>(de)?;
29+
Ok(())
30+
}
2731
}

src/core/mc_server/mod.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,12 @@ use std::cmp::Ordering;
1111
use std::cmp::Ordering::{Equal, Greater, Less};
1212
use std::fmt::{Display, Formatter};
1313

14-
use crate::core::mc_server::base::McServer;
15-
16-
pub struct VersionLoader {
17-
pub versions: Vec<Box<dyn McServer>>,
18-
}
19-
20-
impl VersionLoader {
21-
pub fn new() -> Self {
22-
VersionLoader { versions: vec![] }
23-
}
24-
pub fn register(&mut self, version: Box<dyn McServer>) {
25-
self.versions.push(version);
26-
}
27-
}
28-
2914
/// 更新渠道
3015
#[derive(PartialEq, Clone)]
3116
pub enum McChannel {
3217
Release(u8, u8, u8),
3318
Snapshot(String),
19+
Unknown,
3420
}
3521

3622
/// 服务端类型
@@ -119,6 +105,9 @@ impl Display for McVersion {
119105
McChannel::Snapshot(version) => {
120106
writeln!(f, "Snapshot {}", version)
121107
}
108+
McChannel::Unknown => {
109+
writeln!(f, "Unknown")
110+
}
122111
}?;
123112
Ok(())
124113
}
@@ -134,6 +123,7 @@ impl Serialize for McChannel {
134123
serializer.serialize_str(format!("{}.{}.{}", major, minor, patch).as_str())
135124
}
136125
McChannel::Snapshot(s) => serializer.serialize_str(s),
126+
McChannel::Unknown => serializer.serialize_str("Unknown"),
137127
}
138128
}
139129
}
@@ -158,7 +148,13 @@ impl<'de> Deserialize<'de> for McChannel {
158148
Ok(Self::Snapshot(s))
159149
}
160150
}
161-
Err(_) => Ok(Self::Snapshot(s)),
151+
Err(_) => {
152+
if s.trim() == "Unknown" {
153+
Ok(McChannel::Unknown)
154+
} else {
155+
Ok(Self::Snapshot(s))
156+
}
157+
}
162158
}
163159
}
164160
}

src/core/mc_server/plugin.rs

Lines changed: 137 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,140 @@
11
use crate::core::mc_server::base::McServer;
2+
use anyhow::{Result, anyhow};
3+
use async_trait::async_trait;
24

3-
// 计划的插件功能
4-
trait McServerPlugin: McServer {
5-
// fn plugin()->();
5+
/// 插件管理器
6+
#[async_trait]
7+
pub trait McServerPlugin: McServer {
8+
fn get_repo(&self) -> &'static [&'static dyn ServerPluginRepo];
9+
}
10+
11+
pub struct ServerPlugin {
12+
id: usize,
13+
name: String,
14+
version: String,
15+
description: String,
16+
}
17+
18+
/// 插件仓库
19+
#[async_trait]
20+
pub trait ServerPluginRepo: Sync {
21+
/// 仓库名称,此字符串同时用于标识仓库
22+
fn name(&self) -> &'static str;
23+
/// 列出本地插件
24+
async fn list(&self) -> Vec<ServerPlugin>;
25+
/// 查询插件
26+
async fn search(&self, keyword: &str) -> Vec<ServerPlugin>;
27+
/// 安装插件
28+
async fn install(&self, plugin: ServerPlugin) -> Result<()>;
29+
/// 查询最新版本
30+
async fn latest(&self, plugin: ServerPlugin) -> Result<ServerPlugin>;
31+
}
32+
33+
#[async_trait]
34+
pub trait TryMcServerPlugin: McServer {
35+
fn impl_plugin(&self) -> bool;
36+
/// 列出本地插件
37+
async fn list(&self) -> Result<Vec<(&'static str, ServerPlugin)>>;
38+
/// 查询插件
39+
async fn search(&self, keyword: &str) -> Result<Vec<(&'static str, ServerPlugin)>>;
40+
/// 安装插件
41+
async fn install(&self, repo: &str, plugin: ServerPlugin) -> Result<()>;
42+
/// 查询最新版本
43+
async fn latest(&self, repo: &str, plugin: ServerPlugin) -> Result<ServerPlugin>;
44+
}
45+
46+
#[async_trait]
47+
impl<T> TryMcServerPlugin for T
48+
where
49+
T: McServer + Sync,
50+
{
51+
default fn impl_plugin(&self) -> bool {
52+
false
53+
}
54+
55+
default async fn list(&self) -> Result<Vec<(&'static str, ServerPlugin)>> {
56+
Err(anyhow!(
57+
"The plugin manager has not been implemented for this server."
58+
))
59+
}
60+
61+
default async fn search(&self, _: &str) -> Result<Vec<(&'static str, ServerPlugin)>> {
62+
Err(anyhow!(
63+
"The plugin manager has not been implemented for this server."
64+
))
65+
}
66+
67+
default async fn install(&self, _: &str, _: ServerPlugin) -> Result<()> {
68+
Err(anyhow!(
69+
"The plugin manager has not been implemented for this server."
70+
))
71+
}
72+
73+
default async fn latest(&self, _: &str, _: ServerPlugin) -> Result<ServerPlugin> {
74+
Err(anyhow!(
75+
"The plugin manager has not been implemented for this server."
76+
))
77+
}
78+
}
79+
80+
#[async_trait]
81+
impl<T> TryMcServerPlugin for T
82+
where
83+
T: McServerPlugin + Sync,
84+
{
85+
default fn impl_plugin(&self) -> bool {
86+
false
87+
}
88+
89+
default async fn list(&self) -> Result<Vec<(&'static str, ServerPlugin)>> {
90+
let mut list = Vec::new();
91+
for repo in self.get_repo() {
92+
list.extend(
93+
repo.list()
94+
.await
95+
.into_iter()
96+
.map(|plugin| (repo.name(), plugin)),
97+
)
98+
}
99+
Ok(list)
100+
}
101+
102+
default async fn search(&self, keyword: &str) -> Result<Vec<(&'static str, ServerPlugin)>> {
103+
let mut list = Vec::new();
104+
for repo in self.get_repo() {
105+
list.extend(
106+
repo.search(keyword)
107+
.await
108+
.into_iter()
109+
.map(|plugin| (repo.name(), plugin)),
110+
)
111+
}
112+
Ok(list)
113+
}
114+
115+
default async fn install(&self, repo_name: &str, plugin: ServerPlugin) -> Result<()> {
116+
if let Some(repo) = self
117+
.get_repo()
118+
.iter()
119+
.find(|&&repo| repo.name() == repo_name)
120+
{
121+
repo.install(plugin).await
122+
} else {
123+
// 静态插件仓库不应该找不到
124+
unreachable!("No such plugin repository: {}", repo_name)
125+
}
126+
}
127+
128+
default async fn latest(&self, repo_name: &str, plugin: ServerPlugin) -> Result<ServerPlugin> {
129+
if let Some(repo) = self
130+
.get_repo()
131+
.iter()
132+
.find(|&&repo| repo.name() == repo_name)
133+
{
134+
repo.latest(plugin).await
135+
} else {
136+
// 静态插件仓库不应该找不到
137+
unreachable!("No such plugin repository: {}", repo_name)
138+
}
139+
}
6140
}

0 commit comments

Comments
 (0)