DataLoader.java 5.68 KB
Newer Older
1
2
3
4
5
6
package emu.grasscutter.data;

import emu.grasscutter.Grasscutter;
import emu.grasscutter.server.http.handlers.GachaHandler;
import emu.grasscutter.tools.Tools;
import emu.grasscutter.utils.FileUtils;
7
import emu.grasscutter.utils.JsonUtils;
8
9
import emu.grasscutter.utils.TsvUtils;
import lombok.val;
10

KingRainbow44's avatar
KingRainbow44 committed
11
import java.io.FileNotFoundException;
12
import java.io.IOException;
KingRainbow44's avatar
KingRainbow44 committed
13
import java.io.InputStream;
14
import java.io.InputStreamReader;
15
import java.nio.file.Files;
16
17
import java.nio.file.Path;
import java.util.List;
18
import java.util.Map;
19
20
21
22
23

public class DataLoader {

    /**
     * Load a data file by its name. If the file isn't found within the /data directory then it will fallback to the default within the jar resources
KingRainbow44's avatar
KingRainbow44 committed
24
     *
25
26
27
     * @param resourcePath The path to the data file to be loaded.
     * @return InputStream of the data file.
     * @throws FileNotFoundException
KingRainbow44's avatar
KingRainbow44 committed
28
     * @see #load(String, boolean)
29
30
31
32
     */
    public static InputStream load(String resourcePath) throws FileNotFoundException {
        return load(resourcePath, true);
    }
github-actions's avatar
github-actions committed
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    /**
     * Creates an input stream reader for a data file. If the file isn't found within the /data directory then it will fallback to the default within the jar resources
     *
     * @param resourcePath The path to the data file to be loaded.
     * @return InputStreamReader of the data file.
     * @throws IOException
     * @throws FileNotFoundException
     * @see #load(String, boolean)
     */
    public static InputStreamReader loadReader(String resourcePath) throws IOException, FileNotFoundException {
        try {
            InputStream is = load(resourcePath, true);
            return new InputStreamReader(is);
        } catch (FileNotFoundException exception) {
            throw exception;
        }
    }
51
52
53

    /**
     * Load a data file by its name.
KingRainbow44's avatar
KingRainbow44 committed
54
     *
55
     * @param resourcePath The path to the data file to be loaded.
KingRainbow44's avatar
KingRainbow44 committed
56
     * @param useFallback  If the file does not exist in the /data directory, should it use the default file in the jar?
57
58
59
60
     * @return InputStream of the data file.
     * @throws FileNotFoundException
     */
    public static InputStream load(String resourcePath, boolean useFallback) throws FileNotFoundException {
61
62
63
64
        Path path = useFallback
            ? FileUtils.getDataPath(resourcePath)
            : FileUtils.getDataUserPath(resourcePath);
        if (Files.exists(path)) {
65
            // Data is in the resource directory
66
67
68
69
            try {
                return Files.newInputStream(path);
            } catch (IOException e) {
                throw new FileNotFoundException(e.getMessage());  // This is evil but so is changing the function signature at this point
70
71
72
73
74
            }
        }
        return null;
    }

75
76
    public static <T> T loadClass(String resourcePath, Class<T> classType) throws IOException {
        try (InputStreamReader reader = loadReader(resourcePath)) {
77
            return JsonUtils.loadToClass(reader, classType);
78
79
80
81
82
        }
    }

    public static <T> List<T> loadList(String resourcePath, Class<T> classType) throws IOException {
        try (InputStreamReader reader = loadReader(resourcePath)) {
83
            return JsonUtils.loadToList(reader, classType);
84
85
86
87
88
        }
    }

    public static <T1,T2> Map<T1,T2> loadMap(String resourcePath, Class<T1> keyType, Class<T2> valueType) throws IOException {
        try (InputStreamReader reader = loadReader(resourcePath)) {
89
            return JsonUtils.loadToMap(reader, keyType, valueType);
90
91
92
        }
    }

93
94
95
96
97
98
99
100
101
102
103
    public static <T> List<T> loadTableToList(String resourcePath, Class<T> classType) throws IOException {
        val path = FileUtils.getDataPathTsjJsonTsv(resourcePath);
        Grasscutter.getLogger().info("Loading data table from: "+path);
        return switch (FileUtils.getFileExtension(path)) {
            case "json" -> JsonUtils.loadToList(path, classType);
            case "tsj" -> TsvUtils.loadTsjToListSetField(path, classType);
            case "tsv" -> TsvUtils.loadTsvToListSetField(path, classType);
            default -> null;
        };
    }

104
    public static void checkAllFiles() {
105
106
        try {
            List<Path> filenames = FileUtils.getPathsFromResource("/defaults/data/");
KingRainbow44's avatar
KingRainbow44 committed
107

108
            if (filenames == null) {
KingRainbow44's avatar
KingRainbow44 committed
109
                Grasscutter.getLogger().error("We were unable to locate your default data files.");
110
111
            } //else for (Path file : filenames) {
            //     String relativePath = String.valueOf(file).split("defaults[\\\\\\/]data[\\\\\\/]")[1];
112

113
114
            //     checkAndCopyData(relativePath);
            // }
115
        } catch (Exception e) {
116
            Grasscutter.getLogger().error("An error occurred while trying to check the data folder.", e);
117
118
        }

119
        generateGachaMappings();
120
121
    }

122
    private static void checkAndCopyData(String name) {
123
124
125
126
127
128
129
        // TODO: Revisit this if default dumping is ever reintroduced
        Path filePath = FileUtils.getDataPath(name);

        if (!Files.exists(filePath)) {
            var root = filePath.getParent();
            if (root.toFile().mkdirs())
                Grasscutter.getLogger().info("Created data folder '" + root + "'");
130
131

            Grasscutter.getLogger().info("Creating default '" + name + "' data");
132
            FileUtils.copyResource("/defaults/data/" + name, filePath.toString());
133
134
135
        }
    }

136
    private static void generateGachaMappings() {
137
138
        var path = GachaHandler.getGachaMappingsPath();
        if (!Files.exists(path)) {
139
            try {
140
141
                Grasscutter.getLogger().info("Creating default '" + path.toString() + "' data");
                Tools.createGachaMappings(path);
142
143
144
145
146
147
            } catch (Exception exception) {
                Grasscutter.getLogger().warn("Failed to create gacha mappings. \n" + exception);
            }
        }
    }
}