#language #age #read #genie #resources #file #empires

genie-lang

从《帝国时代1》和《帝国时代2》读取不同类型的语言资源文件

3个不稳定版本

0.2.1 2020年5月18日
0.2.0 2019年8月4日
0.1.0 2019年4月9日

#3 in #genie


用于 2 crates

GPL-3.0 许可证

52KB
1K SLoC

genie-lang将语言文件读取到UTF-8字符串映射中。支持《帝国时代》版本使用的三种主要语言文件类型:DLL、INI文件和HD版的键值格式。

DLL由原始游戏使用。INI文件用于Voobly模组,可以通过aoc-language-ini模组与标准AoC安装一起使用。

DLL

use genie_lang::{LangFileType::Dll, StringKey};
use std::{convert::TryFrom, fs::File};
let f = File::open("./test/dlls/language_x1_p1.dll")?;
let lang_file = Dll.read_from(f)?;
assert_eq!(
    lang_file.get(&StringKey::try_from(30177).unwrap()),
    Some(&String::from("Turbo Random Map - Buildings create units faster, villagers gather faster, build faster, and carry more.")));
assert_eq!(
    lang_file.get(&StringKey::try_from(20156).unwrap()),
    Some(&String::from("<b>Byzantines<b> \n\
          Defensive civilization \n\
          · Buildings +10% HPs Dark, +20% Feudal, \n +30% Castle, +40% Imperial Age \n\
          · Camels, skirmishers, Pikemen, Halberdiers cost -25% \n\
          · Fire ships +20% attack \n\
          · Advance to Imperial Age costs -33% \n\
          · Town Watch free \n\n\
          <b>Unique Unit:<b> Cataphract (cavalry) \n\n\
          <b>Unique Tech:<b> Logistica (Cataphracts cause trample damage) \n\n\
          <b>Team Bonus:<b> Monks +50% heal speed")));

INI文件

use genie_lang::{LangFileType::Ini, StringKey};
use std::{convert::TryFrom, io::Cursor};
let text = br#"
46523=The Uighurs will join if you kill Ornlu the wolf and return to tell the tale.
; a comment
46524=Uighurs: Yes, that is the pelt of the great wolf. We will join you, Genghis Khan. And to seal the agreement, we will give you the gift of flaming arrows!
"#;
let f = Cursor::new(&text[..]);
let lang_file = Ini.read_from(f)?;
assert_eq!(
    lang_file.get(&StringKey::try_from(46523).unwrap()),
    Some(&String::from("The Uighurs will join if you kill Ornlu the wolf and return to tell the tale.")));

HD键值文件

use genie_lang::{LangFileType::KeyValue, StringKey};
use std::{convert::TryFrom, io::Cursor};
let text = br#"
46523 "The Uighurs will join if you kill Ornlu the wolf and return to tell the tale."
46524 "Uighurs: Yes, that is the pelt of the great wolf. We will join you, Genghis Khan. And to seal the agreement, we will give you the gift of flaming arrows!"
46604 "Kill the traitor, Kushluk.\n\nPrevent the tent of Genghis Khan (Wonder) from being destroyed."
LOBBYBROWSER_DATMOD_TITLE_FORMAT "DatMod: \"%s\""
"#;
let f = Cursor::new(&text[..]);
let lang_file = KeyValue.read_from(f)?;
assert_eq!(
    lang_file.get(&StringKey::try_from(46523).unwrap()),
    Some(&String::from("The Uighurs will join if you kill Ornlu the wolf and return to tell the tale.")));
assert_eq!(
    lang_file.get(&StringKey::from("LOBBYBROWSER_DATMOD_TITLE_FORMAT")),
    Some(&String::from(r#"DatMod: "%s""#)));

从头创建文件

use genie_lang::{LangFile, StringKey};
use std::{convert::TryFrom, str};
let mut lang_file = LangFile::new();
lang_file.insert(StringKey::try_from(46604).unwrap(), String::from("Kill the traitor, Kushluk.\n\n\
                      Prevent the tent of Genghis Khan (Wonder) from being destroyed."));
let mut out = vec![];
lang_file.write_to_ini(&mut out)?;
assert_eq!(
    str::from_utf8(&out)?,
    r"46604=Kill the traitor, Kushluk.\n\nPrevent the tent of Genghis Khan (Wonder) from being destroyed.
");
lang_file.insert(StringKey::from("LOBBYBROWSER_DATMOD_TITLE_FORMAT"), String::from(r#"DatMod: "%s""#));
let mut out = vec![];
lang_file.write_to_keyval(&mut out)?;
let result_string = str::from_utf8(&out)?;
println!("{}", result_string);
assert!(
    result_string == r#"46604 "Kill the traitor, Kushluk.\n\nPrevent the tent of Genghis Khan (Wonder) from being destroyed."
LOBBYBROWSER_DATMOD_TITLE_FORMAT "DatMod: \"%s\""
"#
    ||
    result_string == r#"LOBBYBROWSER_DATMOD_TITLE_FORMAT "DatMod: \"%s\""
46604 "Kill the traitor, Kushluk.\n\nPrevent the tent of Genghis Khan (Wonder) from being destroyed."
"#);

依赖

~5MB
~149K SLoC