Skip to content
Snippets Groups Projects
Commit fbc0219c authored by AnimeGitB's avatar AnimeGitB
Browse files

Allow loading Resources from zip files

Move Resources loading from String filenames to Paths
Add zip support
parent a90455a7
Branches
Tags
No related merge requests found
......@@ -45,7 +45,6 @@ import javax.annotation.Nullable;
import java.io.*;
import java.util.Calendar;
import static emu.grasscutter.config.Configuration.DATA;
import static emu.grasscutter.config.Configuration.SERVER;
import static emu.grasscutter.utils.Language.translate;
......@@ -203,7 +202,7 @@ public final class Grasscutter {
// If the file already exists, we attempt to load it.
try {
config = JsonUtils.loadToClass(configFile.getPath(), ConfigContainer.class);
config = JsonUtils.loadToClass(configFile.toPath(), ConfigContainer.class);
} catch (Exception exception) {
getLogger().error("There was an error while trying to load the configuration from config.json. Please make sure that there are no syntax errors. If you want to start with a default configuration, delete your existing config.json.");
System.exit(1);
......
......@@ -26,7 +26,7 @@ public class ConfigContainer {
*/
public static void updateConfig() {
try { // Check if the server is using a legacy config.
JsonObject configObject = JsonUtils.loadToClass(Grasscutter.configFile.getPath(), JsonObject.class);
JsonObject configObject = JsonUtils.loadToClass(Grasscutter.configFile.toPath(), JsonObject.class);
if (!configObject.has("version")) {
Grasscutter.getLogger().info("Updating legacy ..");
Grasscutter.saveConfig(null);
......
package emu.grasscutter.config;
import java.util.Locale;
import java.util.stream.Stream;
import emu.grasscutter.Grasscutter;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static emu.grasscutter.Grasscutter.config;
......@@ -30,6 +38,42 @@ public final class Configuration extends ConfigContainer {
private static final String PLUGINS_FOLDER = config.folderStructure.plugins;
private static final String SCRIPTS_FOLDER = config.folderStructure.scripts;
private static final String PACKETS_FOLDER = config.folderStructure.packets;
private static final FileSystem RESOURCES_FILE_SYSTEM; // Not sure about lifetime rules on this one, might be safe to remove
private static final Path RESOURCES_PATH;
static {
FileSystem fs = null;
Path path = Path.of(RESOURCES_FOLDER);
if (RESOURCES_FOLDER.endsWith(".zip")) { // Would be nice to support .tar.gz too at some point, but it doesn't come for free in Java
try {
fs = FileSystems.newFileSystem(path);
} catch (IOException e) {
Grasscutter.getLogger().error("Failed to load resources zip \"" + RESOURCES_FOLDER + "\"");
}
}
if (fs != null) {
var root = fs.getPath("");
try (Stream<Path> pathStream = java.nio.file.Files.find(root, 3, (p, a) -> {
var filename = p.getFileName();
if (filename == null) return false;
return filename.toString().equals("ExcelBinOutput");
})) {
var excelBinOutput = pathStream.findFirst();
if (excelBinOutput.isPresent()) {
path = excelBinOutput.get().getParent();
if (path == null)
path = root;
Grasscutter.getLogger().debug("Resources will be loaded from \"" + RESOURCES_FOLDER + "/" + path.toString() + "\"");
} else {
Grasscutter.getLogger().error("Failed to find ExcelBinOutput in resources zip \"" + RESOURCES_FOLDER + "\"");
}
} catch (IOException e) {
Grasscutter.getLogger().error("Failed to scan resources zip \"" + RESOURCES_FOLDER + "\"");
}
}
RESOURCES_FILE_SYSTEM = fs;
RESOURCES_PATH = path;
};
public static final Server SERVER = config.server;
public static final Database DATABASE = config.databaseInfo;
......@@ -54,11 +98,15 @@ public final class Configuration extends ConfigContainer {
}
public static String DATA(String path) {
return Paths.get(DATA_FOLDER, path).toString();
return Path.of(DATA_FOLDER, path).toString();
}
public static Path getResourcePath(String path) {
return RESOURCES_PATH.resolve(path);
}
public static String RESOURCE(String path) {
return Paths.get(RESOURCES_FOLDER, path).toString();
return getResourcePath(path).toString();
}
public static String PLUGIN() {
......@@ -66,15 +114,15 @@ public final class Configuration extends ConfigContainer {
}
public static String PLUGIN(String path) {
return Paths.get(PLUGINS_FOLDER, path).toString();
return Path.of(PLUGINS_FOLDER, path).toString();
}
public static String SCRIPT(String path) {
return Paths.get(SCRIPTS_FOLDER, path).toString();
return Path.of(SCRIPTS_FOLDER, path).toString();
}
public static String PACKET(String path) {
return Paths.get(PACKETS_FOLDER, path).toString();
return Path.of(PACKETS_FOLDER, path).toString();
}
/**
......
This diff is collapsed.
......@@ -2,9 +2,11 @@ package emu.grasscutter.tools;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
......@@ -215,11 +217,15 @@ public final class Tools {
}
public static List<String> getAvailableLanguage() {
File textMapFolder = new File(RESOURCE("TextMap"));
List<String> availableLangList = new ArrayList<>();
for (String textMapFileName : Objects.requireNonNull(textMapFolder.list((dir, name) -> name.startsWith("TextMap") && name.endsWith(".json")))) {
availableLangList.add(textMapFileName.replace("TextMap", "").replace(".json", "").toLowerCase());
} return availableLangList;
try {
Files.newDirectoryStream(getResourcePath("TextMap"), "TextMap*.json").forEach(path -> {
availableLangList.add(path.getFileName().toString().replace("TextMap", "").replace(".json", "").toLowerCase());
});
} catch (IOException e) {
Grasscutter.getLogger().error("Failed to get available languages:", e);
}
return availableLangList;
}
@Deprecated(forRemoval = true, since = "1.2.3")
......
......@@ -9,7 +9,6 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
......@@ -17,7 +16,7 @@ import java.util.stream.Collectors;
public final class FileUtils {
public static void write(String dest, byte[] bytes) {
Path path = Paths.get(dest);
Path path = Path.of(dest);
try {
Files.write(path, bytes);
......@@ -27,7 +26,7 @@ public final class FileUtils {
}
public static byte[] read(String dest) {
return read(Paths.get(dest));
return read(Path.of(dest));
}
public static byte[] read(Path path) {
......
......@@ -3,7 +3,10 @@ package emu.grasscutter.utils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
......@@ -32,36 +35,57 @@ public final class JsonUtils {
return gson.fromJson(jsonElement, classType);
}
public static <T> T loadToClass(InputStreamReader fileReader, Class<T> classType) throws IOException {
public static <T> T loadToClass(Reader fileReader, Class<T> classType) throws IOException {
return gson.fromJson(fileReader, classType);
}
@Deprecated
public static <T> T loadToClass(String filename, Class<T> classType) throws IOException {
try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) {
return loadToClass(fileReader, classType);
}
}
public static <T> List<T> loadToList(InputStreamReader fileReader, Class<T> classType) throws IOException {
public static <T> T loadToClass(Path filename, Class<T> classType) throws IOException {
try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) {
return loadToClass(fileReader, classType);
}
}
public static <T> List<T> loadToList(Reader fileReader, Class<T> classType) throws IOException {
return gson.fromJson(fileReader, TypeToken.getParameterized(List.class, classType).getType());
}
@Deprecated
public static <T> List<T> loadToList(String filename, Class<T> classType) throws IOException {
try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) {
return loadToList(fileReader, classType);
}
}
public static <T1,T2> Map<T1,T2> loadToMap(InputStreamReader fileReader, Class<T1> keyType, Class<T2> valueType) throws IOException {
public static <T> List<T> loadToList(Path filename, Class<T> classType) throws IOException {
try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) {
return loadToList(fileReader, classType);
}
}
public static <T1,T2> Map<T1,T2> loadToMap(Reader fileReader, Class<T1> keyType, Class<T2> valueType) throws IOException {
return gson.fromJson(fileReader, TypeToken.getParameterized(Map.class, keyType, valueType).getType());
}
@Deprecated
public static <T1,T2> Map<T1,T2> loadToMap(String filename, Class<T1> keyType, Class<T2> valueType) throws IOException {
try (InputStreamReader fileReader = new InputStreamReader(new FileInputStream(Utils.toFilePath(filename)), StandardCharsets.UTF_8)) {
return loadToMap(fileReader, keyType, valueType);
}
}
public static <T1,T2> Map<T1,T2> loadToMap(Path filename, Class<T1> keyType, Class<T2> valueType) throws IOException {
try (var fileReader = Files.newBufferedReader(filename, StandardCharsets.UTF_8)) {
return loadToMap(fileReader, keyType, valueType);
}
}
/**
* Safely JSON decodes a given string.
* @param jsonData The JSON-encoded data.
......
......@@ -325,7 +325,7 @@ public final class Language {
private static Int2ObjectMap<String> loadTextMapFile(String language, IntSet nameHashes) {
Int2ObjectMap<String> output = new Int2ObjectOpenHashMap<>();
try (BufferedReader file = new BufferedReader(new FileReader(Utils.toFilePath(RESOURCE("TextMap/TextMap"+language+".json")), StandardCharsets.UTF_8))) {
try (BufferedReader file = Files.newBufferedReader(getResourcePath("TextMap/TextMap"+language+".json"), StandardCharsets.UTF_8)) {
Matcher matcher = textMapKeyValueRegex.matcher("");
return new Int2ObjectOpenHashMap<>(
file.lines()
......@@ -406,7 +406,7 @@ public final class Language {
try {
long cacheModified = Files.getLastModifiedTime(TEXTMAP_CACHE_PATH).toMillis();
long textmapsModified = Files.list(Path.of(RESOURCE("TextMap")))
long textmapsModified = Files.list(getResourcePath("TextMap"))
.filter(path -> path.toString().endsWith(".json"))
.map(path -> {
try {
......
......@@ -22,6 +22,7 @@ import org.slf4j.Logger;
import javax.annotation.Nullable;
import static emu.grasscutter.config.Configuration.getResourcePath;
import static emu.grasscutter.utils.Language.translate;
@SuppressWarnings({"UnusedReturnValue", "BooleanMethodIsAlwaysInverted"})
......@@ -169,19 +170,18 @@ public final class Utils {
Logger logger = Grasscutter.getLogger();
boolean exit = false;
String resourcesFolder = config.folderStructure.resources;
String dataFolder = config.folderStructure.data;
// Check for resources folder.
if (!fileExists(resourcesFolder)) {
if (!Files.exists(getResourcePath(""))) {
logger.info(translate("messages.status.create_resources"));
logger.info(translate("messages.status.resources_error"));
createFolder(resourcesFolder); exit = true;
createFolder(config.folderStructure.resources); exit = true;
}
// Check for BinOutput + ExcelBinOutput.
if (!fileExists(resourcesFolder + "BinOutput") ||
!fileExists(resourcesFolder + "ExcelBinOutput")) {
if (!Files.exists(getResourcePath("BinOutput")) ||
!Files.exists(getResourcePath("ExcelBinOutput"))) {
logger.info(translate("messages.status.resources_error"));
exit = true;
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment