gpt4 book ai didi

rust - 使用 serde,是否可以反序列化为实现类型的结构?

转载 作者:行者123 更新时间:2023-11-29 08:17:57 25 4
gpt4 key购买 nike

我正在构建一个 rogue-like,我已经让数据加载器正常工作并且部分 ECS 正常工作(从头开始构建)。数据存储在 .yml 文件中,用于描述游戏中的事物(在本例中为生物)以及这些事物具有的特征,例如:

---
orc:
feature_packs:
- physical
- basic_identifiers_mob
features:
- component: char
initial_value: T
goblin:
feature_packs:
- physical
- basic_identifiers_mob
features:
- component: char
initial_value: t

如您所见,描述了两个生物,一个地精和一个兽人,它们都拥有两个功能包(功能组)并且还拥有一个 char 功能,用于描述它们的内容看起来像玩家。

initial_value 字段可以是字符串、整数、 float 、 bool 值、范围等,具体取决于组件的要求,这将指示组件可能的值或可能的值在实体构建/创建期间生成组件时有。

问题是我不知道如何在迭代功能时根据组件名称选择结构,例如,为 选择 Char 结构” char" 特征。

为了更好地描述我的意思,我用一种我更能理解的语言 Ruby 写了一个例子:

data_manager = function_that_loads_data('folder_path')

Entity_Manager.build(:mob, :orc, data_manager)

class Entity_Manager
class << self
attr_accessor :entities, :components
end

def self.build(entity_type, template_name, data_manager)
template = data_manager[entity_type][template_name]
entity_id = generate_unique_id
entities[entity_id] = Entity.new(entity_id, components: template.components.keys)
template.components.each do |component|
components[component.name][entity_id] =
Components.get(component.name).new(component.initial_value) # <= This part, how do I do the equivalent in rust, a function that will return or allow me to get or create a struct based on the value of a string variable
end
end
end

现在 serde 是我所知道的唯一似乎能够读取文本数据并将其转换为数据的东西,因此为此目的

我如何使用 serde(或更合适的非 serde 使用解决方案)获取功能的名称并检索正确的结构,所有这些都实现了一个类型?

顺便说一下,我尽量不使用的一个解决方案是一个巨大的匹配语句。

我的工作的 repo 是 here

  • Data manager - 加载和管理加载到游戏中的数据
  • Entity manager - 管理实体和组件(不支持位 key atm)
  • Entity Builder - 将使用来自数据管理器的数据构建实体的位置(这是我目前遇到的问题)
  • Components - 简单组件列表

我想避免的是做这样的事情:

pub fn get(comp_name: &String) -> impl Component {
match comp_name.as_ref() {
"kind" => Kind,
"location" => Location,
"name" => Name,
"position" => Position,
"char" => Char,
}
}

因为它不是真正可维护的,虽然宏会有很大帮助,但我不是很擅长那些 atm,它甚至不起作用,rust 一直认为我只是想初始化类型返回几种可能的类型之一,它们都将实现 Component

编辑:因为看起来我还不够清楚:

  • 我不是在尝试将游戏对象加载到游戏中,而是在加载模板
  • 我正在使用这些模板生成游戏过程中存在的实体
  • 我已经可以按照以下结构将我想要的数据加载到游戏中:
pub enum InitialValue {
Char(char),
String(String),
Int(i32),
Float(f32),
Bool(bool),
Range(Range<i32>),
Point((i32,i32))
}


impl InitialValue {

pub fn unwrap_char(&self) -> &char {
match &self {
InitialValue::Char(val) => val,
_ => panic!("Stored value does not match unwrap type")
}
}

pub fn unwrap_string(&self) -> &String {
match &self {
InitialValue::String(val) => val,
_ => panic!("Stored value does not match unwrap type")
}
}

pub fn unwrap_int(&self) -> &i32 {
match &self {
InitialValue::Int(val) => val,
_ => panic!("Stored value does not match unwrap type")
}
}

pub fn unwrap_float(&self) -> &f32 {
match &self {
InitialValue::Float(val) => val,
_ => panic!("Stored value does not match unwrap type")
}
}

pub fn unwrap_bool(&self) -> &bool {
match &self {
InitialValue::Bool(val) => val,
_ => panic!("Stored value does not match unwrap type")
}
}

pub fn unwrap_range(&self) -> &Range<i32> {
match &self {
InitialValue::Range(val) => val,
_ => panic!("Stored value does not match unwrap type")
}
}

pub fn unwrap_point(&self) -> &(i32, i32) {
match &self {
InitialValue::Point(val) => val,
_ => panic!("Stored value does not match unwrap type")
}
}
}

#[derive(Debug, Deserialize)]
pub struct Component {
#[serde(rename="component")]
name: String,
#[serde(default)]
initial_value: Option<InitialValue>,
}

#[derive(Debug, Deserialize)]
pub struct Template {
pub feature_packs: Vec<String>,
pub features: Vec<Component>,
}
  • 如何将模板转换为实体实例?

  • 具体来说,我如何为给定的 Component.name 找到组件然后初始化呢?或者是我的方法错了,还有更好的方法方式。

  • 如果我做错了,其他游戏如何加载数据然后使用它生成游戏实体?

最佳答案

听起来你想要一个带标签的联合,或者求和类型; Rust 知道这些是 enumerations . Serde 甚至支持使用 container internal tags .所以这是我的小实验:

#[macro_use] extern crate serde_derive;
extern crate serde_yaml;

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag="component")]
enum Feature {
Char { initial_value : char },
Weight { kgs : u32 }
}

fn main() {
let v = vec![
Feature::Char{initial_value:'x'},
Feature::Weight{kgs:12}
];
println!("{}", serde_yaml::to_string(&v).unwrap());
}

这个输出:

---
- component: Char
initial_value: x
- component: Weight
kgs: 12

可能下一步是为变体制作专用结构。

关于rust - 使用 serde,是否可以反序列化为实现类型的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55536740/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com