Skip to content

Commit

Permalink
Merge pull request #7 from KAIYOHUGO/single_file
Browse files Browse the repository at this point in the history
Switch to Single file
  • Loading branch information
KAIYOHUGO authored Jun 19, 2023
2 parents 01b6f6f + a72b025 commit d667c9f
Show file tree
Hide file tree
Showing 9 changed files with 16,203 additions and 11,785 deletions.
11,103 changes: 6,091 additions & 5,012 deletions example/en_us.json

Large diffs are not rendered by default.

2,598 changes: 1,859 additions & 739 deletions example/en_us.lang

Large diffs are not rendered by default.

11,113 changes: 6,096 additions & 5,017 deletions example/zh_tw.json

Large diffs are not rendered by default.

2,962 changes: 2,037 additions & 925 deletions example/zh_tw.lang

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/fetch_bedrock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub async fn fetch(
.send()
.await?;
for i in page.items {
let Some((lang_id,ext))=i.name.split_once(".") else {
let Some((lang_id,ext))=i.name.split_once('.') else {
continue;
};
if ext != "lang" {
Expand Down
88 changes: 43 additions & 45 deletions src/generate.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,43 @@
use std::{collections::HashMap, io::Write, path::PathBuf, sync::Arc};
use std::{collections::HashMap, path::Path};

use crate::{
pack::{pack_addon, Header, Manifest, Module},
parse::{ser_bedrock, TranslateKV},
pack::{pack_addon, Header, LangInfo, Manifest, Module},
parse::TranslateKV,
};
use anyhow::{anyhow, Result};
use tokio::{fs, task};
use tokio_util::io::SyncIoBridge;
use tokio::task;

/// output is `Map<bedrock_id,java_id>`
pub fn gen_bedrock_java_id_map(mut bedrock: TranslateKV, java: TranslateKV) -> TranslateKV {
let mut java_value_key = TranslateKV::new();
java_value_key.reserve(java.capacity());
fn gen_bedrock_java_id_map(bedrock: TranslateKV, java: TranslateKV) -> TranslateKV {
let mut java_text_id = TranslateKV::new();
java_text_id.reserve(java.capacity());
for (k, v) in java {
java_value_key.insert(v, k);
java_text_id.insert(v, k);
}

for (_, v) in bedrock.iter_mut() {
if let Some(java_key) = java_value_key.remove(v) {
*v = java_key;
let mut ret = TranslateKV::new();
for (bedrock_id, bedrock_text) in bedrock {
if let Some(java_id) = java_text_id.get(&bedrock_text).cloned() {
ret.insert(bedrock_id, java_id);
}
}
bedrock
ret
}

pub fn gen_translate(
fn gen_translate(
bedrock_java_id_map: &TranslateKV,
mut java: TranslateKV,
bedrock: TranslateKV,
) -> TranslateKV {
let mut translate = TranslateKV::new();
for (bedrock_id, bedrock_text) in bedrock {
let Some(java_id) = bedrock_java_id_map.get(&bedrock_id) else {
continue;
};
for (bedrock_id, java_id) in bedrock_java_id_map {
let Some(java_text) = java.remove(java_id) else {
continue;
};
if bedrock_text == java_text {
if Some(&java_text) == bedrock.get(bedrock_id) {
continue;
}
translate.insert(bedrock_id, java_text);
translate.insert(bedrock_id.clone(), java_text);
}
translate
}
Expand All @@ -49,16 +46,19 @@ pub async fn gen_output(
mut java_texts: HashMap<String, TranslateKV>,
mut bedrock_texts: HashMap<String, TranslateKV>,
version: [u8; 3],
output: PathBuf,
) -> Result<()> {
output: &Path,
) -> Result<TranslateKV> {
let (Some(java_en_us),Some(bedrock_en_us))=(java_texts.remove("en_us"),bedrock_texts.remove("en_us")) else {
return Err(anyhow!("en_us.json and en_us.lang file are required"));
};

let mut tasks = task::JoinSet::new();
let id_map = Arc::new(gen_bedrock_java_id_map(bedrock_en_us, java_en_us));

let manifest = Arc::new(Manifest {
let bedrock_java_id_map = gen_bedrock_java_id_map(bedrock_en_us, java_en_us);
let mut path = output.join(format!(
"To_Bedrock_{}_{}_{}",
&version[0], &version[1], &version[2]
));
path.set_extension("mcpack");
let manifest = Manifest {
format_version: 2,
header: Header {
description: "Java Translation Pack Generate by kaiyo hugo".into(),
Expand All @@ -72,30 +72,28 @@ pub async fn gen_output(
uuid: "743f6949-53be-44b6-b326-398005028623".into(),
version,
}],
});
};

let mut lang_info_list = vec![];
for (id, java_text) in java_texts {
let Some(bedrock_text) = bedrock_texts.remove(&id) else {
continue;
};
let lang_id = id
let id = id
.split_once('_')
.map(|(begin, end)| format!("{}_{}", begin, end.to_uppercase()))
.unwrap_or(id);
let mut path = output.join(format!("To_Bedrock_{}", lang_id));
path.set_extension("mcpack");

let id_map = id_map.clone();
let manifest = manifest.clone();

tasks.spawn(async move {
let text = gen_translate(&id_map, java_text, bedrock_text);
task::spawn_blocking(|| pack_addon(path, lang_id, text, manifest)).await??;
anyhow::Ok(())
});
}
while let Some(next) = tasks.join_next().await {
next??;
let name = {
let name = java_text
.get("language.name")
.ok_or_else(|| anyhow!("cannot find name in java name file (malformed)"))?;
let region = java_text
.get("language.region")
.ok_or_else(|| anyhow!("cannot find region in java name file (malformed)"))?;
format!("{name} ({region})")
};
let bedrock_text = bedrock_texts.remove(&id).unwrap_or_default();
let texts = gen_translate(&bedrock_java_id_map, java_text, bedrock_text);
lang_info_list.push(LangInfo { id, name, texts })
}
Ok(())
task::spawn_blocking(|| pack_addon(path, lang_info_list, manifest)).await??;
Ok(bedrock_java_id_map)
}
63 changes: 45 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ mod generate;
mod pack;
mod parse;

use anyhow::{anyhow, Context, Result};
use api::get;
use anyhow::{anyhow, Result};

use clap::Parser;
use generate::gen_output;
use octocrab::params::repos::Reference;
use parse::{des_bedrock, des_en_us_from_java, des_java};
use std::{collections::HashMap, path::PathBuf};
use tokio::{fs, io, select, spawn, task, try_join};
use tokio_util::io::SyncIoBridge;

use parse::{des_bedrock, des_java};
use std::{collections::HashMap, io::BufWriter, path::PathBuf};
use tokio::{
fs, io,
task::{self, spawn_blocking},
try_join,
};

#[derive(Debug, Clone, Parser)]
struct Cli {
Expand All @@ -36,13 +39,18 @@ struct AutoCmd {
/// java version
#[arg(short, long)]
java: String,

/// bedrock version
#[arg(short, long)]
bedrock: Option<String>,

/// output folder path
#[arg(short, long)]
output: PathBuf,

/// emit bedrock java id map
#[arg(long)]
emit_map: bool,
}

#[derive(Debug, Clone, clap::Args)]
Expand All @@ -62,6 +70,10 @@ struct RawCmd {
/// pack (addon) version e.g. `1.19.0`
#[arg(short, long)]
pack_version: String,

/// emit bedrock java id map
#[arg(long)]
emit_map: bool,
}

#[tokio::main]
Expand Down Expand Up @@ -89,16 +101,25 @@ async fn auto_cmd(cmd: AutoCmd) -> Result<()> {
version.url.get().await?
};

let java_texts = fetch_java::fetch(java_package, 5.try_into()?).await?;
let java_texts = fetch_java::fetch(java_package, 10.try_into()?).await?;
let bedrock_texts = fetch_bedrock::fetch(bedrock_version, 10.try_into()?).await?;

gen_output(
let bedrock_java_id_map = gen_output(
java_texts,
bedrock_texts,
parse_version(cmd.java)?,
cmd.output,
&cmd.output,
)
.await
.await?;
if cmd.emit_map {
spawn_blocking(move || {
let file = BufWriter::new(std::fs::File::create(cmd.output.join("map.json"))?);
serde_json::to_writer(file, &bedrock_java_id_map)?;
anyhow::Ok(())
})
.await??;
}
Ok(())
}

async fn raw_cmd(cmd: RawCmd) -> Result<()> {
Expand Down Expand Up @@ -159,13 +180,22 @@ async fn raw_cmd(cmd: RawCmd) -> Result<()> {
let java_texts = java_texts?;
let bedrock_texts = bedrock_texts?;

gen_output(
let bedrock_java_id_map = gen_output(
java_texts,
bedrock_texts,
parse_version(cmd.pack_version)?,
cmd.output,
&cmd.output,
)
.await
.await?;
if cmd.emit_map {
spawn_blocking(move || {
let file = BufWriter::new(std::fs::File::create(cmd.output.join("map.json"))?);
serde_json::to_writer(file, &bedrock_java_id_map)?;
anyhow::Ok(())
})
.await??;
}
Ok(())
}

fn parse_version(version: String) -> Result<[u8; 3]> {
Expand All @@ -176,14 +206,11 @@ fn parse_version(version: String) -> Result<[u8; 3]> {
while ret.len() < 3 {
ret.push(0);
}
Ok(ret
.try_into()
.map_err(|_| anyhow!("Version Format Error"))?)
ret.try_into().map_err(|_| anyhow!("Version Format Error"))
}

#[cfg(test)]
mod tests {
use super::*;

#[tokio::test]
async fn test_name() {
Expand Down
32 changes: 25 additions & 7 deletions src/pack.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Result;
use serde::Serialize;
use std::{io::Write, path::Path, sync::Arc};
use std::{io::Write, path::Path};
use zip::{write::FileOptions, ZipWriter};

use crate::parse::{sync_ser_bedrock, TranslateKV};
Expand Down Expand Up @@ -29,11 +29,16 @@ pub struct Module {
pub version: [u8; 3],
}

pub struct LangInfo {
pub id: String,
pub name: String,
pub texts: TranslateKV,
}

pub fn pack_addon(
path: impl AsRef<Path>,
lang_id: String,
text: TranslateKV,
manifest: Arc<Manifest>,
lang_info_list: Vec<LangInfo>,
manifest: Manifest,
) -> Result<()> {
let mut file = ZipWriter::new(std::fs::File::create(path)?);
let option = FileOptions::default().compression_level(Some(9));
Expand All @@ -42,10 +47,23 @@ pub fn pack_addon(
file.write_all(include_bytes!("../assets/pack_icon.png"))?;

file.start_file("manifest.json", option)?;
serde_json::to_writer(&mut file, &*manifest)?;
serde_json::to_writer(&mut file, &manifest)?;

let mut lang_id_list = vec![];
let mut lang_name_list = vec![];
for LangInfo { id, name, texts } in &lang_info_list {
lang_id_list.push(id);
lang_name_list.push([id, name]);

file.start_file(format!("texts/{}.lang", &id), option)?;
sync_ser_bedrock(&mut file, texts)?;
}

file.start_file("texts/languages.json", option)?;
serde_json::to_writer(&mut file, &lang_id_list)?;

file.start_file(format!("texts/{}.lang", lang_id), option)?;
sync_ser_bedrock(&mut file, text)?;
file.start_file("texts/language_names.json", option)?;
serde_json::to_writer(&mut file, &lang_name_list)?;

file.finish()?;
Ok(())
Expand Down
27 changes: 6 additions & 21 deletions src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use anyhow::{anyhow, Result};
use anyhow::Result;
use std::{
collections::HashMap,
io::{Cursor, Read, Write},
};
use tokio::io::{self, AsyncBufRead, AsyncBufReadExt, AsyncReadExt, AsyncWriteExt};
use tokio::io::{AsyncBufRead, AsyncBufReadExt, AsyncReadExt};
use zip::ZipArchive;

pub type TranslateKV = HashMap<String, String>;
Expand All @@ -22,37 +22,22 @@ pub async fn des_bedrock(reader: impl AsyncBufReadExt + Unpin) -> Result<Transla
let mut lines = reader.lines();

while let Some(line) = lines.next_line().await? {
let text = if let Some((text, _comment)) = line.split_once("#") {
let text = if let Some((text, _comment)) = line.split_once("##") {
text
} else {
&line
};
// ignore BOM
let text = text
.trim_start_matches("\u{feff}")
.trim_start()
.trim_end_matches('\t');
if text.is_empty() {
continue;
}

let text = text.trim_start_matches('\u{feff}').trim_end_matches("\t#");
let Some((k,v)) = text.split_once('=') else {
dbg!(line);
return Err(anyhow!("malformed bedrock lang file, expect 'key=value'"))
continue;
};
kv.insert(k.to_owned(), v.to_owned());
}
Ok(kv)
}

pub async fn ser_bedrock(writer: &mut (impl AsyncWriteExt + Unpin), kv: TranslateKV) -> Result<()> {
for (k, v) in kv {
writer.write_all(format!("{k}={v}\n").as_bytes()).await?;
}
Ok(())
}

pub fn sync_ser_bedrock(writer: &mut impl Write, kv: TranslateKV) -> Result<()> {
pub fn sync_ser_bedrock(writer: &mut impl Write, kv: &TranslateKV) -> Result<()> {
for (k, v) in kv {
writeln!(writer, "{k}={v}")?;
}
Expand Down

0 comments on commit d667c9f

Please sign in to comment.