diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java index 96bccd892..d2da2fb2a 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitPlatform.java @@ -732,6 +732,11 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl this.getServer().getPluginManager().disablePlugin(this); } + @Override + public void shutdownServer() { + getServer().shutdown(); + } + private void registerCommands() { final BukkitCommand bukkitCommand = new BukkitCommand(); final PluginCommand plotCommand = getCommand("plots"); diff --git a/Core/src/main/java/com/plotsquared/core/PlotPlatform.java b/Core/src/main/java/com/plotsquared/core/PlotPlatform.java index 75ceef94d..020c3c740 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotPlatform.java +++ b/Core/src/main/java/com/plotsquared/core/PlotPlatform.java @@ -75,6 +75,11 @@ public interface PlotPlatform

extends LocaleHolder { */ void shutdown(); + /** + * Completely shuts down the server. + */ + void shutdownServer(); + /** * Get the name of the plugin * diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 9b8d2fd02..5f89c69c1 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -197,6 +197,9 @@ public class PlotSquared { this.loadCaptionMap(); } catch (final Exception e) { LOGGER.error("Failed to load caption map", e); + LOGGER.error("Shutting down server to prevent further issues"); + this.platform.shutdownServer(); + throw new RuntimeException("Abort loading PlotSquared"); } // Setup the global flag container @@ -267,7 +270,7 @@ public class PlotSquared { captionMap = this.captionLoader.loadAll(this.platform.getDirectory().toPath().resolve("lang")); } else { String fileName = "messages_" + Settings.Enabled_Components.DEFAULT_LOCALE + ".json"; - captionMap = this.captionLoader.loadSingle(this.platform.getDirectory().toPath().resolve("lang").resolve(fileName)); + captionMap = this.captionLoader.loadOrCreateSingle(this.platform.getDirectory().toPath().resolve("lang").resolve(fileName)); } this.captionMaps.put(TranslatableCaption.DEFAULT_NAMESPACE, captionMap); LOGGER.info( diff --git a/Core/src/main/java/com/plotsquared/core/configuration/caption/load/CaptionLoader.java b/Core/src/main/java/com/plotsquared/core/configuration/caption/load/CaptionLoader.java index 4a8b5c14f..ca6e934b0 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/caption/load/CaptionLoader.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/caption/load/CaptionLoader.java @@ -190,13 +190,14 @@ public final class CaptionLoader { /** * Load a message file into a new CaptionMap. The file name must match - * the pattern {@code messages_.json} where {@code } - * is a valid {@link Locale} string. + * the pattern expected by the {@link #localeExtractor}. + * Note that this method does not attempt to create a new file. * * @param file The file to load * @return A new CaptionMap containing the loaded messages * @throws IOException if the file couldn't be accessed or read successfully. * @throws IllegalArgumentException if the file name doesn't match the specified format. + * @see #loadOrCreateSingle(Path) */ public @NonNull CaptionMap loadSingle(final @NonNull Path file) throws IOException { final Locale locale = this.localeExtractor.apply(file); @@ -205,15 +206,43 @@ public final class CaptionLoader { if (patch(map, locale)) { save(file, map); // update the file using the modified map } - return new LocalizedCaptionMap(locale, map.entrySet().stream() - .collect(Collectors.toMap( - entry -> TranslatableCaption.of(this.namespace, entry.getKey()), - Map.Entry::getValue - ) - )); + return new LocalizedCaptionMap(locale, mapToCaptions(map)); } } + /** + * Load a message file into a new CaptionMap. The file name must match + * the pattern expected by the {@link #localeExtractor}. + * If no file exists at the given path, this method will + * attempt to create one and fill it with default values. + * + * @param file The file to load + * @return A new CaptionMap containing the loaded messages + * @throws IOException if the file couldn't be accessed or read successfully. + * @throws IllegalArgumentException if the file name doesn't match the specified format. + * @see #loadSingle(Path) + * @since TODO + */ + public @NonNull CaptionMap loadOrCreateSingle(final @NonNull Path file) throws IOException { + final Locale locale = this.localeExtractor.apply(file); + if (!Files.exists(file) ) { + Map map = new LinkedHashMap<>(); + patch(map, locale); + save(file, map); + return new LocalizedCaptionMap(locale, mapToCaptions(map)); + } else { + return loadSingle(file); + } + } + + private @NonNull Map mapToCaptions(Map map) { + return map.entrySet().stream().collect( + Collectors.toMap( + entry -> TranslatableCaption.of(this.namespace, entry.getKey()), + Map.Entry::getValue + )); + } + /** * Add missing entries to the given map. * Entries are missing if the key exists in {@link #defaultLocale} but isn't present