From 5c7441241cc85010de42cdb525a58151cb8ec6bd Mon Sep 17 00:00:00 2001 From: Astrash Date: Sat, 25 Nov 2023 12:37:56 +1100 Subject: [PATCH] Replace Loader with java.nio.files --- .../dfsek/terra/addons/yaml/YamlAddon.java | 25 +++++- .../terra/addons/image/ImageLibraryAddon.java | 4 +- .../addons/image/config/image/ImageCache.java | 24 ++---- .../image/config/image/ImageTemplate.java | 7 +- .../config/image/StitchedImageTemplate.java | 7 +- .../addons/sponge/SpongeSchematicAddon.java | 24 ++++-- .../addons/terrascript/TerraScriptAddon.java | 47 ++++++----- .../dfsek/terra/api/config/ConfigPack.java | 3 +- .../com/dfsek/terra/api/config/Loader.java | 47 ----------- .../config/ConfigurationDiscoveryEvent.java | 10 +-- .../com/dfsek/terra/api/util/FileUtil.java | 39 +++++++++ .../com/dfsek/terra/api/util/StringUtil.java | 25 ------ .../com/dfsek/terra/AbstractPlatform.java | 6 +- .../config/fileloaders/FolderLoader.java | 66 --------------- .../terra/config/fileloaders/LoaderImpl.java | 83 ------------------- .../terra/config/fileloaders/ZIPLoader.java | 63 -------------- .../loaders/config/BufferedImageLoader.java | 8 +- .../terra/config/pack/ConfigPackImpl.java | 69 ++++++--------- .../terra/registry/master/ConfigRegistry.java | 46 +++------- .../com/dfsek/terra/bukkit/PlatformImpl.java | 8 +- .../com/dfsek/terra/forge/ForgePlatform.java | 8 +- .../terra/lifecycle/LifecyclePlatform.java | 9 +- 22 files changed, 186 insertions(+), 442 deletions(-) delete mode 100644 common/api/src/main/java/com/dfsek/terra/api/config/Loader.java create mode 100644 common/api/src/main/java/com/dfsek/terra/api/util/FileUtil.java delete mode 100644 common/api/src/main/java/com/dfsek/terra/api/util/StringUtil.java delete mode 100644 common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java delete mode 100644 common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/LoaderImpl.java delete mode 100644 common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java diff --git a/common/addons/language-yaml/src/main/java/com/dfsek/terra/addons/yaml/YamlAddon.java b/common/addons/language-yaml/src/main/java/com/dfsek/terra/addons/yaml/YamlAddon.java index 08cb9751a..31aad8be5 100644 --- a/common/addons/language-yaml/src/main/java/com/dfsek/terra/addons/yaml/YamlAddon.java +++ b/common/addons/language-yaml/src/main/java/com/dfsek/terra/addons/yaml/YamlAddon.java @@ -8,6 +8,9 @@ package com.dfsek.terra.addons.yaml; import com.dfsek.tectonic.yaml.YamlConfiguration; + +import com.dfsek.terra.api.util.FileUtil; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,6 +21,9 @@ import com.dfsek.terra.api.event.events.config.ConfigurationDiscoveryEvent; import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.inject.annotations.Inject; +import java.io.IOException; +import java.nio.file.Files; + public class YamlAddon implements AddonInitializer { @@ -33,10 +39,21 @@ public class YamlAddon implements AddonInitializer { platform.getEventManager() .getHandler(FunctionalEventHandler.class) .register(addon, ConfigurationDiscoveryEvent.class) - .then(event -> event.getLoader().open("", ".yml").thenEntries(entries -> entries.forEach(entry -> { - LOGGER.debug("Discovered config {}", entry.getKey()); - event.register(entry.getKey(), new YamlConfiguration(entry.getValue(), entry.getKey())); - })).close()) + .then(event -> { + try { + FileUtil.filesWithExtension(event.getPack().getPackDirectory(), ".yml") + .forEach((key, value) -> { + LOGGER.debug("Discovered config {}", key); + try { + event.register(key, new YamlConfiguration(Files.newInputStream(value), key)); + } catch(IOException e) { + throw new RuntimeException(e); + } + }); + } catch(IOException e) { + throw new RuntimeException(e); + } + }) .failThrough(); } } diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/ImageLibraryAddon.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/ImageLibraryAddon.java index b383c4ca7..b29920160 100644 --- a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/ImageLibraryAddon.java +++ b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/ImageLibraryAddon.java @@ -60,8 +60,8 @@ public class ImageLibraryAddon implements AddonInitializer { .then(event -> { ConfigPack pack = event.getPack(); CheckedRegistry>> imageRegistry = pack.getOrCreateRegistry(IMAGE_REGISTRY_KEY); - imageRegistry.register(addon.key("BITMAP"), () -> new ImageTemplate(pack.getLoader(), pack)); - imageRegistry.register(addon.key("STITCHED_BITMAP"), () -> new StitchedImageTemplate(pack.getLoader(), pack)); + imageRegistry.register(addon.key("BITMAP"), () -> new ImageTemplate(pack)); + imageRegistry.register(addon.key("STITCHED_BITMAP"), () -> new StitchedImageTemplate(pack)); }) .then(event -> { event.getPack() diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageCache.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageCache.java index 9283aa4b7..be352ac47 100644 --- a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageCache.java +++ b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageCache.java @@ -4,8 +4,10 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import javax.imageio.ImageIO; -import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.concurrent.TimeUnit; import com.dfsek.terra.addons.image.config.ImageLibraryPackConfigTemplate; @@ -13,7 +15,6 @@ import com.dfsek.terra.addons.image.image.BufferedImageWrapper; import com.dfsek.terra.addons.image.image.Image; import com.dfsek.terra.addons.image.image.SuppliedImage; import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.config.Loader; import com.dfsek.terra.api.properties.Properties; import com.dfsek.terra.api.util.generic.Lazy; @@ -22,13 +23,13 @@ import com.dfsek.terra.api.util.generic.Lazy; * Cache prevents configs from loading the same image multiple times into memory */ record ImageCache(LoadingCache cache) implements Properties { - public static Image load(String path, ConfigPack pack, Loader files) throws IOException { + public static Image load(String path, ConfigPack pack) throws IOException { ImageLibraryPackConfigTemplate config = pack.getContext().get(ImageLibraryPackConfigTemplate.class); ImageCache images; if(!pack.getContext().has(ImageCache.class)) { var cacheBuilder = Caffeine.newBuilder(); if(config.unloadOnTimeout()) cacheBuilder.expireAfterAccess(config.getCacheTimeout(), TimeUnit.SECONDS); - images = new ImageCache(cacheBuilder.build(s -> loadImage(s, files))); + images = new ImageCache(cacheBuilder.build(s -> loadImage(s, pack.getPackDirectory()))); pack.getContext().put(images); } else images = pack.getContext().get(ImageCache.class); @@ -45,17 +46,8 @@ record ImageCache(LoadingCache cache) implements Properties { return images.cache.get(path); } - private static Image loadImage(String path, Loader files) throws IOException { - try { - return new BufferedImageWrapper(ImageIO.read(files.get(path))); - } catch(IllegalArgumentException e) { - throw new IllegalArgumentException("Unable to load image (image might be too large?)", e); - } catch(IOException e) { - if(e instanceof FileNotFoundException) { - // Rethrow using nicer message - throw new IOException("Unable to load image: No such file or directory: " + path, e); - } - throw new IOException("Unable to load image", e); - } + private static Image loadImage(String path, Path directory) throws IOException { + InputStream is = Files.newInputStream(directory.resolve(path)); + return new BufferedImageWrapper(ImageIO.read(is)); } } diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageTemplate.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageTemplate.java index dc33bf13c..0ef7ee751 100644 --- a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageTemplate.java +++ b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageTemplate.java @@ -7,25 +7,22 @@ import java.io.IOException; import com.dfsek.terra.addons.image.image.Image; import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.config.Loader; public class ImageTemplate implements ObjectTemplate { - private final Loader files; private final ConfigPack pack; @Value("path") private String path; - public ImageTemplate(Loader files, ConfigPack pack) { - this.files = files; + public ImageTemplate(ConfigPack pack) { this.pack = pack; } @Override public Image get() { try { - return ImageCache.load(path, pack, files); + return ImageCache.load(path, pack); } catch(IOException e) { throw new RuntimeException(e); } diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/StitchedImageTemplate.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/StitchedImageTemplate.java index 3a834a218..f7f7fb7e4 100644 --- a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/StitchedImageTemplate.java +++ b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/StitchedImageTemplate.java @@ -11,12 +11,10 @@ import java.io.IOException; import com.dfsek.terra.addons.image.image.Image; import com.dfsek.terra.addons.image.image.StitchedImage; import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.config.Loader; public class StitchedImageTemplate implements ObjectTemplate, ValidatedConfigTemplate { - private final Loader files; private final ConfigPack pack; @Value("path-format") private String path; @@ -28,8 +26,7 @@ public class StitchedImageTemplate implements ObjectTemplate, ValidatedCo @Default private boolean zeroIndexed = false; - public StitchedImageTemplate(Loader files, ConfigPack pack) { - this.files = files; + public StitchedImageTemplate(ConfigPack pack) { this.pack = pack; } @@ -39,7 +36,7 @@ public class StitchedImageTemplate implements ObjectTemplate, ValidatedCo for(int i = 0; i < rows; i++) { for(int j = 0; j < cols; j++) { try { - grid[i][j] = ImageCache.load(getFormattedPath(i, j), pack, files); + grid[i][j] = ImageCache.load(getFormattedPath(i, j), pack); } catch(IOException e) { throw new RuntimeException(e); } diff --git a/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeSchematicAddon.java b/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeSchematicAddon.java index 199864cd1..a3715048d 100644 --- a/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeSchematicAddon.java +++ b/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeSchematicAddon.java @@ -7,6 +7,8 @@ package com.dfsek.terra.addons.sponge; +import com.dfsek.terra.api.util.FileUtil; + import net.querz.nbt.io.NBTDeserializer; import net.querz.nbt.tag.ByteArrayTag; import net.querz.nbt.tag.CompoundTag; @@ -16,6 +18,7 @@ import net.querz.nbt.tag.Tag; import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; +import java.nio.file.Files; import java.util.HashMap; import java.util.Map; import java.util.zip.GZIPInputStream; @@ -29,7 +32,6 @@ import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.inject.annotations.Inject; import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.structure.Structure; -import com.dfsek.terra.api.util.StringUtil; import com.dfsek.terra.api.util.vector.Vector3Int; @@ -58,13 +60,21 @@ public class SpongeSchematicAddon implements AddonInitializer { .register(addon, ConfigPackPreLoadEvent.class) .then(event -> { CheckedRegistry structureRegistry = event.getPack().getOrCreateRegistry(Structure.class); - event.getPack() - .getLoader() - .open("", ".schem") - .thenEntries(entries -> entries + try { + FileUtil.filesWithExtension(event.getPack().getPackDirectory(), ".schem") + .entrySet() .stream() - .map(entry -> convert(entry.getValue(), StringUtil.fileName(entry.getKey()))) - .forEach(structureRegistry::register)).close(); + .map(entry -> { + try { + return convert(Files.newInputStream(entry.getValue()), FileUtil.fileName(entry.getKey())); + } catch(IOException e) { + throw new RuntimeException(e); + } + }) + .forEach(structureRegistry::register); + } catch(IOException e) { + throw new RuntimeException(e); + } }) .failThrough(); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java index b555b7bac..a494eef77 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java @@ -19,7 +19,10 @@ import com.dfsek.terra.api.inject.annotations.Inject; import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.structure.LootTable; import com.dfsek.terra.api.structure.Structure; -import com.dfsek.terra.api.util.StringUtil; +import com.dfsek.terra.api.util.FileUtil; + +import java.io.IOException; +import java.nio.file.Files; public class TerraScriptAddon implements AddonInitializer { @@ -37,26 +40,28 @@ public class TerraScriptAddon implements AddonInitializer { .then(event -> { CheckedRegistry structureRegistry = event.getPack().getOrCreateRegistry(Structure.class); CheckedRegistry lootRegistry = event.getPack().getOrCreateRegistry(LootTable.class); - event.getPack().getLoader().open("", ".tesf").thenEntries( - entries -> - entries.stream() - .parallel() - .map(entry -> { - try { - String id = StringUtil.fileName(entry.getKey()); - return new StructureScript(entry.getValue(), - addon.key(id), - platform, - structureRegistry, - lootRegistry, - event.getPack().getOrCreateRegistry(FunctionBuilder.class)); - } catch(ParseException e) { - throw new RuntimeException("Failed to load script \"" + entry.getKey() + "\"", e); - } - }) - .toList() - .forEach(structureRegistry::register)) - .close(); + try { + FileUtil.filesWithExtension(event.getPack().getPackDirectory(), ".tesf") + .entrySet() + .stream() + .parallel() + .map(entry -> { + try { + String id = FileUtil.fileName(entry.getKey()); + return new StructureScript(Files.newInputStream(entry.getValue()), + addon.key(id), + platform, + structureRegistry, + lootRegistry, + event.getPack().getOrCreateRegistry(FunctionBuilder.class)); + } catch(ParseException | IOException e) { + throw new RuntimeException("Failed to load script \"" + entry.getKey() + "\"", e); + } + }) + .forEach(structureRegistry::register); + } catch(IOException e) { + throw new RuntimeException(e); + } }) .priority(100) .failThrough(); diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/ConfigPack.java b/common/api/src/main/java/com/dfsek/terra/api/config/ConfigPack.java index 8e0214ff0..837c44d0b 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/config/ConfigPack.java +++ b/common/api/src/main/java/com/dfsek/terra/api/config/ConfigPack.java @@ -10,6 +10,7 @@ package com.dfsek.terra.api.config; import ca.solostudios.strata.version.Version; import ca.solostudios.strata.version.VersionRange; +import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -43,7 +44,7 @@ public interface ConfigPack extends LoaderRegistrar, List getStages(); - Loader getLoader(); + Path getPackDirectory(); String getAuthor(); diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/Loader.java b/common/api/src/main/java/com/dfsek/terra/api/config/Loader.java deleted file mode 100644 index 5b12e43c2..000000000 --- a/common/api/src/main/java/com/dfsek/terra/api/config/Loader.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2020-2023 Polyhedral Development - * - * The Terra API is licensed under the terms of the MIT License. For more details, - * reference the LICENSE file in the common/api directory. - */ - -package com.dfsek.terra.api.config; - -import com.dfsek.tectonic.api.exception.ConfigException; - -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; - - -public interface Loader { - - Loader thenNames(Consumer> consumer) throws ConfigException; - - Loader thenEntries(Consumer>> consumer) throws ConfigException; - - /** - * Get a single file from this Loader. - * - * @param singleFile File to get - * - * @return InputStream from file. - */ - InputStream get(String singleFile) throws IOException; - - /** - * Open a subdirectory. - * - * @param directory Directory to open - * @param extension File extension - */ - Loader open(String directory, String extension); - - /** - * Close all InputStreams opened. - */ - Loader close(); -} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationDiscoveryEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationDiscoveryEvent.java index fbe1c8a28..ee8b6489b 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationDiscoveryEvent.java +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationDiscoveryEvent.java @@ -9,10 +9,10 @@ package com.dfsek.terra.api.event.events.config; import com.dfsek.tectonic.api.config.Configuration; +import java.nio.file.Path; import java.util.function.BiConsumer; import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.config.Loader; import com.dfsek.terra.api.event.events.FailThroughEvent; import com.dfsek.terra.api.event.events.PackEvent; @@ -25,13 +25,11 @@ import com.dfsek.terra.api.event.events.PackEvent; */ public class ConfigurationDiscoveryEvent implements PackEvent, FailThroughEvent { private final ConfigPack pack; - private final Loader loader; private final BiConsumer consumer; - public ConfigurationDiscoveryEvent(ConfigPack pack, Loader loader, BiConsumer consumer) { + public ConfigurationDiscoveryEvent(ConfigPack pack, BiConsumer consumer) { this.pack = pack; - this.loader = loader; this.consumer = consumer; } @@ -43,8 +41,4 @@ public class ConfigurationDiscoveryEvent implements PackEvent, FailThroughEvent public ConfigPack getPack() { return pack; } - - public Loader getLoader() { - return loader; - } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/FileUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/FileUtil.java new file mode 100644 index 000000000..3d9f22fbe --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/FileUtil.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.api.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.function.Function.*; + + +public class FileUtil { + public static Map filesWithExtension(Path start, String... extensions) throws IOException { + if(Files.notExists(start) || !Files.isDirectory(start)) return Collections.emptyMap(); + try (Stream paths = Files.walk(start)) { + return paths + .filter(Files::isRegularFile) + .filter(p -> Arrays.stream(extensions).anyMatch(e -> p.getFileName().toString().endsWith(e))) + .collect(Collectors.toMap(p -> start.relativize(p).toString(), identity())); + } + } + + public static String fileName(String path) { + if(path.contains(File.separator)) { + return path.substring(path.lastIndexOf(File.separatorChar) + 1, path.lastIndexOf('.')); + } else if(path.contains("/")) { + return path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf('.')); + } else if(path.contains(".")) { + return path.substring(0, path.lastIndexOf('.')); + } else { + return path; + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/StringUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/StringUtil.java deleted file mode 100644 index d48753fb2..000000000 --- a/common/api/src/main/java/com/dfsek/terra/api/util/StringUtil.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2020-2023 Polyhedral Development - * - * The Terra API is licensed under the terms of the MIT License. For more details, - * reference the LICENSE file in the common/api directory. - */ - -package com.dfsek.terra.api.util; - -import java.io.File; - - -public class StringUtil { - public static String fileName(String path) { - if(path.contains(File.separator)) { - return path.substring(path.lastIndexOf(File.separatorChar) + 1, path.lastIndexOf('.')); - } else if(path.contains("/")) { - return path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf('.')); - } else if(path.contains(".")) { - return path.substring(0, path.lastIndexOf('.')); - } else { - return path; - } - } -} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java index 86d22bc2a..08c9acbce 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java @@ -149,7 +149,11 @@ public abstract class AbstractPlatform implements Platform { .register(internalAddon, PlatformInitializationEvent.class) .then(event -> { logger.info("Loading config packs..."); - configRegistry.loadAll(this); + try { + configRegistry.loadAll(this); + } catch(IOException e) { + logger.error("Error loading config packs", e); + } logger.info("Loaded packs."); }) .global(); diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java deleted file mode 100644 index fb236f6d7..000000000 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.config.fileloaders; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.stream.Stream; - - -/** - * Load all {@code *.yml} files from a {@link java.nio.file.Path}. - */ -public class FolderLoader extends LoaderImpl { - private static final Logger logger = LoggerFactory.getLogger(FolderLoader.class); - - private final Path path; - - public FolderLoader(Path path) { - this.path = path; - } - - @Override - public InputStream get(String singleFile) throws IOException { - return new FileInputStream(new File(path.toFile(), singleFile)); - } - - protected void load(String directory, String extension) { - File newPath = new File(path.toFile(), directory); - newPath.mkdirs(); - try(Stream paths = Files.walk(newPath.toPath())) { - paths.filter(Files::isRegularFile).filter(file -> file.toString().toLowerCase().endsWith(extension)).forEach(file -> { - try { - String rel = newPath.toPath().relativize(file).toString(); - streams.put(rel, new FileInputStream(file.toFile())); - } catch(FileNotFoundException e) { - logger.error("Could not find file to load", e); - } - }); - } catch(IOException e) { - logger.error("Error while loading files", e); - } - } -} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/LoaderImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/LoaderImpl.java deleted file mode 100644 index b1cfe97c6..000000000 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/LoaderImpl.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.config.fileloaders; - -import com.dfsek.tectonic.api.exception.ConfigException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; - -import com.dfsek.terra.api.config.Loader; - - -public abstract class LoaderImpl implements Loader { - private static final Logger logger = LoggerFactory.getLogger(LoaderImpl.class); - - protected final Map streams = new HashMap<>(); - - @Override - public Loader thenNames(Consumer> consumer) throws ConfigException { - consumer.accept(new ArrayList<>(streams.keySet())); - return this; - } - - @Override - public Loader thenEntries(Consumer>> consumer) throws ConfigException { - consumer.accept(streams.entrySet()); - return this; - } - - /** - * Open a subdirectory. - * - * @param directory Directory to open - * @param extension File extension - */ - @Override - public LoaderImpl open(String directory, String extension) { - if(!streams.isEmpty()) throw new IllegalStateException("Attempted to load new directory before closing existing InputStreams"); - load(directory, extension); - return this; - } - - /** - * Close all InputStreams opened. - */ - @Override - public Loader close() { - streams.forEach((name, input) -> { - try { - input.close(); - } catch(IOException e) { - logger.error("Error occurred while loading", e); - } - }); - streams.clear(); - return this; - } - - protected abstract void load(String directory, String extension); -} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java deleted file mode 100644 index 9bcd5962c..000000000 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Terra is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Terra. If not, see . - */ - -package com.dfsek.terra.config.fileloaders; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - - -public class ZIPLoader extends LoaderImpl { - private static final Logger logger = LoggerFactory.getLogger(ZIPLoader.class); - - private final ZipFile file; - - public ZIPLoader(ZipFile file) { - this.file = file; - } - - @Override - public InputStream get(String singleFile) throws IOException { - Enumeration entries = file.entries(); - while(entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if(!entry.isDirectory() && entry.getName().equals(singleFile)) return file.getInputStream(entry); - } - throw new IllegalArgumentException("No such file: " + singleFile); - } - - protected void load(String directory, String extension) { - Enumeration entries = file.entries(); - while(entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if(!entry.isDirectory() && entry.getName().startsWith(directory) && entry.getName().endsWith(extension)) { - try { - String rel = entry.getName().substring(directory.length()); - streams.put(rel, file.getInputStream(entry)); - } catch(IOException e) { - logger.error("Error while loading file from zip", e); - } - } - } - } -} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java index 078e62e87..61585aa27 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java @@ -27,10 +27,10 @@ import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; import java.lang.reflect.AnnotatedType; +import java.nio.file.Files; import java.util.concurrent.ConcurrentHashMap; import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.config.Loader; import com.dfsek.terra.api.properties.Properties; @@ -39,12 +39,10 @@ import com.dfsek.terra.api.properties.Properties; */ @Deprecated public class BufferedImageLoader implements TypeLoader { - private final Loader files; private final ConfigPack pack; - public BufferedImageLoader(Loader files, ConfigPack pack) { - this.files = files; + public BufferedImageLoader(ConfigPack pack) { this.pack = pack; if(!pack.getContext().has(ImageCache.class)) pack.getContext().put(new ImageCache(new ConcurrentHashMap<>())); @@ -55,7 +53,7 @@ public class BufferedImageLoader implements TypeLoader { throws LoadException { return pack.getContext().get(ImageCache.class).map.computeIfAbsent((String) c, s -> { try { - return ImageIO.read(files.get(s)); + return ImageIO.read(Files.newInputStream(pack.getPackDirectory().resolve(s))); } catch(IOException e) { throw new LoadException("Unable to load image", e, depthTracker); } diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java index 06b617cd8..fb0f96739 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java @@ -32,7 +32,6 @@ import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.config.ConfigFactory; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigType; -import com.dfsek.terra.api.config.Loader; import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.event.events.config.ConfigurationDiscoveryEvent; import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; @@ -45,15 +44,12 @@ import com.dfsek.terra.api.registry.OpenRegistry; import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.registry.key.RegistryKey; import com.dfsek.terra.api.tectonic.ShortcutLoader; -import com.dfsek.terra.api.util.generic.Construct; import com.dfsek.terra.api.util.generic.pair.Pair; import com.dfsek.terra.api.util.reflection.ReflectionUtil; import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider; -import com.dfsek.terra.config.fileloaders.FolderLoader; -import com.dfsek.terra.config.fileloaders.ZIPLoader; import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader; import com.dfsek.terra.config.loaders.config.BufferedImageLoader; import com.dfsek.terra.config.preprocessor.*; @@ -72,11 +68,13 @@ import java.awt.image.BufferedImage; import java.io.*; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** @@ -92,7 +90,7 @@ public class ConfigPackImpl implements ConfigPack { private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader(); private final ConfigLoader selfLoader = new ConfigLoader(); private final Platform platform; - private final Loader loader; + private final Path packDirectory; private final Map addons; @@ -106,40 +104,25 @@ public class ConfigPackImpl implements ConfigPack { private final RegistryKey key; - public ConfigPackImpl(File folder, Platform platform) { - this(new FolderLoader(folder.toPath()), Construct.construct(() -> { - try { - return new YamlConfiguration(new FileInputStream(new File(folder, "pack.yml")), "pack.yml"); - } catch(FileNotFoundException e) { - throw new UncheckedIOException("No pack.yml file found in " + folder.getAbsolutePath(), e); - } - }), platform); - } - - public ConfigPackImpl(ZipFile file, Platform platform) { - this(new ZIPLoader(file), Construct.construct(() -> { - ZipEntry pack = null; - Enumeration entries = file.entries(); - while(entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if(entry.getName().equals("pack.yml")) pack = entry; - } - - if(pack == null) throw new IllegalArgumentException("No pack.yml file found in " + file.getName()); - - try { - return new YamlConfiguration(file.getInputStream(pack), "pack.yml"); - } catch(IOException e) { - throw new UncheckedIOException("Unable to load pack.yml from ZIP file", e); - } - }), platform); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private ConfigPackImpl(Loader loader, Configuration packManifest, Platform platform) { + @SuppressWarnings({ "rawtypes" }) + public ConfigPackImpl(Path path, Platform platform) throws IOException { long start = System.nanoTime(); - this.loader = loader; + if(Files.notExists(path)) throw new FileNotFoundException("Could not create config pack, " + path + " does not exist"); + + if(Files.isDirectory(path)) { + this.packDirectory = path; + } else if(Files.isRegularFile(path) && path.getFileName().toString().endsWith(".zip")) { + FileSystem zipfs = FileSystems.newFileSystem(path); + this.packDirectory = zipfs.getPath("/"); + } else { + throw new IllegalArgumentException("Could not load config pack from " + path + ", not a directory or zip file"); + } + + Path packManifestPath = packDirectory.resolve("pack.yml"); + if(Files.notExists(packManifestPath)) throw new FileNotFoundException("No pack.yml found in " + path); + Configuration packManifest = new YamlConfiguration(Files.newInputStream(packManifestPath), packManifestPath.getFileName().toString()); + this.platform = platform; this.configTypeRegistry = createConfigRegistry(); @@ -223,7 +206,7 @@ public class ConfigPackImpl implements ConfigPack { private Map discoverConfigurations() { Map configurations = new HashMap<>(); - platform.getEventManager().callEvent(new ConfigurationDiscoveryEvent(this, loader, + platform.getEventManager().callEvent(new ConfigurationDiscoveryEvent(this, (s, c) -> configurations.put(s.replace("\\", "/"), c))); // Create all the configs. return configurations; @@ -268,7 +251,7 @@ public class ConfigPackImpl implements ConfigPack { @Override public void register(TypeRegistry registry) { registry.registerLoader(ConfigType.class, configTypeRegistry) - .registerLoader(BufferedImage.class, new BufferedImageLoader(loader, this)); + .registerLoader(BufferedImage.class, new BufferedImageLoader(this)); registryMap.forEach(registry::registerLoader); shortcuts.forEach(registry::registerLoader); // overwrite with delegated shortcuts if present } @@ -333,8 +316,8 @@ public class ConfigPackImpl implements ConfigPack { } @Override - public Loader getLoader() { - return loader; + public Path getPackDirectory() { + return packDirectory; } @Override diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java b/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java index 28886b354..1a4ed5d15 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java @@ -17,14 +17,13 @@ package com.dfsek.terra.registry.master; -import com.dfsek.tectonic.api.exception.ConfigException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; -import java.util.Objects; -import java.util.zip.ZipFile; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.config.ConfigPack; @@ -37,44 +36,19 @@ import com.dfsek.terra.registry.OpenRegistryImpl; * Class to hold config packs */ public class ConfigRegistry extends OpenRegistryImpl { - private static final Logger logger = LoggerFactory.getLogger(ConfigRegistry.class); public ConfigRegistry() { super(TypeKey.of(ConfigPack.class)); } - public void load(File folder, Platform platform) throws ConfigException { - ConfigPack pack = new ConfigPackImpl(folder, platform); - registerChecked(pack.getRegistryKey(), pack); - } - - public boolean loadAll(Platform platform) { - boolean valid = true; - File packsFolder = new File(platform.getDataFolder(), "packs"); - packsFolder.mkdirs(); - for(File dir : Objects.requireNonNull(packsFolder.listFiles(File::isDirectory))) { - try { - load(dir, platform); - } catch(ConfigException e) { - logger.error("Error loading config pack {}", dir.getName(), e); - valid = false; + public void loadAll(Platform platform) throws IOException { + Path packsDirectory = platform.getDataFolder().toPath().resolve("packs"); + Files.createDirectories(packsDirectory); + try (Stream packs = Files.list(packsDirectory)) { + for (Path path : packs.toList()) { + ConfigPack pack = new ConfigPackImpl(path, platform); + registerChecked(pack.getRegistryKey(), pack); } } - for(File zip : Objects.requireNonNull( - packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".terra")))) { - try { - logger.info("Loading ZIP archive: {}", zip.getName()); - load(new ZipFile(zip), platform); - } catch(IOException | ConfigException e) { - logger.error("Error loading config pack {}", zip.getName(), e); - valid = false; - } - } - return valid; - } - - public void load(ZipFile file, Platform platform) throws ConfigException { - ConfigPackImpl pack = new ConfigPackImpl(file, platform); - registerChecked(pack.getRegistryKey(), pack); } } diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java index 0ef6164d8..14be9a7d0 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java @@ -27,6 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.io.IOException; import java.util.List; import java.util.Locale; @@ -64,7 +65,12 @@ public class PlatformImpl extends AbstractPlatform { public boolean reload() { getTerraConfig().load(this); getRawConfigRegistry().clear(); - boolean succeed = getRawConfigRegistry().loadAll(this); + boolean succeed = true; + try { + getRawConfigRegistry().loadAll(this); + } catch(IOException e) { + succeed = false; + } Bukkit.getWorlds().forEach(world -> { if(world.getGenerator() instanceof BukkitChunkGeneratorWrapper wrapper) { diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java index c07bde6f3..301d37226 100644 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java +++ b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgePlatform.java @@ -34,6 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -63,7 +64,12 @@ public class ForgePlatform extends ModPlatform { public boolean reload() { getTerraConfig().load(this); getRawConfigRegistry().clear(); - boolean succeed = getRawConfigRegistry().loadAll(this); + boolean succeed = true; + try { + getRawConfigRegistry().loadAll(this); + } catch(IOException e) { + succeed = false; + } MinecraftServer server = getServer(); diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java index be845eb19..00f74bd1b 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java @@ -14,6 +14,7 @@ import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -64,8 +65,12 @@ public abstract class LifecyclePlatform extends ModPlatform { public boolean reload() { getTerraConfig().load(this); getRawConfigRegistry().clear(); - boolean succeed = getRawConfigRegistry().loadAll(this); - + boolean succeed = true; + try { + getRawConfigRegistry().loadAll(this); + } catch(IOException e) { + succeed = false; + } if(server != null) { BiomeUtil.registerBiomes(server.getRegistryManager().get(RegistryKeys.BIOME));