1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! A Backend that can compile to minecraft datapacks

use crate::datapack::templates::{template_load_json, template_pack_mcmeta, template_tick_json};

use datapack_common::{directories, vfs::Directory};
use debris_common::Config;

mod generator;

mod backend;
pub use backend::DatapackBackend;

mod stringify;
mod templates;

mod scoreboard_constants;

mod function_context;

mod scoreboard_context;

pub mod json_formatter;

/// Represents an in-memory datapack
#[derive(Debug, Default)]
struct Datapack {
    /// The virtual file structure
    dir: Directory,
    /// The name of the main directory
    main_dir: String,
}

impl Datapack {
    const FUNCTION_TAGS_PATH: [&'static str; 4] = ["data", "minecraft", "tags", "functions"];

    /// Creates a new `Datapack` from a [Config]
    ///
    /// Looks like the vfs implementation is really bad
    fn new(config: &Config) -> Self {
        let main_dir = config.project_name.to_ascii_lowercase();
        let dir = directories! {
            "pack.mcmeta" => File(template_pack_mcmeta(config.into())),
            data => directories! {
                main_dir.clone() => directories! {
                    functions => directories!()
                },
                minecraft => directories! {
                    tags => directories! {
                        functions => directories! {}
                    }
                }
            }
        };
        Datapack { dir, main_dir }
    }

    fn add_tick_json(&mut self, config: &Config) {
        let file = self
            .dir
            .resolve_path(&Self::FUNCTION_TAGS_PATH)
            .unwrap()
            .dir()
            .unwrap()
            .file("tick.json".into());
        file.contents = template_tick_json(config.into());
    }

    fn add_load_json(&mut self, config: &Config) {
        let file = self
            .dir
            .resolve_path(&Self::FUNCTION_TAGS_PATH)
            .unwrap()
            .dir()
            .unwrap()
            .file("load.json".into());
        file.contents = template_load_json(config.into());
    }

    /// Returns the functions directory of this pack
    fn functions(&mut self) -> &mut Directory {
        match self
            .dir
            .resolve_path(&["data", &self.main_dir, "functions"])
            .unwrap()
        {
            datapack_common::vfs::FsElement::Directory(dir) => dir,
            datapack_common::vfs::FsElement::File(_) => unreachable!(),
        }
    }
}

#[cfg(test)]
mod tests {
    use debris_common::Config;
    use tempfile::tempdir;

    use super::Datapack;

    #[test]
    fn test_default_pack() {
        let config = Config::default();
        let datapack = Datapack::new(&config);

        let temp_dir = tempdir().expect("Could not get a temporary directory");

        datapack
            .dir
            .persist("test_pack", temp_dir.path())
            .expect("Failed to persist");
    }
}