Runtime Core - 运行时核心

runtime_core crate 负责运行模式编排和生命周期管理。

职责

  • 管理运行模式 (单人/主机/远程)
  • 启动和关闭 server/client
  • 协调 server 和 client 的更新
  • 前端 Snapshot 投影
  • 错误处理和状态管理

核心类型

Runtime

#![allow(unused)]
fn main() {
pub struct Runtime {
    mode: RuntimeMode,
    server: Option<Server>,
    client: Option<Client>,
    content_db: Option<ContentDatabase>,
}
}

RuntimeMode

#![allow(unused)]
fn main() {
pub enum RuntimeMode {
    None,
    Singleplayer,
    Host { port: u16 },
    Client { server_addr: String },
}
}

RuntimeConfig

#![allow(unused)]
fn main() {
pub struct RuntimeConfig {
    pub assets_root: PathBuf,
    pub content_package_path: PathBuf,
}
}

核心 API

初始化

#![allow(unused)]
fn main() {
impl Runtime {
    pub fn new() -> Self {
        Runtime {
            mode: RuntimeMode::None,
            server: None,
            client: None,
            content_db: None,
        }
    }
    
    pub fn initialize(&mut self, config: RuntimeConfig) -> Result<()> {
        // 加载内容包
        let loader = ContentLoader::new();
        self.content_db = Some(loader.load_package(&config.content_package_path)?);
        Ok(())
    }
}
}

启动模式

#![allow(unused)]
fn main() {
impl Runtime {
    pub fn start_singleplayer(&mut self) -> Result<()> {
        let content_db = self.content_db.as_ref()
            .ok_or(RuntimeError::NotInitialized)?;
        
        // 创建本地 server
        let server = Server::new_local(content_db.clone())?;
        
        // 创建本地 client
        let client = Client::new_local()?;
        
        // 建立内存通道
        self.connect_local(&mut server, &mut client)?;
        
        self.server = Some(server);
        self.client = Some(client);
        self.mode = RuntimeMode::Singleplayer;
        
        Ok(())
    }
    
    pub fn start_host(&mut self, port: u16) -> Result<()> {
        // 类似单人模式,但 server 监听网络端口
        // ...
    }
    
    pub fn start_client(&mut self, server_addr: String) -> Result<()> {
        // 仅创建 client,连接远程 server
        // ...
    }
}
}

更新循环

#![allow(unused)]
fn main() {
impl Runtime {
    pub fn update(&mut self, delta_seconds: f64) -> Result<()> {
        match self.mode {
            RuntimeMode::Singleplayer => {
                // 更新 server
                if let Some(server) = &mut self.server {
                    server.update(delta_seconds)?;
                }
                
                // 更新 client
                if let Some(client) = &mut self.client {
                    client.update(delta_seconds)?;
                }
            }
            RuntimeMode::Host { .. } => {
                // 同上
            }
            RuntimeMode::Client { .. } => {
                // 仅更新 client
                if let Some(client) = &mut self.client {
                    client.update(delta_seconds)?;
                }
            }
            RuntimeMode::None => {
                return Err(RuntimeError::NotStarted);
            }
        }
        
        Ok(())
    }
}
}

前端 Snapshot

#![allow(unused)]
fn main() {
impl Runtime {
    pub fn get_frontend_snapshot(&self) -> Option<FrontendSnapshot> {
        self.client.as_ref().map(|c| c.get_frontend_snapshot())
    }
}
}

关闭

#![allow(unused)]
fn main() {
impl Runtime {
    pub fn shutdown(&mut self) -> Result<()> {
        if let Some(mut server) = self.server.take() {
            server.shutdown()?;
        }
        
        if let Some(mut client) = self.client.take() {
            client.shutdown()?;
        }
        
        self.mode = RuntimeMode::None;
        
        Ok(())
    }
}
}

错误处理

#![allow(unused)]
fn main() {
#[derive(Debug, thiserror::Error)]
pub enum RuntimeError {
    #[error("Runtime not initialized")]
    NotInitialized,
    
    #[error("Runtime not started")]
    NotStarted,
    
    #[error("Server error: {0}")]
    ServerError(#[from] ServerError),
    
    #[error("Client error: {0}")]
    ClientError(#[from] ClientError),
    
    #[error("Content error: {0}")]
    ContentError(#[from] ContentError),
}
}

为什么需要 runtime_core?

如果没有 runtime_coregdextension 会直接管理:

  • Server 和 client 的生命周期
  • 网络配置
  • 内容加载
  • 模式切换

这会让 gdextension 变得臃肿,且难以测试。

runtime_core 提供纯 Rust API,使得:

  • 可以编写不依赖 Godot 的测试
  • 未来可支持其他前端 (如纯 Bevy 渲染)
  • GDExtension 层只做类型转换

使用示例

#![allow(unused)]
fn main() {
use runtime_core::{Runtime, RuntimeConfig};

let mut runtime = Runtime::new();

// 初始化
runtime.initialize(RuntimeConfig {
    assets_root: PathBuf::from("assets"),
    content_package_path: PathBuf::from("assets/official"),
})?;

// 启动单人模式
runtime.start_singleplayer()?;

// 游戏循环
loop {
    runtime.update(0.016)?;  // 60 FPS
    
    if let Some(snapshot) = runtime.get_frontend_snapshot() {
        // 渲染 snapshot
    }
}

// 关闭
runtime.shutdown()?;
}

下一步