diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index f96b11f6b..f26dae170 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -85,8 +85,13 @@ public final class Tools { void newTranslatedLine(String template, TextStrings... textstrings) { for (int i = 0; i < TextStrings.NUM_LANGUAGES; i++) { String s = template; - for (int j = 0; j < textstrings.length; j++) + for (int j = 0; j < textstrings.length; j++) try { s = s.replace("{" + j + "}", textstrings[j].strings[i]); + } catch (NullPointerException ignored) { + // TextMap cache is outdated. + j--; // Retry the action. + Language.loadTextMaps(true); + } handbookBuilders.get(i).append(s + "\n"); } } diff --git a/src/main/java/emu/grasscutter/utils/Language.java b/src/main/java/emu/grasscutter/utils/Language.java index c823a50d3..42b44bb6b 100644 --- a/src/main/java/emu/grasscutter/utils/Language.java +++ b/src/main/java/emu/grasscutter/utils/Language.java @@ -314,38 +314,49 @@ public final class Language { return getTextMapKey((int) hash); } + /** + * Loads game text maps with caching. + */ public static void loadTextMaps() { - // Check system timestamps on cache and resources - try { - long cacheModified = Files.getLastModifiedTime(TEXTMAP_CACHE_PATH).toMillis(); + Language.loadTextMaps(false); + } + /** + * Loads game language data (text maps). + * + * @param bypassCache Should the cache be bypassed? + */ + public static void loadTextMaps(boolean bypassCache) { + // Check system timestamps on cache and resources + if (!bypassCache) try { + long cacheModified = Files.getLastModifiedTime(TEXTMAP_CACHE_PATH).toMillis(); long textmapsModified = - Files.list(getResourcePath("TextMap")) - .filter(path -> path.toString().endsWith(".json")) - .map( - path -> { - try { - return Files.getLastModifiedTime(path).toMillis(); - } catch (Exception ignored) { - Grasscutter.getLogger() - .debug("Exception while checking modified time: ", path); - return Long.MAX_VALUE; // Don't use cache, something has gone wrong - } - }) - .max(Long::compare) - .get(); + Files.list(getResourcePath("TextMap")) + .filter(path -> path.toString().endsWith(".json")) + .map( + path -> { + try { + return Files.getLastModifiedTime(path).toMillis(); + } catch (Exception ignored) { + Grasscutter.getLogger() + .debug("Exception while checking modified time: ", path); + return Long.MAX_VALUE; // Don't use cache, something has gone wrong + } + }) + .max(Long::compare) + .get(); Grasscutter.getLogger() - .debug( - "Cache modified %d, textmap modified %d".formatted(cacheModified, textmapsModified)); + .debug( + "Cache modified %d, textmap modified %d".formatted(cacheModified, textmapsModified)); if (textmapsModified < cacheModified) { // Try loading from cache Grasscutter.getLogger().debug("Loading cached 'TextMaps'..."); textMapStrings = loadTextMapsCache(); return; } - } catch (Exception e) { - Grasscutter.getLogger().debug("Exception while checking cache: ", e); + } catch (Exception exception) { + Grasscutter.getLogger().error("Error loading textmaps cache: " + exception.toString()); } // Regenerate cache