From 384b2047ac2c5d91bd7f3523e7936f1c1bf9fdba Mon Sep 17 00:00:00 2001 From: serega404 Date: Mon, 2 Nov 2020 16:30:14 +0300 Subject: [PATCH 01/10] Init crash reports --- .../client/ProgressiaClientMain.java | 12 ++ .../common/util/crash/Analyzer.java | 5 + .../common/util/crash/ContextProvider.java | 8 ++ .../util/crash/CrashReportGenerator.java | 134 ++++++++++++++++++ .../crash/analyzers/OutOfMemoryAnalyzer.java | 12 ++ .../crash/providers/OSContextProvider.java | 18 +++ src/main/resources/log4j2.xml | 4 - 7 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java create mode 100644 src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java diff --git a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java index c9e3f2c..369602e 100644 --- a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java +++ b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java @@ -20,6 +20,9 @@ package ru.windcorp.progressia.client; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ru.windcorp.progressia.ProgressiaLauncher; +import ru.windcorp.progressia.common.util.crash.CrashReportGenerator; +import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; +import ru.windcorp.progressia.common.util.crash.providers.OSContextProvider; public class ProgressiaClientMain { @@ -28,6 +31,15 @@ public class ProgressiaClientMain { public static void main(String[] args) { logger.info("App started!"); + CrashReportGenerator.registerProvider(new OSContextProvider()); + CrashReportGenerator.registerAnalyzer(new OutOfMemoryAnalyzer()); + try { + long[] ssdss = new long[1 << 30]; + } catch (Throwable t) + { + CrashReportGenerator.makeCrashReport(t, ""); + } + ProgressiaLauncher.launch(args, new ClientProxy()); } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java new file mode 100644 index 0000000..47b9e76 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java @@ -0,0 +1,5 @@ +package ru.windcorp.progressia.common.util.crash; + +public interface Analyzer { + String getPrompt(Throwable throwable, String messageFormat, Object... args); +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java new file mode 100644 index 0000000..ad0d5d3 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java @@ -0,0 +1,8 @@ +package ru.windcorp.progressia.common.util.crash; + +import java.util.Map; + +public interface ContextProvider { + + Map provideContext(); +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java new file mode 100644 index 0000000..4c808dd --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java @@ -0,0 +1,134 @@ +package ru.windcorp.progressia.common.util.crash; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +public class CrashReportGenerator { + + private CrashReportGenerator() { + } + + final static File latestLogFile = new File("crash-reports/latest.log"); + + private static Collection providers = new ArrayList(); + private static Collection> providerResponse = new ArrayList>(); + + private static Collection analyzers = new ArrayList(); + private static Collection analyzerResponse = new ArrayList(); + + private static final Logger logger = LogManager.getLogger("crash"); + + static public void makeCrashReport(Throwable throwable, String messageFormat, Object... args) { + + StringBuilder output = new StringBuilder(); + + for (ContextProvider currentProvider : providers) { + if (currentProvider != null) { + providerResponse.add(currentProvider.provideContext()); + } + } + + if (throwable != null) { + for (Analyzer currentAnalyzer : analyzers) { + if (currentAnalyzer != null) { + analyzerResponse.add(currentAnalyzer.getPrompt(throwable, messageFormat, args)); + } + } + } + + for (Map currentProviderResponse : providerResponse) { + if (currentProviderResponse != null && !currentProviderResponse.isEmpty()) { + addSeparator(output); + for (Map.Entry entry : currentProviderResponse.entrySet()) { + output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + } + } + } + + for (String currentPrompt : analyzerResponse) { + if (currentPrompt != null && !currentPrompt.isEmpty()) { + addSeparator(output); + output.append(currentPrompt).append("\n"); + } + } + + // Formatting to a human-readable string + StringWriter sink = new StringWriter(); + if (throwable != null) { + try { + throwable.printStackTrace(new PrintWriter(sink)); + } catch (Exception e) { + // PLAK + } + } else { + sink.append("Null"); + } + + logger.info("\n" + output.toString()); + logger.fatal("Stacktrace: \n" + sink.toString()); + + addSeparator(output); + + output.append("Stacktrace: \n"); + output.append(sink.toString()).append("\n"); + + try { + System.err.println(output.toString()); + } catch (Exception e) { + // PLAK + } + + + createFileForCrashReport(output); + createFileForLatestCrashReport(output); + + + System.exit(0); + } + + public static void createFileForCrashReport(StringBuilder sb) { + Date date = new Date(); + + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss"); + + File logFile = new File("crash-reports/" + "crash-" + dateFormat.format(date) + ".log"); + + try (FileOutputStream fos = new FileOutputStream(logFile)) { + byte[] buffer = sb.toString().getBytes(); + + fos.write(buffer, 0, buffer.length); + } catch (IOException ex) { + // Crash Report not created + } + } + + public static void createFileForLatestCrashReport(StringBuilder sb) { + try (FileOutputStream fos = new FileOutputStream(latestLogFile)) { + byte[] buffer = sb.toString().getBytes(); + + fos.write(buffer, 0, buffer.length); + } catch (IOException ex) { + // Crash Report not created + } + } + + public static void registerProvider(ContextProvider provider) { + providers.add(provider); + } + + public static void registerAnalyzer(Analyzer analyzer) { + analyzers.add(analyzer); + } + + private static void addSeparator(StringBuilder sb) { + sb.append("-------------------------------------------------").append("\n"); + } +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java new file mode 100644 index 0000000..e750cea --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java @@ -0,0 +1,12 @@ +package ru.windcorp.progressia.common.util.crash.analyzers; + +import ru.windcorp.progressia.common.util.crash.Analyzer; + +public class OutOfMemoryAnalyzer implements Analyzer { + @Override + public String getPrompt(Throwable throwable, String messageFormat, Object... args) { + if (throwable instanceof OutOfMemoryError) + return "Try add memory for the JVM"; + return null; + } +} diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java new file mode 100644 index 0000000..712ee17 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java @@ -0,0 +1,18 @@ +package ru.windcorp.progressia.common.util.crash.providers; + +import ru.windcorp.progressia.common.util.crash.ContextProvider; + +import java.util.HashMap; +import java.util.Map; + +public class OSContextProvider implements ContextProvider { + + @Override + public Map provideContext() { + Map theThings = new HashMap<>(); + theThings.put("Name OS", System.getProperty("os.name")); + theThings.put("Version OS", System.getProperty("os.version")); + theThings.put("Architecture OS", System.getProperty("os.arch")); + return theThings; + } +} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 29aaea2..c40552b 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -13,18 +13,14 @@ - - - - From e7e54d0ffdc664bed3067bf51a756e5d18c42ef4 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Mon, 2 Nov 2020 17:27:17 +0300 Subject: [PATCH 02/10] Code review --- .../client/ProgressiaClientMain.java | 3 +- .../common/util/crash/Analyzer.java | 2 +- .../common/util/crash/ContextProvider.java | 1 - .../util/crash/CrashReportGenerator.java | 55 +++++++++---------- .../crash/analyzers/OutOfMemoryAnalyzer.java | 2 +- .../crash/providers/OSContextProvider.java | 10 ++-- 6 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java index 369602e..84fa145 100644 --- a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java +++ b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java @@ -34,10 +34,11 @@ public class ProgressiaClientMain { CrashReportGenerator.registerProvider(new OSContextProvider()); CrashReportGenerator.registerAnalyzer(new OutOfMemoryAnalyzer()); try { + @SuppressWarnings("unused") long[] ssdss = new long[1 << 30]; } catch (Throwable t) { - CrashReportGenerator.makeCrashReport(t, ""); + CrashReportGenerator.makeCrashReport(t, "u %s stupid", "vry"); } ProgressiaLauncher.launch(args, new ClientProxy()); diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java index 47b9e76..0afdb1d 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java @@ -1,5 +1,5 @@ package ru.windcorp.progressia.common.util.crash; public interface Analyzer { - String getPrompt(Throwable throwable, String messageFormat, Object... args); + String analyze(Throwable throwable, String messageFormat, Object... args); } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java index ad0d5d3..06150f0 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java @@ -3,6 +3,5 @@ package ru.windcorp.progressia.common.util.crash; import java.util.Map; public interface ContextProvider { - Map provideContext(); } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java index 4c808dd..c51c125 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java @@ -13,50 +13,47 @@ import java.util.Map; public class CrashReportGenerator { - private CrashReportGenerator() { - } + private CrashReportGenerator() {} - final static File latestLogFile = new File("crash-reports/latest.log"); + private static final File LATEST_LOG_FILE = new File("crash-reports/latest.log"); - private static Collection providers = new ArrayList(); - private static Collection> providerResponse = new ArrayList>(); + private static final Collection PROVIDERS = new ArrayList<>(); + private static final Collection> PROVIDER_RESPONSES = new ArrayList<>(); - private static Collection analyzers = new ArrayList(); - private static Collection analyzerResponse = new ArrayList(); + private static final Collection ANALYZER = new ArrayList<>(); + private static final Collection ANALYZER_RESPONSES = new ArrayList<>(); - private static final Logger logger = LogManager.getLogger("crash"); + private static final Logger LOGGER = LogManager.getLogger("crash"); - static public void makeCrashReport(Throwable throwable, String messageFormat, Object... args) { + public static void makeCrashReport(Throwable throwable, String messageFormat, Object... args) { StringBuilder output = new StringBuilder(); - for (ContextProvider currentProvider : providers) { - if (currentProvider != null) { - providerResponse.add(currentProvider.provideContext()); + for (ContextProvider provider : PROVIDERS) { + if (provider != null) { + PROVIDER_RESPONSES.add(provider.provideContext()); } } - if (throwable != null) { - for (Analyzer currentAnalyzer : analyzers) { - if (currentAnalyzer != null) { - analyzerResponse.add(currentAnalyzer.getPrompt(throwable, messageFormat, args)); - } + for (Analyzer analyzer : ANALYZER) { + if (analyzer != null) { + ANALYZER_RESPONSES.add(analyzer.analyze(throwable, messageFormat, args)); } } - for (Map currentProviderResponse : providerResponse) { - if (currentProviderResponse != null && !currentProviderResponse.isEmpty()) { + for (Map response : PROVIDER_RESPONSES) { + if (response != null && !response.isEmpty()) { addSeparator(output); - for (Map.Entry entry : currentProviderResponse.entrySet()) { + for (Map.Entry entry : response.entrySet()) { output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); } } } - for (String currentPrompt : analyzerResponse) { - if (currentPrompt != null && !currentPrompt.isEmpty()) { + for (String response : ANALYZER_RESPONSES) { + if (response != null && !response.isEmpty()) { addSeparator(output); - output.append(currentPrompt).append("\n"); + output.append(response).append("\n"); } } @@ -72,8 +69,8 @@ public class CrashReportGenerator { sink.append("Null"); } - logger.info("\n" + output.toString()); - logger.fatal("Stacktrace: \n" + sink.toString()); + LOGGER.info(output.toString()); + LOGGER.fatal("Stacktrace: \n" + sink.toString()); addSeparator(output); @@ -86,11 +83,9 @@ public class CrashReportGenerator { // PLAK } - createFileForCrashReport(output); createFileForLatestCrashReport(output); - System.exit(0); } @@ -111,7 +106,7 @@ public class CrashReportGenerator { } public static void createFileForLatestCrashReport(StringBuilder sb) { - try (FileOutputStream fos = new FileOutputStream(latestLogFile)) { + try (FileOutputStream fos = new FileOutputStream(LATEST_LOG_FILE)) { byte[] buffer = sb.toString().getBytes(); fos.write(buffer, 0, buffer.length); @@ -121,11 +116,11 @@ public class CrashReportGenerator { } public static void registerProvider(ContextProvider provider) { - providers.add(provider); + PROVIDERS.add(provider); } public static void registerAnalyzer(Analyzer analyzer) { - analyzers.add(analyzer); + ANALYZER.add(analyzer); } private static void addSeparator(StringBuilder sb) { diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java index e750cea..d5fb6dc 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java @@ -4,7 +4,7 @@ import ru.windcorp.progressia.common.util.crash.Analyzer; public class OutOfMemoryAnalyzer implements Analyzer { @Override - public String getPrompt(Throwable throwable, String messageFormat, Object... args) { + public String analyze(Throwable throwable, String messageFormat, Object... args) { if (throwable instanceof OutOfMemoryError) return "Try add memory for the JVM"; return null; diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java index 712ee17..56b8916 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java @@ -9,10 +9,10 @@ public class OSContextProvider implements ContextProvider { @Override public Map provideContext() { - Map theThings = new HashMap<>(); - theThings.put("Name OS", System.getProperty("os.name")); - theThings.put("Version OS", System.getProperty("os.version")); - theThings.put("Architecture OS", System.getProperty("os.arch")); - return theThings; + Map result = new HashMap<>(); + result.put("Name OS", System.getProperty("os.name")); + result.put("Version OS", System.getProperty("os.version")); + result.put("Architecture OS", System.getProperty("os.arch")); + return result; } } From ddf48c058709023acc295061388c8397f40fcc4e Mon Sep 17 00:00:00 2001 From: serega404 Date: Wed, 4 Nov 2020 23:10:07 +0300 Subject: [PATCH 03/10] Crash-reports code update --- .../common/util/crash/Analyzer.java | 2 + .../common/util/crash/ContextProvider.java | 4 +- .../util/crash/CrashReportGenerator.java | 124 +++++++++++------- .../crash/analyzers/OutOfMemoryAnalyzer.java | 5 + .../crash/providers/OSContextProvider.java | 16 ++- 5 files changed, 95 insertions(+), 56 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java index 0afdb1d..e98814d 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java @@ -2,4 +2,6 @@ package ru.windcorp.progressia.common.util.crash; public interface Analyzer { String analyze(Throwable throwable, String messageFormat, Object... args); + + String getName(); } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java index 06150f0..a1077e8 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java @@ -3,5 +3,7 @@ package ru.windcorp.progressia.common.util.crash; import java.util.Map; public interface ContextProvider { - Map provideContext(); + void provideContext(Map output); + + String getName(); } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java index c51c125..7720efc 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java @@ -3,25 +3,28 @@ package ru.windcorp.progressia.common.util.crash; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.*; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Map; +import java.util.*; public class CrashReportGenerator { - private CrashReportGenerator() {} + private CrashReportGenerator() { + } - private static final File LATEST_LOG_FILE = new File("crash-reports/latest.log"); + private static final Path CRASH_REPORTS_PATH = Paths.get("crash-reports"); private static final Collection PROVIDERS = new ArrayList<>(); - private static final Collection> PROVIDER_RESPONSES = new ArrayList<>(); - private static final Collection ANALYZER = new ArrayList<>(); - private static final Collection ANALYZER_RESPONSES = new ArrayList<>(); + private static final Collection ANALYZERS = new ArrayList<>(); private static final Logger LOGGER = LogManager.getLogger("crash"); @@ -31,32 +34,56 @@ public class CrashReportGenerator { for (ContextProvider provider : PROVIDERS) { if (provider != null) { - PROVIDER_RESPONSES.add(provider.provideContext()); - } - } + Map buf = new HashMap<>(); - for (Analyzer analyzer : ANALYZER) { - if (analyzer != null) { - ANALYZER_RESPONSES.add(analyzer.analyze(throwable, messageFormat, args)); - } - } + try { + provider.provideContext(buf); - for (Map response : PROVIDER_RESPONSES) { - if (response != null && !response.isEmpty()) { - addSeparator(output); - for (Map.Entry entry : response.entrySet()) { - output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + addSeparator(output); + output.append("Provider name: ").append(provider.getName()).append("\n"); + for (Map.Entry entry : buf.entrySet()) { + output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + } + } catch (Throwable t) { + try { + addSeparator(output); + output.append(provider.getName()).append(" is broken").append("\n"); + } catch (Throwable th) { + // You stupid + } + // Analyzer is broken } } } - for (String response : ANALYZER_RESPONSES) { - if (response != null && !response.isEmpty()) { - addSeparator(output); - output.append(response).append("\n"); + addSeparator(output); + + boolean analyzerResponseExist = false; + for (Analyzer analyzer : ANALYZERS) { + if (analyzer != null) { + + String answer; + try { + answer = analyzer.analyze(throwable, messageFormat, args); + + if (answer != null && !answer.isEmpty()) { + analyzerResponseExist = true; + output.append(analyzer.getName()).append(": ").append(answer).append("\n"); + } + } catch (Throwable t) { + try { + analyzerResponseExist = true; + output.append(analyzer.getName()).append(" is broken").append("\n"); + } catch (Throwable th) { + // You stupid + } + // Analyzer is broken + } } } + if (analyzerResponseExist) addSeparator(output); + // Formatting to a human-readable string StringWriter sink = new StringWriter(); if (throwable != null) { @@ -69,47 +96,48 @@ public class CrashReportGenerator { sink.append("Null"); } - LOGGER.info(output.toString()); - LOGGER.fatal("Stacktrace: \n" + sink.toString()); - - addSeparator(output); - output.append("Stacktrace: \n"); output.append(sink.toString()).append("\n"); + LOGGER.fatal("/n" + output.toString()); + try { System.err.println(output.toString()); } catch (Exception e) { // PLAK } - createFileForCrashReport(output); - createFileForLatestCrashReport(output); + generateCrashReportFiles(output.toString()); System.exit(0); } - public static void createFileForCrashReport(StringBuilder sb) { + public static void generateCrashReportFiles(String output) { Date date = new Date(); - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss"); - File logFile = new File("crash-reports/" + "crash-" + dateFormat.format(date) + ".log"); + boolean pathExist = false; + if (!Files.exists(CRASH_REPORTS_PATH)) { - try (FileOutputStream fos = new FileOutputStream(logFile)) { - byte[] buffer = sb.toString().getBytes(); + try { + Files.createDirectory(CRASH_REPORTS_PATH); + ; + pathExist = true; + } catch (IOException e) { + // Crash Report not created + } - fos.write(buffer, 0, buffer.length); - } catch (IOException ex) { - // Crash Report not created + } else pathExist = true; + + if (pathExist) { + createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/latest.log"); + createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/crash-" + dateFormat.format(date) + ".log"); } } - public static void createFileForLatestCrashReport(StringBuilder sb) { - try (FileOutputStream fos = new FileOutputStream(LATEST_LOG_FILE)) { - byte[] buffer = sb.toString().getBytes(); - - fos.write(buffer, 0, buffer.length); + public static void createFileForCrashReport(String buffer, String filename) { + try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8)) { + writer.write(buffer); } catch (IOException ex) { // Crash Report not created } @@ -120,7 +148,7 @@ public class CrashReportGenerator { } public static void registerAnalyzer(Analyzer analyzer) { - ANALYZER.add(analyzer); + ANALYZERS.add(analyzer); } private static void addSeparator(StringBuilder sb) { diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java index d5fb6dc..85a41e4 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java @@ -9,4 +9,9 @@ public class OutOfMemoryAnalyzer implements Analyzer { return "Try add memory for the JVM"; return null; } + + @Override + public String getName() { + return this.getClass().getSimpleName(); + } } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java index 56b8916..ecfe6ab 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java @@ -2,17 +2,19 @@ package ru.windcorp.progressia.common.util.crash.providers; import ru.windcorp.progressia.common.util.crash.ContextProvider; -import java.util.HashMap; import java.util.Map; public class OSContextProvider implements ContextProvider { @Override - public Map provideContext() { - Map result = new HashMap<>(); - result.put("Name OS", System.getProperty("os.name")); - result.put("Version OS", System.getProperty("os.version")); - result.put("Architecture OS", System.getProperty("os.arch")); - return result; + public void provideContext(Map output) { + output.put("Name OS", System.getProperty("os.name")); + output.put("Version OS", System.getProperty("os.version")); + output.put("Architecture OS", System.getProperty("os.arch")); + } + + @Override + public String getName() { + return this.getClass().getSimpleName(); } } From 044c690d096c944a0807f97a2c7ed6deb1bddb88 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Thu, 5 Nov 2020 12:14:03 +0300 Subject: [PATCH 04/10] Code Review - Renamed CrashReportGenerator.makeCrashReport to .crash for convenience - Split .crash into subroutines - Documented Analyzer and ContextProvider - Both are now supposed to have names In Title Case - CRG.export now assumes PrintStream does not fail and assumes Log can fail --- .../client/ProgressiaClientMain.java | 2 +- .../common/util/crash/Analyzer.java | 25 ++++ .../common/util/crash/ContextProvider.java | 22 ++++ .../util/crash/CrashReportGenerator.java | 117 ++++++++++++------ .../crash/analyzers/OutOfMemoryAnalyzer.java | 4 +- .../crash/providers/OSContextProvider.java | 8 +- 6 files changed, 130 insertions(+), 48 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java index 84fa145..bc79991 100644 --- a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java +++ b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java @@ -38,7 +38,7 @@ public class ProgressiaClientMain { long[] ssdss = new long[1 << 30]; } catch (Throwable t) { - CrashReportGenerator.makeCrashReport(t, "u %s stupid", "vry"); + CrashReportGenerator.crash(t, "u %s stupid", "vry"); } ProgressiaLauncher.launch(args, new ClientProxy()); diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java index e98814d..df9bdcd 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/Analyzer.java @@ -1,7 +1,32 @@ package ru.windcorp.progressia.common.util.crash; +/** + * A crash report utility that performs analysis of a problem during crash + * report generation and presents its conclusion to the user via the crash report. + * Unlike {@link ContextProvider}s, Analyzers are provided with the reported problem + * details. + * @see ContextProvider + * @author serega404 + */ public interface Analyzer { + + /** + * Provides a human-readable string describing this analyzer's conclusion + * on the presented problem, or returns {@code null} if no conclusion + * could be made. + * @param throwable The reported throwable (may be {@code null}) + * @param messageFormat A {@linkplain java.util.Formatter#syntax format string} of a + * human-readable description of the problem + * @param args The arguments for the format string + * @return a conclusion or {@code null} + */ String analyze(Throwable throwable, String messageFormat, Object... args); + /** + * Returns this analyzer's human-readable name. + * It should be A String In Title Case With Spaces. + * @return this analyzer's name + */ String getName(); + } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java index a1077e8..7938c2a 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/ContextProvider.java @@ -2,8 +2,30 @@ package ru.windcorp.progressia.common.util.crash; import java.util.Map; +/** + * A crash report utility that gathers information about game and system state + * when a crash occurs and presents it to the user via the crash report. + * ContextProviders are not aware of the nature of the problem, unlike {@link Analyzer}s. + * @see Analyzer + * @author serega404 + */ public interface ContextProvider { + + /** + * Provides human-readable description of the state of the game and the system. + * This information is {@link Map#put(Object, Object) put} into the provided map + * as key-value pairs. Keys are the characteristic being described, such as "OS Name", + * and should be Strings In Title Case With Spaces. + * If this provider cannot provide any information at this moment, the map is not + * modified. + * @param output the map to append output to + */ void provideContext(Map output); + /** + * Returns this provider's human-readable name. + * It should be A String In Title Case With Spaces. + * @return this provider's name + */ String getName(); } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java index 7720efc..ca5311f 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java @@ -2,11 +2,12 @@ package ru.windcorp.progressia.common.util.crash; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.util.StringBuilderWriter; import java.io.BufferedWriter; import java.io.IOException; import java.io.PrintWriter; -import java.io.StringWriter; +import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -17,21 +18,43 @@ import java.util.*; public class CrashReportGenerator { - private CrashReportGenerator() { - } + private CrashReportGenerator() {} private static final Path CRASH_REPORTS_PATH = Paths.get("crash-reports"); - private static final Collection PROVIDERS = new ArrayList<>(); + private static final Collection PROVIDERS = + Collections.synchronizedCollection(new ArrayList<>()); - private static final Collection ANALYZERS = new ArrayList<>(); + private static final Collection ANALYZERS = + Collections.synchronizedCollection(new ArrayList<>()); private static final Logger LOGGER = LogManager.getLogger("crash"); - public static void makeCrashReport(Throwable throwable, String messageFormat, Object... args) { - + /** + * This method never returns. + *

+ * TODO document + * @param throwable + * @param messageFormat + * @param args + */ + public static void crash(Throwable throwable, String messageFormat, Object... args) { StringBuilder output = new StringBuilder(); + appendContextProviders(output); + addSeparator(output); + if (appendAnalyzers(output, throwable, messageFormat, args)) { + addSeparator(output); + } + + appendStackTrace(output, throwable); + + export(output.toString()); + + System.exit(0); + } + + private static void appendContextProviders(StringBuilder output) { for (ContextProvider provider : PROVIDERS) { if (provider != null) { Map buf = new HashMap<>(); @@ -55,10 +78,13 @@ public class CrashReportGenerator { } } } - - addSeparator(output); - - boolean analyzerResponseExist = false; + } + + private static boolean appendAnalyzers( + StringBuilder output, + Throwable throwable, String messageFormat, Object[] args + ) { + boolean analyzerResponsesExist = false; for (Analyzer analyzer : ANALYZERS) { if (analyzer != null) { @@ -67,12 +93,12 @@ public class CrashReportGenerator { answer = analyzer.analyze(throwable, messageFormat, args); if (answer != null && !answer.isEmpty()) { - analyzerResponseExist = true; + analyzerResponsesExist = true; output.append(analyzer.getName()).append(": ").append(answer).append("\n"); } } catch (Throwable t) { try { - analyzerResponseExist = true; + analyzerResponsesExist = true; output.append(analyzer.getName()).append(" is broken").append("\n"); } catch (Throwable th) { // You stupid @@ -81,38 +107,40 @@ public class CrashReportGenerator { } } } + + return analyzerResponsesExist; + } - if (analyzerResponseExist) addSeparator(output); - - // Formatting to a human-readable string - StringWriter sink = new StringWriter(); - if (throwable != null) { - try { - throwable.printStackTrace(new PrintWriter(sink)); - } catch (Exception e) { - // PLAK - } - } else { - sink.append("Null"); - } - + private static void appendStackTrace(StringBuilder output, Throwable throwable) { output.append("Stacktrace: \n"); - output.append(sink.toString()).append("\n"); - - LOGGER.fatal("/n" + output.toString()); - + + if (throwable == null) { + output.append("no Throwable provided").append("\n"); + } + + // Formatting to a human-readable string + Writer sink = new StringBuilderWriter(output); try { - System.err.println(output.toString()); + throwable.printStackTrace(new PrintWriter(sink)); } catch (Exception e) { // PLAK } - - generateCrashReportFiles(output.toString()); - - System.exit(0); + output.append("\n"); + } + + private static void export(String report) { + try { + LOGGER.fatal("/n" + report); + } catch (Exception e) { + // PLAK + } + + System.err.println(report); + + generateCrashReportFiles(report); } - public static void generateCrashReportFiles(String output) { + private static void generateCrashReportFiles(String output) { Date date = new Date(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss"); @@ -121,7 +149,6 @@ public class CrashReportGenerator { try { Files.createDirectory(CRASH_REPORTS_PATH); - ; pathExist = true; } catch (IOException e) { // Crash Report not created @@ -135,8 +162,13 @@ public class CrashReportGenerator { } } - public static void createFileForCrashReport(String buffer, String filename) { - try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8)) { + private static void createFileForCrashReport(String buffer, String filename) { + try ( + BufferedWriter writer = Files.newBufferedWriter( + Paths.get(filename), + StandardCharsets.UTF_8 + ) + ) { writer.write(buffer); } catch (IOException ex) { // Crash Report not created @@ -152,6 +184,9 @@ public class CrashReportGenerator { } private static void addSeparator(StringBuilder sb) { - sb.append("-------------------------------------------------").append("\n"); + sb.append( + // 80 chars + "--------------------------------------------------------------------------------" + ).append("\n"); } } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java index 85a41e4..95d5f76 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/analyzers/OutOfMemoryAnalyzer.java @@ -6,12 +6,12 @@ public class OutOfMemoryAnalyzer implements Analyzer { @Override public String analyze(Throwable throwable, String messageFormat, Object... args) { if (throwable instanceof OutOfMemoryError) - return "Try add memory for the JVM"; + return "Try to add memory to the JVM"; return null; } @Override public String getName() { - return this.getClass().getSimpleName(); + return "Out Of Memory Analyzer"; } } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java index ecfe6ab..f8d4ab4 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/OSContextProvider.java @@ -8,13 +8,13 @@ public class OSContextProvider implements ContextProvider { @Override public void provideContext(Map output) { - output.put("Name OS", System.getProperty("os.name")); - output.put("Version OS", System.getProperty("os.version")); - output.put("Architecture OS", System.getProperty("os.arch")); + output.put("OS Name", System.getProperty("os.name")); + output.put("OS Version", System.getProperty("os.version")); + output.put("OS Architecture", System.getProperty("os.arch")); } @Override public String getName() { - return this.getClass().getSimpleName(); + return "OS Context Provider"; } } From d5723b9ae6badf4b51e4293349cd01f0ae5ebe1c Mon Sep 17 00:00:00 2001 From: serega404 Date: Sat, 7 Nov 2020 21:52:09 +0300 Subject: [PATCH 05/10] Refactored crash-report --- .../util/crash/CrashReportGenerator.java | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java index ca5311f..0109bdd 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java @@ -46,9 +46,11 @@ public class CrashReportGenerator { if (appendAnalyzers(output, throwable, messageFormat, args)) { addSeparator(output); } - + + appendMessageFormat(output, messageFormat, args); + appendStackTrace(output, throwable); - + export(output.toString()); System.exit(0); @@ -62,16 +64,19 @@ public class CrashReportGenerator { try { provider.provideContext(buf); - addSeparator(output); - output.append("Provider name: ").append(provider.getName()).append("\n"); - for (Map.Entry entry : buf.entrySet()) { - output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + if (!buf.isEmpty()) { + addSeparator(output); + output.append("Provider name: ").append(provider.getName()).append("\n"); + for (Map.Entry entry : buf.entrySet()) { + output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + } } } catch (Throwable t) { + output.append("\n"); try { - addSeparator(output); output.append(provider.getName()).append(" is broken").append("\n"); } catch (Throwable th) { + output.append(provider.getClass().getName()).append(" is broken").append("\n"); // You stupid } // Analyzer is broken @@ -107,17 +112,24 @@ public class CrashReportGenerator { } } } - + return analyzerResponsesExist; } + private static void appendMessageFormat(StringBuilder output, String messageFormat, Object... arg) { + output.append("Provided description: ").append(String.format(messageFormat, arg)).append("\n"); + + addSeparator(output); + } + private static void appendStackTrace(StringBuilder output, Throwable throwable) { output.append("Stacktrace: \n"); - + if (throwable == null) { output.append("no Throwable provided").append("\n"); + return; } - + // Formatting to a human-readable string Writer sink = new StringBuilderWriter(output); try { @@ -127,16 +139,16 @@ public class CrashReportGenerator { } output.append("\n"); } - + private static void export(String report) { try { LOGGER.fatal("/n" + report); } catch (Exception e) { // PLAK } - + System.err.println(report); - + generateCrashReportFiles(report); } @@ -144,21 +156,13 @@ public class CrashReportGenerator { Date date = new Date(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss"); - boolean pathExist = false; - if (!Files.exists(CRASH_REPORTS_PATH)) { + try { + if (!Files.exists(CRASH_REPORTS_PATH)) Files.createDirectory(CRASH_REPORTS_PATH); - try { - Files.createDirectory(CRASH_REPORTS_PATH); - pathExist = true; - } catch (IOException e) { - // Crash Report not created - } - - } else pathExist = true; - - if (pathExist) { createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/latest.log"); createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/crash-" + dateFormat.format(date) + ".log"); + } catch (Throwable t) { + // Crash Report not created } } From 0017ecc5a74297204938d8adfc1e3d65b6088616 Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Tue, 10 Nov 2020 01:25:42 +0300 Subject: [PATCH 06/10] Refactored CrashReportGenerator to avoid deadlocks and clarify code --- .../util/crash/CrashReportGenerator.java | 96 +++++++++++-------- 1 file changed, 58 insertions(+), 38 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java index 0109bdd..18bacba 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java @@ -57,30 +57,39 @@ public class CrashReportGenerator { } private static void appendContextProviders(StringBuilder output) { - for (ContextProvider provider : PROVIDERS) { - if (provider != null) { + + // Do a local copy to avoid deadlocks -OLEGSHA + ContextProvider[] localProvidersCopy = + PROVIDERS.toArray(new ContextProvider[PROVIDERS.size()]); + + for (ContextProvider provider : localProvidersCopy) { + if (provider == null) continue; + + addSeparator(output); + + try { Map buf = new HashMap<>(); + provider.provideContext(buf); - try { - provider.provideContext(buf); - - if (!buf.isEmpty()) { - addSeparator(output); - output.append("Provider name: ").append(provider.getName()).append("\n"); - for (Map.Entry entry : buf.entrySet()) { - output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); - } + if (!buf.isEmpty()) { + output.append("Provider name: ").append(provider.getName()).append("\n"); + for (Map.Entry entry : buf.entrySet()) { + output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); } - } catch (Throwable t) { - output.append("\n"); - try { - output.append(provider.getName()).append(" is broken").append("\n"); - } catch (Throwable th) { - output.append(provider.getClass().getName()).append(" is broken").append("\n"); - // You stupid - } - // Analyzer is broken } + } catch (Throwable t) { + output.append("\n"); + + String providerName; + + try { + providerName = provider.getName(); + } catch (Throwable t1) { + providerName = provider.getClass().getName(); + } + + output.append(providerName).append(" is broken").append("\n"); + // ContextProvider is broken } } } @@ -90,26 +99,37 @@ public class CrashReportGenerator { Throwable throwable, String messageFormat, Object[] args ) { boolean analyzerResponsesExist = false; - for (Analyzer analyzer : ANALYZERS) { - if (analyzer != null) { + + // Do a local copy to avoid deadlocks -OLEGSHA + Analyzer[] localAnalyzersCopy = + ANALYZERS.toArray(new Analyzer[ANALYZERS.size()]); + + for (Analyzer analyzer : localAnalyzersCopy) { + if (analyzer == null) continue; - String answer; - try { - answer = analyzer.analyze(throwable, messageFormat, args); + String answer; + try { + answer = analyzer.analyze(throwable, messageFormat, args); - if (answer != null && !answer.isEmpty()) { - analyzerResponsesExist = true; - output.append(analyzer.getName()).append(": ").append(answer).append("\n"); - } - } catch (Throwable t) { - try { - analyzerResponsesExist = true; - output.append(analyzer.getName()).append(" is broken").append("\n"); - } catch (Throwable th) { - // You stupid - } - // Analyzer is broken + if (answer != null && !answer.isEmpty()) { + analyzerResponsesExist = true; + output.append(analyzer.getName()).append(": ").append(answer).append("\n"); } + } catch (Throwable t) { + analyzerResponsesExist = true; + + output.append("\n"); + + String analyzerName; + + try { + analyzerName = analyzer.getName(); + } catch (Throwable t1) { + analyzerName = analyzer.getClass().getName(); + } + + output.append(analyzerName).append(" is broken").append("\n"); + // Analyzer is broken } } @@ -117,7 +137,7 @@ public class CrashReportGenerator { } private static void appendMessageFormat(StringBuilder output, String messageFormat, Object... arg) { - output.append("Provided description: ").append(String.format(messageFormat, arg)).append("\n"); + output.append("Provided description: \n").append(String.format(messageFormat, arg)).append("\n"); addSeparator(output); } From c1194b7601867e921db22da8408456e66e067a21 Mon Sep 17 00:00:00 2001 From: serega404 Date: Sat, 14 Nov 2020 20:38:49 +0300 Subject: [PATCH 07/10] Introduced crash reports --- .../java/ru/windcorp/jputil/ArrayUtil.java | 134 +++--- .../progressia/client/ClientProxy.java | 4 +- .../client/ProgressiaClientMain.java | 15 +- .../comms/DefaultClientCommsListener.java | 9 +- .../graphics/backend/shaders/Program.java | 21 +- .../graphics/backend/shaders/Shader.java | 40 +- .../backend/shaders/attributes/Attribute.java | 15 +- .../backend/shaders/uniforms/Uniform.java | 35 +- .../graphics/font/GNUUnifontLoader.java | 139 +++--- .../client/graphics/gui/Component.java | 361 ++++++++------- .../client/graphics/input/Keys.java | 101 ++--- .../client/graphics/texture/Atlases.java | 122 +++-- .../graphics/texture/SimpleTextures.java | 16 +- .../graphics/texture/TexturePrimitive.java | 25 +- .../client/localization/Localizer.java | 8 +- .../client/localization/Parser.java | 6 +- .../world/entity/EntityRenderRegistry.java | 8 +- .../progressia/common/resource/Resource.java | 25 +- ...ReportGenerator.java => CrashReports.java} | 428 +++++++++--------- .../world/entity/PacketEntityChange.java | 21 +- .../world/ImplementedChangeTracker.java | 74 +-- 21 files changed, 789 insertions(+), 818 deletions(-) rename src/main/java/ru/windcorp/progressia/common/util/crash/{CrashReportGenerator.java => CrashReports.java} (76%) diff --git a/src/main/java/ru/windcorp/jputil/ArrayUtil.java b/src/main/java/ru/windcorp/jputil/ArrayUtil.java index 4c849b7..04de6c4 100644 --- a/src/main/java/ru/windcorp/jputil/ArrayUtil.java +++ b/src/main/java/ru/windcorp/jputil/ArrayUtil.java @@ -33,7 +33,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(byte[] array, byte element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -42,7 +42,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(byte[] array, byte element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -52,7 +52,7 @@ public class ArrayUtil { } return result; } - + public static int hasDuplicates(byte[] array) { for (int i = 0; i < array.length; ++i) { byte a = array[i]; @@ -62,10 +62,10 @@ public class ArrayUtil { } } } - + return -1; } - + public static int firstIndexOf(short[] array, short element) { for (int i = 0; i < array.length; ++i) { if (array[i] == element) { @@ -74,7 +74,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(short[] array, short element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -83,7 +83,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(short[] array, short element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -93,7 +93,7 @@ public class ArrayUtil { } return result; } - + public static int hasDuplicates(short[] array) { for (int i = 0; i < array.length; ++i) { short a = array[i]; @@ -103,10 +103,10 @@ public class ArrayUtil { } } } - + return -1; } - + public static int firstIndexOf(int[] array, int element) { for (int i = 0; i < array.length; ++i) { if (array[i] == element) { @@ -115,7 +115,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(int[] array, int element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -124,7 +124,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(int[] array, int element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -134,7 +134,7 @@ public class ArrayUtil { } return result; } - + public static int hasDuplicates(int[] array) { for (int i = 0; i < array.length; ++i) { int a = array[i]; @@ -144,10 +144,10 @@ public class ArrayUtil { } } } - + return -1; } - + public static int firstIndexOf(long[] array, long element) { for (int i = 0; i < array.length; ++i) { if (array[i] == element) { @@ -156,7 +156,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(long[] array, long element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -165,7 +165,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(long[] array, long element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -175,7 +175,7 @@ public class ArrayUtil { } return result; } - + public static int hasDuplicates(long[] array) { for (int i = 0; i < array.length; ++i) { long a = array[i]; @@ -185,10 +185,10 @@ public class ArrayUtil { } } } - + return -1; } - + public static int firstIndexOf(float[] array, float element) { for (int i = 0; i < array.length; ++i) { if (array[i] == element) { @@ -197,7 +197,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(float[] array, float element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -206,7 +206,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(float[] array, float element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -216,7 +216,7 @@ public class ArrayUtil { } return result; } - + public static int hasDuplicates(float[] array) { for (int i = 0; i < array.length; ++i) { float a = array[i]; @@ -226,7 +226,7 @@ public class ArrayUtil { } } } - + return -1; } @@ -238,7 +238,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(double[] array, double element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -247,7 +247,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(double[] array, double element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -257,7 +257,7 @@ public class ArrayUtil { } return result; } - + public static int hasDuplicates(double[] array) { for (int i = 0; i < array.length; ++i) { double a = array[i]; @@ -267,10 +267,10 @@ public class ArrayUtil { } } } - + return -1; } - + public static int firstIndexOf(boolean[] array, boolean element) { for (int i = 0; i < array.length; ++i) { if (array[i] == element) { @@ -279,7 +279,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(boolean[] array, boolean element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -288,7 +288,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(boolean[] array, boolean element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -298,7 +298,7 @@ public class ArrayUtil { } return result; } - + public static int firstIndexOf(char[] array, char element) { for (int i = 0; i < array.length; ++i) { if (array[i] == element) { @@ -307,7 +307,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(char[] array, char element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -316,7 +316,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(char[] array, char element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -326,7 +326,7 @@ public class ArrayUtil { } return result; } - + public static int hasDuplicates(char[] array) { for (int i = 0; i < array.length; ++i) { char a = array[i]; @@ -336,10 +336,10 @@ public class ArrayUtil { } } } - + return -1; } - + public static int firstIndexOf(Object[] array, Object element) { for (int i = 0; i < array.length; ++i) { if (array[i] == element) { @@ -348,7 +348,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOf(Object[] array, Object element) { for (int i = array.length - 1; i >= 0; --i) { if (array[i] == element) { @@ -357,7 +357,7 @@ public class ArrayUtil { } return -1; } - + public static int occurences(Object[] array, Object element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -367,7 +367,7 @@ public class ArrayUtil { } return result; } - + public static int hasDuplicates(Object[] array) { for (int i = 0; i < array.length; ++i) { Object a = array[i]; @@ -377,10 +377,10 @@ public class ArrayUtil { } } } - + return -1; } - + public static int firstIndexOfEqual(Object[] array, Object element) { for (int i = 0; i < array.length; ++i) { if (Objects.equals(array[i], element)) { @@ -389,7 +389,7 @@ public class ArrayUtil { } return -1; } - + public static int lastIndexOfEqual(Object[] array, Object element) { for (int i = array.length - 1; i >= 0; --i) { if (Objects.equals(array[i], element)) { @@ -398,7 +398,7 @@ public class ArrayUtil { } return -1; } - + public static int occurencesOfEqual(Object[] array, Object element) { int result = 0; for (int i = 0; i < array.length; ++i) { @@ -408,7 +408,7 @@ public class ArrayUtil { } return result; } - + public static int hasEquals(Object[] array) { for (int i = 0; i < array.length; ++i) { Object a = array[i]; @@ -418,10 +418,10 @@ public class ArrayUtil { } } } - + return -1; } - + public static long sum(byte[] array, int start, int length) { long s = 0; length += start; @@ -430,7 +430,7 @@ public class ArrayUtil { } return s; } - + public static long sum(short[] array, int start, int length) { long s = 0; length += start; @@ -439,7 +439,7 @@ public class ArrayUtil { } return s; } - + public static long sum(int[] array, int start, int length) { long s = 0; length += start; @@ -448,7 +448,7 @@ public class ArrayUtil { } return s; } - + public static long sum(long[] array, int start, int length) { long s = 0; length += start; @@ -457,7 +457,7 @@ public class ArrayUtil { } return s; } - + public static BigInteger longSum(long[] array, int start, int length) { BigInteger s = BigInteger.ZERO; length += start; @@ -466,7 +466,7 @@ public class ArrayUtil { } return s; } - + public static float sum(float[] array, int start, int length) { float s = 0; length += start; @@ -475,7 +475,7 @@ public class ArrayUtil { } return s; } - + public static double sum(double[] array, int start, int length) { double s = 0; length += start; @@ -484,7 +484,7 @@ public class ArrayUtil { } return s; } - + public static long sum(char[] array, int start, int length) { long s = 0; length += start; @@ -493,33 +493,35 @@ public class ArrayUtil { } return s; } - + public static int checkArrayOffsetLength(Object array, int offset, int length) { int arrayLength = Array.getLength(array); - + if (length < 0) length = arrayLength; - + int end = offset + length; if (end > arrayLength || offset < 0) - throw new IllegalArgumentException("Array contains [0; " + arrayLength + "), requested [" + offset + "; " + end + ")"); - + throw new IllegalArgumentException( + "Array contains [0; " + arrayLength + "), requested [" + offset + "; " + end + ")"); + return length; } - + public static int checkArrayStartEnd(Object array, int start, int end) { int arrayLength = Array.getLength(array); - + if (end < 0) end = arrayLength; - + if (start > end) throw new IllegalArgumentException("Start > end: " + start + " > " + end); - + if (end > arrayLength || start < 0) - throw new IllegalArgumentException("Array contains [0; " + arrayLength + "), requested [" + start + "; " + end + ")"); - + throw new IllegalArgumentException( + "Array contains [0; " + arrayLength + "), requested [" + start + "; " + end + ")"); + return end; } - + } diff --git a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java index 9690642..921fce5 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java @@ -26,6 +26,7 @@ import ru.windcorp.progressia.client.graphics.font.Typefaces; import ru.windcorp.progressia.client.graphics.texture.Atlases; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.common.resource.ResourceManager; +import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.test.TestContent; @@ -39,8 +40,7 @@ public class ClientProxy implements Proxy { RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init); RenderTaskQueue.waitAndInvoke(() -> Typefaces.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz")))); } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + CrashReports.report(e, "ClientProxy failed"); } TestContent.registerContent(); diff --git a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java index bc79991..0b755f0 100644 --- a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java +++ b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java @@ -20,7 +20,7 @@ package ru.windcorp.progressia.client; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ru.windcorp.progressia.ProgressiaLauncher; -import ru.windcorp.progressia.common.util.crash.CrashReportGenerator; +import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; import ru.windcorp.progressia.common.util.crash.providers.OSContextProvider; @@ -31,17 +31,16 @@ public class ProgressiaClientMain { public static void main(String[] args) { logger.info("App started!"); - CrashReportGenerator.registerProvider(new OSContextProvider()); - CrashReportGenerator.registerAnalyzer(new OutOfMemoryAnalyzer()); + CrashReports.registerProvider(new OSContextProvider()); + CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer()); try { @SuppressWarnings("unused") long[] ssdss = new long[1 << 30]; - } catch (Throwable t) - { - CrashReportGenerator.crash(t, "u %s stupid", "vry"); + } catch (Throwable t) { + CrashReports.report(t, "u %s stupid", "vry"); } ProgressiaLauncher.launch(args, new ClientProxy()); } - -} + +} \ No newline at end of file diff --git a/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java b/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java index 4292bb9..b2c7051 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java @@ -8,12 +8,13 @@ import ru.windcorp.progressia.common.comms.CommsListener; import ru.windcorp.progressia.common.comms.packets.Packet; import ru.windcorp.progressia.common.comms.packets.PacketSetLocalPlayer; import ru.windcorp.progressia.common.comms.packets.PacketWorldChange; +import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.PacketEntityChange; // TODO refactor with no mercy public class DefaultClientCommsListener implements CommsListener { - + private final Client client; public DefaultClientCommsListener(Client client) { @@ -41,9 +42,9 @@ public class DefaultClientCommsListener implements CommsListener { ); if (entity == null) { - throw new RuntimeException(""); + CrashReports.report(null, "Player entity not found"); } - + getClient().setLocalPlayer(entity); getClient().getCamera().setAnchor(new EntityAnchor( getClient().getWorld().getEntityRenderable(entity) @@ -58,7 +59,7 @@ public class DefaultClientCommsListener implements CommsListener { public void onIOError(IOException reason) { // TODO implement } - + public Client getClient() { return client; } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java index 6aee18d..64c54bc 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java @@ -24,37 +24,38 @@ import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker; import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable; import ru.windcorp.progressia.client.graphics.backend.shaders.attributes.Attribute; import ru.windcorp.progressia.client.graphics.backend.shaders.uniforms.Uniform; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class Program implements OpenGLDeletable { - + private int handle; - + public Program(Shader vertexShader, Shader fragmentShader) { handle = glCreateProgram(); OpenGLObjectTracker.register(this); - + glAttachShader(handle, vertexShader.getHandle()); glAttachShader(handle, fragmentShader.getHandle()); - + glLinkProgram(handle); - + if (glGetProgrami(handle, GL_LINK_STATUS) == GL_FALSE) { - throw new RuntimeException("Bad program:\n" + glGetProgramInfoLog(handle)); + CrashReports.report(null, "Bad program:\n %s", glGetProgramInfoLog(handle)); } } - + public Attribute getAttribute(String name) { return new Attribute(glGetAttribLocation(handle, name), this); } - + public Uniform getUniform(String name) { return new Uniform(glGetUniformLocation(handle, name), this); } - + public void use() { glUseProgram(handle); } - + @Override public void delete() { glDeleteProgram(handle); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Shader.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Shader.java index 7dfef92..27567e7 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Shader.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Shader.java @@ -26,26 +26,26 @@ import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker; import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable; import ru.windcorp.progressia.common.resource.Resource; import ru.windcorp.progressia.common.resource.ResourceManager; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class Shader implements OpenGLDeletable { - + public static enum ShaderType { - VERTEX(GL_VERTEX_SHADER), - FRAGMENT(GL_FRAGMENT_SHADER); - + VERTEX(GL_VERTEX_SHADER), FRAGMENT(GL_FRAGMENT_SHADER); + private final int glCode; - + private ShaderType(int glCode) { this.glCode = glCode; } - + public int getGlCode() { return glCode; } - + public static ShaderType guessByResourceName(String resource) { resource = resource.toLowerCase(Locale.ENGLISH); - + if (resource.contains("vertex")) return VERTEX; if (resource.contains("fragment")) return FRAGMENT; if (resource.contains("vsh")) return VERTEX; @@ -57,48 +57,48 @@ public class Shader implements OpenGLDeletable { ); } } - + private static final String SHADER_ASSETS_PREFIX = "assets/shaders/"; - + protected static Resource getShaderResource(String name) { return ResourceManager.getResource(SHADER_ASSETS_PREFIX + name); } - + private final int handle; private final ShaderType type; - + public Shader(ShaderType type, String source) { handle = glCreateShader(type.getGlCode()); OpenGLObjectTracker.register(this); - + this.type = type; - + glShaderSource(handle, source); glCompileShader(handle); - + if (glGetShaderi(handle, GL_COMPILE_STATUS) == GL_FALSE) { System.out.println("***************** ERROR ******************"); System.out.println(source); - throw new RuntimeException("Bad shader:\n" + glGetShaderInfoLog(handle)); + CrashReports.report(null, "Bad shader:\n %s", glGetShaderInfoLog(handle)); } } - + public Shader(String resource) { this( ShaderType.guessByResourceName(resource), getShaderResource(resource).readAsString() ); } - + @Override public void delete() { glDeleteShader(handle); } - + public int getHandle() { return handle; } - + public ShaderType getType() { return type; } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java index 3773d18..34624f4 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java @@ -18,29 +18,30 @@ package ru.windcorp.progressia.client.graphics.backend.shaders.attributes; import ru.windcorp.progressia.client.graphics.backend.shaders.Program; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class Attribute { - + protected final int handle; private final Program program; - + public Attribute(int handle, Program program) { if (handle < 0) { - throw new RuntimeException("Bad handle: " + handle); + CrashReports.report(null, "Bad handle: %s", handle); } - + this.handle = handle; this.program = program; } - + public int getHandle() { return handle; } - + public Program getProgram() { return program; } - + public AttributeVertexArray asVertexArray() { return new AttributeVertexArray(handle, program); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java index be78878..d1475b0 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java @@ -18,69 +18,70 @@ package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms; import ru.windcorp.progressia.client.graphics.backend.shaders.Program; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class Uniform { - + protected final int handle; private final Program program; - + public Uniform(int handle, Program program) { if (handle < 0) { - throw new RuntimeException("Bad handle: " + handle); + CrashReports.report(null, "Bad handle: %s", handle); } - + this.handle = handle; this.program = program; } - + public int getHandle() { return handle; } - + public Program getProgram() { return program; } - + public Uniform1Float as1Float() { return new Uniform1Float(handle, program); } - + public Uniform1Int as1Int() { return new Uniform1Int(handle, program); } - + public Uniform2Float as2Float() { return new Uniform2Float(handle, program); } - + public Uniform2Int as2Int() { return new Uniform2Int(handle, program); } - + public Uniform3Float as3Float() { return new Uniform3Float(handle, program); } - + public Uniform3Int as3Int() { return new Uniform3Int(handle, program); } - + public Uniform4Float as4Float() { return new Uniform4Float(handle, program); } - + public Uniform4Int as4Int() { return new Uniform4Int(handle, program); } - + public Uniform2Matrix as2Matrix() { return new Uniform2Matrix(handle, program); } - + public Uniform3Matrix as3Matrix() { return new Uniform3Matrix(handle, program); } - + public Uniform4Matrix as4Matrix() { return new Uniform4Matrix(handle, program); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java index 681effb..61e9666 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java @@ -21,117 +21,96 @@ import ru.windcorp.progressia.client.graphics.texture.Texture; import ru.windcorp.progressia.client.graphics.texture.TextureDataEditor; import ru.windcorp.progressia.client.graphics.texture.TextureSettings; import ru.windcorp.progressia.common.resource.Resource; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class GNUUnifontLoader { - - private static final AtlasGroup ATLAS_GROUP_GNU_UNIFONT = - new AtlasGroup("GNUUnifont", 1 << 12); - - private static final TextureSettings TEXTURE_SETTINGS = - new TextureSettings(false); - + + private static final AtlasGroup ATLAS_GROUP_GNU_UNIFONT = new AtlasGroup("GNUUnifont", 1 << 12); + + private static final TextureSettings TEXTURE_SETTINGS = new TextureSettings(false); + private static final int BITS_PER_HEX_DIGIT = 4; private static final int PREFIX_LENGTH = "0000:".length(); - + private static class ParsedGlyph { final char c; final TextureDataEditor data; - + ParsedGlyph(char c, TextureDataEditor data) { this.c = c; this.data = data; } } - + private static class AtlasGlyph { final char c; final Texture texture; - + AtlasGlyph(char c, Texture texture) { this.c = c; this.texture = texture; } } - + public static GNUUnifont load(Resource resource) { try (BufferedReader reader = createReader(resource)) { - return createStream(reader) - .map(GNUUnifontLoader::parse) - .map(GNUUnifontLoader::addToAtlas) - .collect(Collectors.collectingAndThen( - createMapper(), - GNUUnifont::new - )); + return createStream(reader).map(GNUUnifontLoader::parse).map(GNUUnifontLoader::addToAtlas) + .collect(Collectors.collectingAndThen(createMapper(), GNUUnifont::new)); } catch (IOException | UncheckedIOException e) { - throw new RuntimeException(e); + CrashReports.report(e, "Problem with load GNUUnifont"); + return null; } } - - private static BufferedReader createReader(Resource resource) - throws IOException - { + + private static BufferedReader createReader(Resource resource) throws IOException { return new BufferedReader( - new InputStreamReader( - new GZIPInputStream( - resource.getInputStream() - ), - StandardCharsets.UTF_8 - ) - ); + new InputStreamReader(new GZIPInputStream(resource.getInputStream()), StandardCharsets.UTF_8)); } private static Stream createStream(BufferedReader reader) { return reader.lines(); } - + private static ParsedGlyph parse(String declar) { int width = getWidth(declar); checkDeclaration(declar, width); - + char c = getChar(declar); - - TextureDataEditor editor = new TextureDataEditor( - width, GNUUnifont.HEIGHT, - width, GNUUnifont.HEIGHT, - TEXTURE_SETTINGS - ); - + + TextureDataEditor editor = new TextureDataEditor(width, GNUUnifont.HEIGHT, width, GNUUnifont.HEIGHT, + TEXTURE_SETTINGS); + for (int y = 0; y < GNUUnifont.HEIGHT; ++y) { for (int x = 0; x < width; ++x) { int bit = x + y * width; - - editor.setPixel( - x, GNUUnifont.HEIGHT - y - 1, - getBit(declar, bit) ? 0xFFFFFFFF : 0x00000000 - ); + + editor.setPixel(x, GNUUnifont.HEIGHT - y - 1, getBit(declar, bit) ? 0xFFFFFFFF : 0x00000000); } } - + return new ParsedGlyph(c, editor); } - + private static char getChar(String declar) { int result = 0; - + for (int i = 0; i < 4; ++i) { - result = - (result << BITS_PER_HEX_DIGIT) | - getHexValue(declar.charAt(i)); + result = (result << BITS_PER_HEX_DIGIT) | getHexValue(declar.charAt(i)); } - + return (char) result; } private static boolean getBit(String declar, int bit) { int character = PREFIX_LENGTH + (bit / BITS_PER_HEX_DIGIT); bit = bit % BITS_PER_HEX_DIGIT; - + char c = declar.charAt(character); int value = getHexValue(c); - + return (value & (1 << (BITS_PER_HEX_DIGIT - bit - 1))) != 0; } - + private static int getWidth(String declar) { int meaningfulChars = declar.length() - PREFIX_LENGTH; final int charsPerColumn = GNUUnifont.HEIGHT / BITS_PER_HEX_DIGIT; @@ -140,33 +119,38 @@ public class GNUUnifontLoader { private static void checkDeclaration(String declar, int width) { if (!GNUUnifont.WIDTHS.contains(width)) { - throw new RuntimeException("Width " + width + " is not supported (in declar \"" + declar + "\")"); + CrashReports.report(null, "Width %d is not supported (in declar \"%s\")", width, declar); } - + if ((declar.length() - PREFIX_LENGTH) % width != 0) { - throw new RuntimeException("Declar \"" + declar + "\" has invalid length"); + CrashReports.report(null, "Declar \"%s\" has invalid length", declar); } - + for (int i = 0; i < declar.length(); ++i) { if (i == BITS_PER_HEX_DIGIT) { if (declar.charAt(i) != ':') { - throw new RuntimeException("No colon ':' found in declar \"" + declar + "\" at index 4"); + CrashReports.report(null, "No colon ':' found in declar \"%s\" at index 4", declar); } } else { char c = declar.charAt(i); - + if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))) { - throw new RuntimeException("Illegal char in declar \"" + declar + "\" at index " + i + "; expected 0-9A-F"); + CrashReports.report(null, + "Illegal char in declar \"%s\" at index " + i + "; expected 0-9A-F", declar); } } } } - + private static int getHexValue(char digit) { - if (digit < '0') throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)"); - if (digit <= '9') return digit - '0'; - if (digit < 'A') throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)"); - if (digit <= 'F') return digit - 'A' + 0xA; + if (digit < '0') + throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)"); + if (digit <= '9') + return digit - '0'; + if (digit < 'A') + throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)"); + if (digit <= 'F') + return digit - 'A' + 0xA; throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)"); } @@ -174,24 +158,21 @@ public class GNUUnifontLoader { Sprite sprite = Atlases.loadSprite(glyph.data.getData(), ATLAS_GROUP_GNU_UNIFONT); return new AtlasGlyph(glyph.c, new SimpleTexture(sprite)); } - - private static - Collector> - createMapper() { - return Collector.of( - TCharObjectHashMap::new, - + + private static Collector> createMapper() { + return Collector.of(TCharObjectHashMap::new, + (map, glyph) -> map.put(glyph.c, glyph.texture), - + (a, b) -> { a.putAll(b); return a; }, - - Characteristics.UNORDERED - ); + + Characteristics.UNORDERED); } - private GNUUnifontLoader() {} + private GNUUnifontLoader() { + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java index 9260476..7ba1b83 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -39,40 +39,40 @@ import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.graphics.input.bus.InputBus; import ru.windcorp.progressia.client.graphics.input.bus.InputListener; import ru.windcorp.progressia.common.util.Named; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class Component extends Named { - private final List children = - Collections.synchronizedList(new CopyOnWriteArrayList<>()); - + private final List children = Collections.synchronizedList(new CopyOnWriteArrayList<>()); + private Component parent = null; - + private EventBus eventBus = null; private InputBus inputBus = null; - + private int x, y; private int width, height; - + private boolean valid = false; - + private Vec2i preferredSize = null; - + private Object layoutHint = null; private Layout layout = null; - + private boolean isFocusable = false; private boolean isFocused = false; - + private boolean isHovered = false; public Component(String name) { super(name); } - + public Component getParent() { return parent; } - + protected void setParent(Component parent) { if (this.parent != parent) { Component previousParent = this.parent; @@ -81,68 +81,71 @@ public class Component extends Named { dispatchEvent(new ParentChangedEvent(this, previousParent, parent)); } } - + public List getChildren() { return children; } - + public Component getChild(int index) { synchronized (getChildren()) { - if (index < 0 || index >= getChildren().size()) return null; + if (index < 0 || index >= getChildren().size()) + return null; return getChildren().get(index); } } - + public int getChildIndex(Component child) { return getChildren().indexOf(child); } - + public int getOwnIndex() { Component parent = getParent(); if (parent != null) { return parent.getChildIndex(this); } - + return -1; } - + public void moveChild(Component child, int newIndex) { - if (newIndex == -1) newIndex = getChildren().size() - 1; - + if (newIndex == -1) + newIndex = getChildren().size() - 1; + if (getChildren().remove(child)) { getChildren().add(newIndex, child); invalidate(); } } - + public void moveSelf(int newIndex) { Component parent = getParent(); if (parent != null) { parent.moveChild(this, newIndex); } } - + public Component addChild(Component child, int index) { - if (index == -1) index = getChildren().size(); + if (index == -1) + index = getChildren().size(); invalidate(); getChildren().add(index, child); child.setParent(this); - + dispatchEvent(new ChildAddedEvent(this, child)); - + return this; } - + public Component addChild(Component child) { return addChild(child, -1); } - + public Component removeChild(Component child) { if (!getChildren().contains(child)) { return this; } - + if (child.isFocused()) { child.focusNext(); } @@ -150,204 +153,205 @@ public class Component extends Named { invalidate(); getChildren().remove(child); child.setParent(null); - + dispatchEvent(new ChildRemovedEvent(this, child)); - + return this; } - + public synchronized int getX() { return x; } - + public synchronized int getY() { return y; } - + public synchronized Component setPosition(int x, int y) { invalidate(); this.x = x; this.y = y; return this; } - + public synchronized int getWidth() { return width; } - + public synchronized int getHeight() { return height; } - + public synchronized Component setSize(int width, int height) { invalidate(); this.width = width; this.height = height; return this; } - + public Component setSize(Vec2i size) { return setSize(size.x, size.y); } - + public synchronized Component setBounds(int x, int y, int width, int height) { setPosition(x, y); setSize(width, height); return this; } - + public Component setBounds(int x, int y, Vec2i size) { return setBounds(x, y, size.x, size.y); } - + public boolean isValid() { return valid; } - + public synchronized void invalidate() { valid = false; getChildren().forEach(child -> child.invalidate()); } - + public synchronized void validate() { Component parent = getParent(); invalidate(); - + if (parent == null) { layoutSelf(); } else { parent.validate(); } } - + protected synchronized void layoutSelf() { try { if (getLayout() != null) { getLayout().layout(this); } - + getChildren().forEach(child -> { child.layoutSelf(); }); - + valid = true; } catch (Exception e) { - throw new RuntimeException(e); + CrashReports.report(e, "__DOC__ME__"); } } - + public synchronized Vec2i getPreferredSize() { if (preferredSize != null) { return preferredSize; } - + if (getLayout() != null) { try { return getLayout().calculatePreferredSize(this); } catch (Exception e) { - throw new RuntimeException(e); + CrashReports.report(e, "__DOC__ME__"); } } - + return new Vec2i(0, 0); } - + public synchronized Component setPreferredSize(Vec2i preferredSize) { this.preferredSize = preferredSize; return this; } - + public Component setPreferredSize(int width, int height) { return setPreferredSize(new Vec2i(width, height)); } - + public Layout getLayout() { return layout; } - + public synchronized Component setLayout(Layout layout) { invalidate(); this.layout = layout; return this; } - + public Object getLayoutHint() { return layoutHint; } - + public Component setLayoutHint(Object hint) { this.layoutHint = hint; return this; } - + public boolean isFocusable() { return isFocusable; } - + public Component setFocusable(boolean focusable) { this.isFocusable = focusable; return this; } - + public boolean isFocused() { return isFocused; } - + protected synchronized void setFocused(boolean focus) { if (focus != this.isFocused) { dispatchEvent(new FocusEvent(this, focus)); this.isFocused = focus; } } - + public Component takeFocus() { if (isFocused()) { return this; } - + Component comp = this; Component focused = null; - + while (comp != null) { if ((focused = comp.findFocused()) != null) { focused.setFocused(false); setFocused(true); return this; } - + comp = comp.getParent(); } - + setFocused(true); return this; } - + public void focusNext() { Component component = this; - + while (true) { - + component = component.getNextFocusCandidate(true); if (component == this) { return; } - + if (component.isFocusable()) { setFocused(false); component.setFocused(true); return; } - + } } - + private Component getNextFocusCandidate(boolean canUseChildren) { - if (canUseChildren) synchronized (getChildren()) { - if (!getChildren().isEmpty()) { - return getChild(0); + if (canUseChildren) + synchronized (getChildren()) { + if (!getChildren().isEmpty()) { + return getChild(0); + } } - } - + Component parent = getParent(); if (parent != null) { synchronized (parent.getChildren()) { @@ -356,32 +360,32 @@ public class Component extends Named { return parent.getChild(ownIndex + 1); } } - + return parent.getNextFocusCandidate(false); } - + return this; } - + public void focusPrevious() { Component component = this; - + while (true) { - + component = component.getPreviousFocusCandidate(); if (component == this) { return; } - + if (component.isFocusable()) { setFocused(false); component.setFocused(true); return; } - + } } - + private Component getPreviousFocusCandidate() { Component parent = getParent(); if (parent != null) { @@ -391,30 +395,30 @@ public class Component extends Named { return parent.getChild(ownIndex - 1).getLastDeepChild(); } } - + return parent; } - + return getLastDeepChild(); } - + private Component getLastDeepChild() { synchronized (getChildren()) { if (!getChildren().isEmpty()) { return getChild(getChildren().size() - 1).getLastDeepChild(); } - + return this; } } - + public synchronized Component findFocused() { if (isFocused()) { return this; } - + Component result; - + synchronized (getChildren()) { for (Component c : getChildren()) { result = c.findFocused(); @@ -423,10 +427,10 @@ public class Component extends Named { } } } - + return null; } - + public boolean isHovered() { return isHovered; } @@ -434,9 +438,9 @@ public class Component extends Named { protected void setHovered(boolean isHovered) { if (this.isHovered != isHovered) { this.isHovered = isHovered; - + if (!isHovered && !getChildren().isEmpty()) { - + getChildren().forEach(child -> { if (child.isHovered()) { child.setHovered(false); @@ -444,7 +448,7 @@ public class Component extends Named { } }); } - + dispatchEvent(new HoverEvent(this, isHovered)); } } @@ -453,40 +457,36 @@ public class Component extends Named { if (eventBus == null) { eventBus = new EventBus(getName()); } - + eventBus.register(listener); } - + public void removeListener(Object listener) { - if (eventBus == null) return; + if (eventBus == null) + return; eventBus.unregister(listener); } - + public void dispatchEvent(Object event) { - if (eventBus == null) return; + if (eventBus == null) + return; eventBus.post(event); } - - public void addListener( - Class type, - boolean handlesConsumed, - InputListener listener - ) { + + public void addListener(Class type, boolean handlesConsumed, + InputListener listener) { if (inputBus == null) { inputBus = new InputBus(); } - + inputBus.register(type, handlesConsumed, listener); } - public void addListener( - Class type, - InputListener listener - ) { + public void addListener(Class type, InputListener listener) { if (inputBus == null) { inputBus = new InputBus(); } - + inputBus.register(type, listener); } @@ -501,43 +501,45 @@ public class Component extends Named { inputBus.dispatch(input); } } - + public void dispatchInput(Input input) { try { switch (input.getTarget()) { - case FOCUSED: - dispatchInputToFocused(input); - break; - case HOVERED: - dispatchInputToHovered(input); - break; - case ALL: - default: - dispatchInputToAll(input); - break; + case FOCUSED: + dispatchInputToFocused(input); + break; + case HOVERED: + dispatchInputToHovered(input); + break; + case ALL: + default: + dispatchInputToAll(input); + break; } } catch (Exception e) { - throw new RuntimeException(e); + CrashReports.report(e, "__DOC__ME__"); } } private void dispatchInputToFocused(Input input) { Component c = findFocused(); - - if (c == null) return; - if (attemptFocusTransfer(input, c)) return; - + + if (c == null) + return; + if (attemptFocusTransfer(input, c)) + return; + while (c != null) { c.handleInput(input); c = c.getParent(); } } - + private void dispatchInputToHovered(Input input) { getChildren().forEach(child -> { if (child.containsCursor()) { child.setHovered(true); - + if (!input.isConsumed()) { child.dispatchInput(input); } @@ -555,11 +557,13 @@ public class Component extends Named { } private boolean attemptFocusTransfer(Input input, Component focused) { - if (input.isConsumed()) return false; - if (!(input.getEvent() instanceof KeyEvent)) return false; - + if (input.isConsumed()) + return false; + if (!(input.getEvent() instanceof KeyEvent)) + return false; + KeyEvent keyInput = (KeyEvent) input.getEvent(); - + if (keyInput.getKey() == GLFW.GLFW_KEY_TAB && !keyInput.isRelease()) { input.consume(); if (keyInput.hasShift()) { @@ -569,23 +573,18 @@ public class Component extends Named { } return true; } - + return false; } - + public synchronized boolean contains(int x, int y) { - return - x >= getX() && x < getX() + getWidth() && - y >= getY() && y < getY() + getHeight(); + return x >= getX() && x < getX() + getWidth() && y >= getY() && y < getY() + getHeight(); } - + public boolean containsCursor() { - return contains( - (int) InputTracker.getCursorX(), - (int) InputTracker.getCursorY() - ); + return contains((int) InputTracker.getCursorX(), (int) InputTracker.getCursorY()); } - + public void requestReassembly() { if (parent != null) { parent.requestReassembly(); @@ -602,60 +601,60 @@ public class Component extends Named { if (width == 0 || height == 0) { return; } - + if (!isValid()) { validate(); } - + try { assembleSelf(target); } catch (Exception e) { - throw new RuntimeException(e); + CrashReports.report(e, "__DOC__ME__"); } - + assembleChildren(target); - + try { postAssembleSelf(target); } catch (Exception e) { - throw new RuntimeException(e); + CrashReports.report(e, "__DOC__ME__"); } } - + protected void assembleSelf(RenderTarget target) { // To be overridden } - + protected void postAssembleSelf(RenderTarget target) { // To be overridden } - + protected void assembleChildren(RenderTarget target) { getChildren().forEach(child -> child.assemble(target)); } - -// /** -// * Returns a component that displays this component in its center. -// * @return a {@link Aligner} initialized to center this component -// */ -// public Component center() { -// return new Aligner(this); -// } -// -// /** -// * Returns a component that aligns this component. -// * @return a {@link Aligner} initialized with this component -// */ -// public Component align(double x, double y) { -// return new Aligner(this, x, y); -// } -// -// /** -// * Returns a component that allows scrolling this component -// * @return a {@link Scroller} initialized with this component -// */ -// public Component scroller() { -// return new Scroller(this); -// } + + // /** + // * Returns a component that displays this component in its center. + // * @return a {@link Aligner} initialized to center this component + // */ + // public Component center() { + // return new Aligner(this); + // } + // + // /** + // * Returns a component that aligns this component. + // * @return a {@link Aligner} initialized with this component + // */ + // public Component align(double x, double y) { + // return new Aligner(this, x, y); + // } + // + // /** + // * Returns a component that allows scrolling this component + // * @return a {@link Scroller} initialized with this component + // */ + // public Component scroller() { + // return new Scroller(this); + // } } \ No newline at end of file diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java index c080192..f97c4b0 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/Keys.java @@ -31,108 +31,101 @@ import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.TIntSet; import gnu.trove.set.hash.TIntHashSet; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class Keys { - - private static final TIntObjectMap CODES_TO_NAMES = - new TIntObjectHashMap<>(); - - private static final TObjectIntMap NAMES_TO_CODES = - new TObjectIntHashMap<>(); - + + private static final TIntObjectMap CODES_TO_NAMES = new TIntObjectHashMap<>(); + + private static final TObjectIntMap NAMES_TO_CODES = new TObjectIntHashMap<>(); + private static final TIntSet MOUSE_BUTTONS = new TIntHashSet(); - + private static final String KEY_PREFIX = "GLFW_KEY_"; private static final String MOUSE_BUTTON_PREFIX = "GLFW_MOUSE_BUTTON_"; - - private static final Set IGNORE_FIELDS = - new HashSet<>(Arrays.asList( - "GLFW_KEY_UNKNOWN", - "GLFW_KEY_LAST", - "GLFW_MOUSE_BUTTON_LAST", - "GLFW_MOUSE_BUTTON_1", // Alias for LEFT + + private static final Set IGNORE_FIELDS = new HashSet<>( + Arrays.asList("GLFW_KEY_UNKNOWN", "GLFW_KEY_LAST", "GLFW_MOUSE_BUTTON_LAST", "GLFW_MOUSE_BUTTON_1", // Alias + // for + // LEFT "GLFW_MOUSE_BUTTON_2", // Alias for RIGHT - "GLFW_MOUSE_BUTTON_3" // Alias for MIDDLE + "GLFW_MOUSE_BUTTON_3" // Alias for MIDDLE )); - + static { initializeDictionary(); } private static void initializeDictionary() { try { - + for (Field field : GLFW.class.getFields()) { - if (!Modifier.isStatic(field.getModifiers())) continue; - if (!Modifier.isFinal(field.getModifiers())) continue; - + if (!Modifier.isStatic(field.getModifiers())) + continue; + if (!Modifier.isFinal(field.getModifiers())) + continue; + String name = field.getName(); - - if ( - !name.startsWith(KEY_PREFIX) && - !name.startsWith(MOUSE_BUTTON_PREFIX) - ) continue; - - if (IGNORE_FIELDS.contains(name)) continue; - + + if (!name.startsWith(KEY_PREFIX) && !name.startsWith(MOUSE_BUTTON_PREFIX)) + continue; + + if (IGNORE_FIELDS.contains(name)) + continue; + addToDictionary(field); } - + } catch (IllegalAccessException e) { - throw new RuntimeException(e); + CrashReports.report(e, "Cannot access GLFW constants"); } } - private static void addToDictionary(Field field) - throws IllegalAccessException { - + private static void addToDictionary(Field field) throws IllegalAccessException { + int value = field.getInt(null); String name = field.getName(); - + if (name.startsWith(KEY_PREFIX)) { name = name.substring(KEY_PREFIX.length()); } else if (name.startsWith(MOUSE_BUTTON_PREFIX)) { name = "MOUSE_" + name.substring(MOUSE_BUTTON_PREFIX.length()); MOUSE_BUTTONS.add(value); } - + if (CODES_TO_NAMES.containsKey(value)) { - throw new RuntimeException( - "Duplicate keys: " + CODES_TO_NAMES.get(value) + - " and " + name + " both map to " + value + - "(0x" + Integer.toHexString(value) + ")" - ); + CrashReports.report(null, "Duplicate keys: %s and %s both map to %d(0x%s)", + CODES_TO_NAMES.get(value), name, value, Integer.toHexString(value)); } - + CODES_TO_NAMES.put(value, name); NAMES_TO_CODES.put(name, value); } - + public static String getInternalName(int code) { String result = CODES_TO_NAMES.get(code); - + if (result == null) { return "UNKNOWN"; } - + return result; } - + public static String getDisplayName(int code) { String name = getInternalName(code); - + if (name.startsWith("KP_")) { name = "KEYPAD_" + name.substring("KP_".length()); } - - name = Character.toTitleCase(name.charAt(0)) + - name.substring(1).toLowerCase(); - + + name = Character.toTitleCase(name.charAt(0)) + name.substring(1).toLowerCase(); + name = name.replace('_', ' '); - + return name; } - + public static int getCode(String internalName) { if (NAMES_TO_CODES.containsKey(internalName)) { return -1; @@ -140,7 +133,7 @@ public class Keys { return NAMES_TO_CODES.get(internalName); } } - + public static boolean isMouse(int code) { return MOUSE_BUTTONS.contains(code); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java index 0d7c435..a945f03 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java @@ -13,72 +13,67 @@ import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue; import ru.windcorp.progressia.common.resource.Resource; import ru.windcorp.progressia.common.util.BinUtil; import ru.windcorp.progressia.common.util.Named; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class Atlases { - + public static class AtlasGroup extends Named { private final int atlasSize; - + public AtlasGroup(String name, int atlasSize) { super(name); this.atlasSize = atlasSize; - + if (!BinUtil.isPowerOf2(atlasSize)) { - throw new IllegalArgumentException( - "Atlas size " + atlasSize - + " is not a power of 2" - ); + throw new IllegalArgumentException("Atlas size " + atlasSize + " is not a power of 2"); } } - + public int getAtlasSize() { return atlasSize; } - + @Override public int hashCode() { return super.hashCode(); } - + @Override public boolean equals(Object obj) { return super.equals(obj); } } - + public static class Atlas { private final AtlasGroup group; - + private final TextureDataEditor editor; private int nextX, nextY; private int rowHeight; - + private final TexturePrimitive primitive; - + public Atlas(AtlasGroup group) { this.group = group; int size = group.getAtlasSize(); - + this.editor = new TextureDataEditor(size, size, size, size, SETTINGS); this.primitive = new TexturePrimitive(editor.getData()); } - + public Sprite addSprite(TextureData data) { int width = data.getContentWidth(); int height = data.getContentHeight(); - + selectPosition(width, height); - + editor.draw(data, nextX, nextY); - - Sprite result = new Sprite( - getPrimitive(), - toPrimitiveCoords(nextX, nextY), - toPrimitiveCoords(width, height) - ); - + + Sprite result = new Sprite(getPrimitive(), toPrimitiveCoords(nextX, nextY), + toPrimitiveCoords(width, height)); + nextX += width; - + return result; } @@ -87,10 +82,10 @@ public class Atlases { // Wrapping nextY += rowHeight; // Move to next row rowHeight = height; // Next row is at least 'height' high - nextX = 0; // Start the row over + nextX = 0; // Start the row over } else { // Not wrapping - + // Update rowHeight if necessary if (rowHeight < height) { rowHeight = height; @@ -99,10 +94,7 @@ public class Atlases { } private Vec2 toPrimitiveCoords(int x, int y) { - return new Vec2( - toPrimitiveCoord(x), - toPrimitiveCoord(y) - ); + return new Vec2(toPrimitiveCoord(x), toPrimitiveCoord(y)); } private float toPrimitiveCoord(int c) { @@ -112,87 +104,82 @@ public class Atlases { public boolean canAddSprite(TextureData data) { int width = data.getContentWidth(); int height = data.getContentHeight(); - + // Try to fit without wrapping - + if (nextY + height > getSize()) // Does not fit vertically return false; - + if (nextX + width <= getSize()) // Can place at (nextX; nextY) return true; - + // Try wrapping - + if (width > getSize()) // GTFO. We couldn't fit if if we tried return false; - + if (nextY + rowHeight + height > getSize()) // Does not fit vertically when wrapped return false; - + // Can place at (0; nextY + rowHeight) return true; } - + public AtlasGroup getGroup() { return group; } - + public TexturePrimitive getPrimitive() { return primitive; } - + public int getSize() { return editor.getBufferWidth(); } } - + private static final TextureSettings SETTINGS = new TextureSettings(false); - - private static final Map LOADED = - new HashMap<>(); - private static final Multimap ATLASES = - MultimapBuilder.hashKeys().arrayListValues().build(); - + + private static final Map LOADED = new HashMap<>(); + private static final Multimap ATLASES = MultimapBuilder.hashKeys().arrayListValues().build(); + public static Sprite getSprite(Resource resource, AtlasGroup group) { return LOADED.computeIfAbsent(resource, k -> loadSprite(k, group)); } - + private static Sprite loadSprite(Resource resource, AtlasGroup group) { try { - TextureDataEditor data = - TextureLoader.loadPixels(resource, SETTINGS); - + TextureDataEditor data = TextureLoader.loadPixels(resource, SETTINGS); + return loadSprite(data.getData(), group); } catch (IOException e) { - throw new RuntimeException(e); + CrashReports.report(e, "Problem with load atlases sprite"); + return null; } } - + public static Sprite loadSprite(TextureData data, AtlasGroup group) { Atlas atlas = getReadyAtlas(group, data); return atlas.addSprite(data); } - + private static Atlas getReadyAtlas(AtlasGroup group, TextureData data) { List atlases = (List) ATLASES.get(group); - - if ( - atlases.isEmpty() || - !(atlases.get(atlases.size() - 1).canAddSprite(data)) - ) { + + if (atlases.isEmpty() || !(atlases.get(atlases.size() - 1).canAddSprite(data))) { Atlas newAtlas = new Atlas(group); - + if (!newAtlas.canAddSprite(data)) { - throw new RuntimeException("Could not fit tex into atlas of size " + newAtlas.getSize()); + CrashReports.report(null, "Could not fit tex into atlas of size %d", newAtlas.getSize()); } - + atlases.add(newAtlas); } - + return atlases.get(atlases.size() - 1); } @@ -201,7 +188,8 @@ public class Atlases { RenderTaskQueue.invokeLater(atlas.getPrimitive()::load); }); } - - private Atlases() {} + + private Atlases() { + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java index e453ff7..e0711db 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java @@ -6,21 +6,22 @@ import java.util.Map; import ru.windcorp.progressia.common.resource.Resource; import ru.windcorp.progressia.common.resource.ResourceManager; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class SimpleTextures { - + private static final TextureSettings SETTINGS = new TextureSettings(false); - + private static final Map TEXTURES = new HashMap<>(); - + public static Texture get(Resource resource) { return TEXTURES.computeIfAbsent(resource, SimpleTextures::load); } - + public static Texture get(String textureName) { return get(ResourceManager.getTextureResource(textureName)); } - + private static Texture load(Resource resource) { try { TextureDataEditor data = @@ -30,9 +31,10 @@ public class SimpleTextures { new Sprite(new TexturePrimitive(data.getData())) ); } catch (IOException e) { - throw new RuntimeException(e); + CrashReports.report(e, "Problem with load texture"); + return null; } - + } private SimpleTextures() {} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java index c59405e..e4f5fdc 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java @@ -24,27 +24,28 @@ import java.util.Arrays; import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker; import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class TexturePrimitive implements OpenGLDeletable { - + private static final int NOT_LOADED = -1; - + private static int[] currentlyBound = new int[32]; static { Arrays.fill(currentlyBound, NOT_LOADED); } - + private int handle = NOT_LOADED; private TextureData pixels; public TexturePrimitive(TextureData pixels) { this.pixels = pixels; } - + public TextureData getData() { return pixels; } - + public int getBufferWidth() { return pixels.getBufferWidth(); } @@ -64,21 +65,21 @@ public class TexturePrimitive implements OpenGLDeletable { public boolean isLoaded() { return handle != NOT_LOADED; } - + public void bind(int slot) { if (!isLoaded()) { load(); } - + if (currentlyBound[slot] == handle) { return; } - + int code = GL_TEXTURE0 + slot; - + glActiveTexture(code); glBindTexture(GL_TEXTURE_2D, handle); - + currentlyBound[slot] = handle; } @@ -87,9 +88,9 @@ public class TexturePrimitive implements OpenGLDeletable { handle = pixels.load(); OpenGLObjectTracker.register(this); - + if (handle < 0) { - throw new RuntimeException("oops"); + CrashReports.report(null, "Failed to create texture"); } } diff --git a/src/main/java/ru/windcorp/progressia/client/localization/Localizer.java b/src/main/java/ru/windcorp/progressia/client/localization/Localizer.java index 413ddab..16f7b05 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/Localizer.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/Localizer.java @@ -3,6 +3,8 @@ package ru.windcorp.progressia.client.localization; import java.lang.ref.WeakReference; import java.util.*; +import ru.windcorp.progressia.common.util.crash.CrashReports; + public class Localizer { private static final Localizer INSTANCE = new Localizer("assets/languages/", "en-US"); @@ -17,7 +19,7 @@ public class Localizer { private final Collection> listeners = Collections.synchronizedCollection(new LinkedList<>()); - //lang list must be in the same folder as .lang files + // lang list must be in the same folder as .lang files public Localizer(String langFolder) { this.langFolder = langFolder; this.langList = new Parser(langFolder + "lang_list.txt").parse(); @@ -41,7 +43,7 @@ public class Localizer { data = new Parser(langFolder + this.language + ".lang").parse(); pokeListeners(language); } else { - throw new RuntimeException("Language not found: " + language); + CrashReports.report(null, "Language not found: %s", language); } } @@ -64,7 +66,7 @@ public class Localizer { } private void pokeListeners(String newLanguage) { - //TODO extract as weak bus listener class + // TODO extract as weak bus listener class synchronized (listeners) { Iterator> iterator = listeners.iterator(); while (iterator.hasNext()) { diff --git a/src/main/java/ru/windcorp/progressia/client/localization/Parser.java b/src/main/java/ru/windcorp/progressia/client/localization/Parser.java index cfa6022..c0438d5 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/Parser.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/Parser.java @@ -3,6 +3,7 @@ package ru.windcorp.progressia.client.localization; import ru.windcorp.jputil.chars.EscapeException; import ru.windcorp.jputil.chars.Escaper; import ru.windcorp.progressia.common.resource.ResourceManager; +import ru.windcorp.progressia.common.util.crash.CrashReports; import java.io.IOException; import java.io.Reader; @@ -54,7 +55,7 @@ public class Parser { if (c == '=') { String key = ESCAPER.escape(stringBuilder.toString()); stringBuilder.setLength(0); - rawData.read(); //skip a char + rawData.read(); // skip a char while (true) { code = rawData.read(); if (code == -1) { @@ -80,7 +81,8 @@ public class Parser { } } catch (IOException | EscapeException e) { - throw new RuntimeException(e); + CrashReports.report(e, "Problems with parsing"); + return null; } return parsedData; } diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java index e79cebe..1e33fd3 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java @@ -7,16 +7,17 @@ import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive; import ru.windcorp.progressia.client.graphics.texture.TextureSettings; import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.util.NamespacedRegistry; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class EntityRenderRegistry extends NamespacedRegistry { - + private static final EntityRenderRegistry INSTANCE = new EntityRenderRegistry(); public static EntityRenderRegistry getInstance() { return INSTANCE; } - + public static TexturePrimitive getEntityTexture(String name) { try { return new TexturePrimitive( @@ -28,7 +29,8 @@ public class EntityRenderRegistry extends NamespacedRegistry { ).getData() ); } catch (IOException e) { - throw new RuntimeException(e); + CrashReports.report(e, "__DOC__ME__"); + return null; } } diff --git a/src/main/java/ru/windcorp/progressia/common/resource/Resource.java b/src/main/java/ru/windcorp/progressia/common/resource/Resource.java index 7a14329..d2e42ea 100644 --- a/src/main/java/ru/windcorp/progressia/common/resource/Resource.java +++ b/src/main/java/ru/windcorp/progressia/common/resource/Resource.java @@ -30,50 +30,53 @@ import com.google.common.io.CharStreams; import ru.windcorp.progressia.Progressia; import ru.windcorp.progressia.common.util.Named; +import ru.windcorp.progressia.common.util.crash.CrashReports; public class Resource extends Named { - + public Resource(String name) { super(name); } - + public InputStream getInputStream() { // TODO Do proper resource lookup return Progressia.class.getClassLoader().getResourceAsStream(getName()); } - + public Reader getReader() { return new InputStreamReader(getInputStream()); } - + public String readAsString() { try (Reader reader = getReader()) { return CharStreams.toString(reader); } catch (IOException e) { - throw new RuntimeException(e); // TODO handle gracefully + CrashReports.report(e, "__DOC__ME__"); + return null; } } - + public ByteBuffer readAsBytes(ByteBuffer output) { byte[] byteArray; try (InputStream stream = getInputStream()) { byteArray = ByteStreams.toByteArray(stream); } catch (IOException e) { - throw new RuntimeException(e); // TODO handle gracefully + CrashReports.report(e, "__DOC__ME__"); + return null; } - + if (output == null || output.remaining() < byteArray.length) { output = BufferUtils.createByteBuffer(byteArray.length); } - + int position = output.position(); output.put(byteArray); output.limit(output.position()); output.position(position); - + return output; } - + public ByteBuffer readAsBytes() { return readAsBytes(null); } diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java similarity index 76% rename from src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java rename to src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java index 18bacba..ce4cdee 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReportGenerator.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java @@ -1,216 +1,212 @@ -package ru.windcorp.progressia.common.util.crash; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.util.StringBuilderWriter; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.*; - -public class CrashReportGenerator { - - private CrashReportGenerator() {} - - private static final Path CRASH_REPORTS_PATH = Paths.get("crash-reports"); - - private static final Collection PROVIDERS = - Collections.synchronizedCollection(new ArrayList<>()); - - private static final Collection ANALYZERS = - Collections.synchronizedCollection(new ArrayList<>()); - - private static final Logger LOGGER = LogManager.getLogger("crash"); - - /** - * This method never returns. - *

- * TODO document - * @param throwable - * @param messageFormat - * @param args - */ - public static void crash(Throwable throwable, String messageFormat, Object... args) { - StringBuilder output = new StringBuilder(); - - appendContextProviders(output); - addSeparator(output); - if (appendAnalyzers(output, throwable, messageFormat, args)) { - addSeparator(output); - } - - appendMessageFormat(output, messageFormat, args); - - appendStackTrace(output, throwable); - - export(output.toString()); - - System.exit(0); - } - - private static void appendContextProviders(StringBuilder output) { - - // Do a local copy to avoid deadlocks -OLEGSHA - ContextProvider[] localProvidersCopy = - PROVIDERS.toArray(new ContextProvider[PROVIDERS.size()]); - - for (ContextProvider provider : localProvidersCopy) { - if (provider == null) continue; - - addSeparator(output); - - try { - Map buf = new HashMap<>(); - provider.provideContext(buf); - - if (!buf.isEmpty()) { - output.append("Provider name: ").append(provider.getName()).append("\n"); - for (Map.Entry entry : buf.entrySet()) { - output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); - } - } - } catch (Throwable t) { - output.append("\n"); - - String providerName; - - try { - providerName = provider.getName(); - } catch (Throwable t1) { - providerName = provider.getClass().getName(); - } - - output.append(providerName).append(" is broken").append("\n"); - // ContextProvider is broken - } - } - } - - private static boolean appendAnalyzers( - StringBuilder output, - Throwable throwable, String messageFormat, Object[] args - ) { - boolean analyzerResponsesExist = false; - - // Do a local copy to avoid deadlocks -OLEGSHA - Analyzer[] localAnalyzersCopy = - ANALYZERS.toArray(new Analyzer[ANALYZERS.size()]); - - for (Analyzer analyzer : localAnalyzersCopy) { - if (analyzer == null) continue; - - String answer; - try { - answer = analyzer.analyze(throwable, messageFormat, args); - - if (answer != null && !answer.isEmpty()) { - analyzerResponsesExist = true; - output.append(analyzer.getName()).append(": ").append(answer).append("\n"); - } - } catch (Throwable t) { - analyzerResponsesExist = true; - - output.append("\n"); - - String analyzerName; - - try { - analyzerName = analyzer.getName(); - } catch (Throwable t1) { - analyzerName = analyzer.getClass().getName(); - } - - output.append(analyzerName).append(" is broken").append("\n"); - // Analyzer is broken - } - } - - return analyzerResponsesExist; - } - - private static void appendMessageFormat(StringBuilder output, String messageFormat, Object... arg) { - output.append("Provided description: \n").append(String.format(messageFormat, arg)).append("\n"); - - addSeparator(output); - } - - private static void appendStackTrace(StringBuilder output, Throwable throwable) { - output.append("Stacktrace: \n"); - - if (throwable == null) { - output.append("no Throwable provided").append("\n"); - return; - } - - // Formatting to a human-readable string - Writer sink = new StringBuilderWriter(output); - try { - throwable.printStackTrace(new PrintWriter(sink)); - } catch (Exception e) { - // PLAK - } - output.append("\n"); - } - - private static void export(String report) { - try { - LOGGER.fatal("/n" + report); - } catch (Exception e) { - // PLAK - } - - System.err.println(report); - - generateCrashReportFiles(report); - } - - private static void generateCrashReportFiles(String output) { - Date date = new Date(); - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss"); - - try { - if (!Files.exists(CRASH_REPORTS_PATH)) Files.createDirectory(CRASH_REPORTS_PATH); - - createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/latest.log"); - createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/crash-" + dateFormat.format(date) + ".log"); - } catch (Throwable t) { - // Crash Report not created - } - } - - private static void createFileForCrashReport(String buffer, String filename) { - try ( - BufferedWriter writer = Files.newBufferedWriter( - Paths.get(filename), - StandardCharsets.UTF_8 - ) - ) { - writer.write(buffer); - } catch (IOException ex) { - // Crash Report not created - } - } - - public static void registerProvider(ContextProvider provider) { - PROVIDERS.add(provider); - } - - public static void registerAnalyzer(Analyzer analyzer) { - ANALYZERS.add(analyzer); - } - - private static void addSeparator(StringBuilder sb) { - sb.append( - // 80 chars - "--------------------------------------------------------------------------------" - ).append("\n"); - } -} +package ru.windcorp.progressia.common.util.crash; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.util.StringBuilderWriter; + +import ru.windcorp.jputil.chars.StringUtil; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +public class CrashReports { + + private CrashReports() { + } + + private static final Path CRASH_REPORTS_PATH = Paths.get("crash-reports"); + + private static final Collection PROVIDERS = Collections.synchronizedCollection(new ArrayList<>()); + + private static final Collection ANALYZERS = Collections.synchronizedCollection(new ArrayList<>()); + + private static final Logger LOGGER = LogManager.getLogger("crash"); + + /** + * This method never returns. + *

+ * TODO document + * + * @param throwable + * @param messageFormat + * @param args + */ + public static void report(Throwable throwable, String messageFormat, Object... args) { + StringBuilder output = new StringBuilder(); + + appendContextProviders(output); + addSeparator(output); + if (appendAnalyzers(output, throwable, messageFormat, args)) { + addSeparator(output); + } + + appendMessageFormat(output, messageFormat, args); + + appendStackTrace(output, throwable); + + export(output.toString()); + + System.exit(0); + } + + private static void appendContextProviders(StringBuilder output) { + + // Do a local copy to avoid deadlocks -OLEGSHA + ContextProvider[] localProvidersCopy = PROVIDERS.toArray(new ContextProvider[PROVIDERS.size()]); + + for (ContextProvider provider : localProvidersCopy) { + if (provider == null) + continue; + + addSeparator(output); + + try { + Map buf = new HashMap<>(); + provider.provideContext(buf); + + if (!buf.isEmpty()) { + output.append("Provider name: ").append(provider.getName()).append("\n"); + for (Map.Entry entry : buf.entrySet()) { + output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + } + } + } catch (Throwable t) { + output.append("\n"); + + String providerName; + + try { + providerName = provider.getName(); + } catch (Throwable t1) { + providerName = provider.getClass().getName(); + } + + output.append(providerName).append(" is broken").append("\n"); + // ContextProvider is broken + } + } + } + + private static boolean appendAnalyzers(StringBuilder output, Throwable throwable, String messageFormat, + Object[] args) { + boolean analyzerResponsesExist = false; + + // Do a local copy to avoid deadlocks -OLEGSHA + Analyzer[] localAnalyzersCopy = ANALYZERS.toArray(new Analyzer[ANALYZERS.size()]); + + for (Analyzer analyzer : localAnalyzersCopy) { + if (analyzer == null) + continue; + + String answer; + try { + answer = analyzer.analyze(throwable, messageFormat, args); + + if (answer != null && !answer.isEmpty()) { + analyzerResponsesExist = true; + output.append(analyzer.getName()).append(": ").append(answer).append("\n"); + } + } catch (Throwable t) { + analyzerResponsesExist = true; + + output.append("\n"); + + String analyzerName; + + try { + analyzerName = analyzer.getName(); + } catch (Throwable t1) { + analyzerName = analyzer.getClass().getName(); + } + + output.append(analyzerName).append(" is broken").append("\n"); + // Analyzer is broken + } + } + + return analyzerResponsesExist; + } + + private static void appendMessageFormat(StringBuilder output, String messageFormat, Object... arg) { + output.append("Provided description: \n").append(String.format(messageFormat, arg)).append("\n"); + + addSeparator(output); + } + + private static void appendStackTrace(StringBuilder output, Throwable throwable) { + output.append("Stacktrace: \n"); + + if (throwable == null) { + output.append("no Throwable provided").append("\n"); + return; + } + + // Formatting to a human-readable string + Writer sink = new StringBuilderWriter(output); + try { + throwable.printStackTrace(new PrintWriter(sink)); + } catch (Exception e) { + // PLAK + } + output.append("\n"); + } + + private static void export(String report) { + try { + LOGGER.fatal("/n" + report); + } catch (Exception e) { + // PLAK + } + + System.err.println(report); + + generateCrashReportFiles(report); + } + + private static void generateCrashReportFiles(String output) { + Date date = new Date(); + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss"); + + try { + if (!Files.exists(CRASH_REPORTS_PATH)) + Files.createDirectory(CRASH_REPORTS_PATH); + + createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/latest.log"); + createFileForCrashReport(output, + CRASH_REPORTS_PATH.toString() + "/crash-" + dateFormat.format(date) + ".log"); + } catch (Throwable t) { + // Crash Report not created + } + } + + private static void createFileForCrashReport(String buffer, String filename) { + try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8)) { + writer.write(buffer); + } catch (IOException ex) { + // Crash Report not created + } + } + + public static void registerProvider(ContextProvider provider) { + PROVIDERS.add(provider); + } + + public static void registerAnalyzer(Analyzer analyzer) { + ANALYZERS.add(analyzer); + } + + private static void addSeparator(StringBuilder sb) { + sb.append( + // 80 chars + "--------------------------------------------------------------------------------").append("\n"); + } +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketEntityChange.java b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketEntityChange.java index f6c5c8b..1b6d5bb 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/PacketEntityChange.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/PacketEntityChange.java @@ -7,25 +7,26 @@ import java.io.IOException; import ru.windcorp.progressia.common.comms.packets.PacketWorldChange; import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.util.DataBuffer; +import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.world.WorldData; public class PacketEntityChange extends PacketWorldChange { - + private long entityId; private final DataBuffer buffer = new DataBuffer(); public PacketEntityChange() { super("Core", "EntityChange"); } - + public long getEntityId() { return entityId; } - + public void setEntityId(long entityId) { this.entityId = entityId; } - + public DataBuffer getBuffer() { return buffer; } @@ -41,19 +42,15 @@ public class PacketEntityChange extends PacketWorldChange { @Override public void apply(WorldData world) { EntityData entity = world.getEntity(getEntityId()); - + if (entity == null) { - throw new RuntimeException( - "Entity with ID " + getEntityId() + " not found" - ); + CrashReports.report(null, "Entity with ID %d not found", getEntityId()); } - + try { entity.read(getReader(), IOContext.COMMS); } catch (IOException e) { - throw new RuntimeException( - "Entity could not be read", e - ); + CrashReports.report(e, "Entity could not be read"); } } diff --git a/src/main/java/ru/windcorp/progressia/server/world/ImplementedChangeTracker.java b/src/main/java/ru/windcorp/progressia/server/world/ImplementedChangeTracker.java index 70fada1..960f77d 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ImplementedChangeTracker.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ImplementedChangeTracker.java @@ -11,6 +11,7 @@ import ru.windcorp.progressia.common.comms.packets.PacketWorldChange; import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.util.LowOverheadCache; import ru.windcorp.progressia.common.util.Vectors; +import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.block.BlockData; @@ -21,50 +22,50 @@ import ru.windcorp.progressia.common.world.tile.TileData; import ru.windcorp.progressia.server.Server; public class ImplementedChangeTracker implements Changer { - + public static interface ChangeImplementation { void applyOnServer(WorldData world); Packet asPacket(); } - + private static class SetBlock extends PacketWorldChange implements ChangeImplementation { private final Vec3i position = new Vec3i(); private BlockData block; - + public SetBlock() { super("Core", "SetBlock"); } - + public void initialize(Vec3i position, BlockData block) { this.position.set(position.x, position.y, position.z); this.block = block; } - + @Override public void applyOnServer(WorldData world) { Vec3i blockInChunk = Vectors.grab3i(); Coordinates.convertInWorldToInChunk(position, blockInChunk); - + world.getChunkByBlock(position).setBlock(blockInChunk, block); - + Vectors.release(blockInChunk); } - + @Override public void apply(WorldData world) { applyOnServer(world); } - + @Override public Packet asPacket() { return this; } - + } - + private static class AddOrRemoveTile extends PacketWorldChange implements ChangeImplementation { @@ -72,13 +73,13 @@ public class ImplementedChangeTracker implements Changer { private final Vec3i position = new Vec3i(); private BlockFace face; private TileData tile; - + private boolean shouldAdd; - + public AddOrRemoveTile() { super("Core", "AddOrRemoveTile"); } - + public void initialize( Vec3i position, BlockFace face, TileData tile, @@ -89,52 +90,51 @@ public class ImplementedChangeTracker implements Changer { this.tile = tile; this.shouldAdd = shouldAdd; } - + @Override public void applyOnServer(WorldData world) { Vec3i blockInChunk = Vectors.grab3i(); Coordinates.convertInWorldToInChunk(position, blockInChunk); - - List tiles = world.getChunkByBlock(position) - .getTiles(blockInChunk, face); - + + List tiles = world.getChunkByBlock(position).getTiles(blockInChunk, face); + if (shouldAdd) { tiles.add(tile); } else { tiles.remove(tile); } - + Vectors.release(blockInChunk); } - + @Override public void apply(WorldData world) { applyOnServer(world); } - + @Override public Packet asPacket() { return this; } - + } - + private static class ChangeEntity implements ChangeImplementation { - + private EntityData entity; private Change change; - + private final PacketEntityChange packet = new PacketEntityChange(); public void set(T entity, Change change) { this.entity = entity; this.change = change; - + packet.setEntityId(entity.getEntityId()); try { entity.write(packet.getWriter(), IOContext.COMMS); } catch (IOException e) { - throw new RuntimeException(e); + CrashReports.report(e, "__DOC__ME__"); } } @@ -142,11 +142,11 @@ public class ImplementedChangeTracker implements Changer { @Override public void applyOnServer(WorldData world) { ((Change) change).change(entity); - + try { entity.write(packet.getWriter(), IOContext.COMMS); } catch (IOException e) { - throw new RuntimeException("Entity could not be written", e); + CrashReports.report(e, "Entity could not be written"); } } @@ -154,11 +154,11 @@ public class ImplementedChangeTracker implements Changer { public Packet asPacket() { return packet; } - + } private final List changes = new ArrayList<>(1024); - + private final LowOverheadCache setBlockCache = new LowOverheadCache<>(SetBlock::new); @@ -174,21 +174,21 @@ public class ImplementedChangeTracker implements Changer { change.initialize(pos, block); changes.add(change); } - + @Override public void addTile(Vec3i block, BlockFace face, TileData tile) { AddOrRemoveTile change = addOrRemoveTileCache.grab(); change.initialize(block, face, tile, true); changes.add(change); } - + @Override public void removeTile(Vec3i block, BlockFace face, TileData tile) { AddOrRemoveTile change = addOrRemoveTileCache.grab(); change.initialize(block, face, tile, false); changes.add(change); } - + @Override public void changeEntity( T entity, Change change @@ -197,7 +197,7 @@ public class ImplementedChangeTracker implements Changer { changeRecord.set(entity, change); changes.add(changeRecord); } - + public void applyChanges(Server server) { changes.forEach(c -> c.applyOnServer(server.getWorld().getData())); changes.stream().map(ChangeImplementation::asPacket).filter(Objects::nonNull).forEach( @@ -206,7 +206,7 @@ public class ImplementedChangeTracker implements Changer { changes.forEach(this::release); changes.clear(); } - + private void release(ChangeImplementation c) { if (c instanceof SetBlock) { setBlockCache.release((SetBlock) c); From ec6181aaa83972acc786b61b6ae485e1667b3353 Mon Sep 17 00:00:00 2001 From: serega404 Date: Sun, 15 Nov 2020 23:11:46 +0300 Subject: [PATCH 08/10] Crash reports handle invalid format strings properly --- .../common/util/crash/CrashReports.java | 310 ++++++++++-------- 1 file changed, 165 insertions(+), 145 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java index ce4cdee..f6dd3d2 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/CrashReports.java @@ -20,193 +20,213 @@ import java.util.*; public class CrashReports { - private CrashReports() { - } + private CrashReports() { + } - private static final Path CRASH_REPORTS_PATH = Paths.get("crash-reports"); + private static final Path CRASH_REPORTS_PATH = Paths.get("crash-reports"); - private static final Collection PROVIDERS = Collections.synchronizedCollection(new ArrayList<>()); + private static final Collection PROVIDERS = Collections.synchronizedCollection(new ArrayList<>()); - private static final Collection ANALYZERS = Collections.synchronizedCollection(new ArrayList<>()); + private static final Collection ANALYZERS = Collections.synchronizedCollection(new ArrayList<>()); - private static final Logger LOGGER = LogManager.getLogger("crash"); + private static final Logger LOGGER = LogManager.getLogger("crash"); - /** - * This method never returns. - *

- * TODO document - * - * @param throwable - * @param messageFormat - * @param args - */ - public static void report(Throwable throwable, String messageFormat, Object... args) { - StringBuilder output = new StringBuilder(); + /** + * This method never returns. + *

+ * TODO document + * + * @param throwable + * @param messageFormat + * @param args + */ + public static void report(Throwable throwable, String messageFormat, Object... args) { + StringBuilder output = new StringBuilder(); - appendContextProviders(output); - addSeparator(output); - if (appendAnalyzers(output, throwable, messageFormat, args)) { - addSeparator(output); - } + try { + String.format(messageFormat, args); + } catch (IllegalFormatException e) { + messageFormat = StringUtil.replaceAll(messageFormat, "%", "%%"); - appendMessageFormat(output, messageFormat, args); + if (args.length != 0) { + messageFormat += "\nArgs:"; + for (Object arg : args) { + try { + messageFormat += " \"" + arg.toString() + "\""; + } catch (Throwable t) { + messageFormat += " exc: \"" + t.getClass().toString() + "\""; + } + } + args = new Object[0]; // clear args + } - appendStackTrace(output, throwable); + messageFormat += "\nCould not format provided description"; + } - export(output.toString()); + appendContextProviders(output); + addSeparator(output); + if (appendAnalyzers(output, throwable, messageFormat, args)) { + addSeparator(output); + } - System.exit(0); - } + appendMessageFormat(output, messageFormat, args); - private static void appendContextProviders(StringBuilder output) { + appendStackTrace(output, throwable); - // Do a local copy to avoid deadlocks -OLEGSHA - ContextProvider[] localProvidersCopy = PROVIDERS.toArray(new ContextProvider[PROVIDERS.size()]); + export(output.toString()); - for (ContextProvider provider : localProvidersCopy) { - if (provider == null) - continue; + System.exit(0); + } - addSeparator(output); + private static void appendContextProviders(StringBuilder output) { - try { - Map buf = new HashMap<>(); - provider.provideContext(buf); + // Do a local copy to avoid deadlocks -OLEGSHA + ContextProvider[] localProvidersCopy = PROVIDERS.toArray(new ContextProvider[PROVIDERS.size()]); - if (!buf.isEmpty()) { - output.append("Provider name: ").append(provider.getName()).append("\n"); - for (Map.Entry entry : buf.entrySet()) { - output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); - } - } - } catch (Throwable t) { - output.append("\n"); + for (ContextProvider provider : localProvidersCopy) { + if (provider == null) + continue; - String providerName; + addSeparator(output); - try { - providerName = provider.getName(); - } catch (Throwable t1) { - providerName = provider.getClass().getName(); - } + try { + Map buf = new HashMap<>(); + provider.provideContext(buf); - output.append(providerName).append(" is broken").append("\n"); - // ContextProvider is broken - } - } - } + if (!buf.isEmpty()) { + output.append("Provider name: ").append(provider.getName()).append("\n"); + for (Map.Entry entry : buf.entrySet()) { + output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); + } + } + } catch (Throwable t) { + output.append("\n"); - private static boolean appendAnalyzers(StringBuilder output, Throwable throwable, String messageFormat, - Object[] args) { - boolean analyzerResponsesExist = false; + String providerName; - // Do a local copy to avoid deadlocks -OLEGSHA - Analyzer[] localAnalyzersCopy = ANALYZERS.toArray(new Analyzer[ANALYZERS.size()]); + try { + providerName = provider.getName(); + } catch (Throwable t1) { + providerName = provider.getClass().getName(); + } - for (Analyzer analyzer : localAnalyzersCopy) { - if (analyzer == null) - continue; + output.append(providerName).append(" is broken").append("\n"); + // ContextProvider is broken + } + } + } - String answer; - try { - answer = analyzer.analyze(throwable, messageFormat, args); + private static boolean appendAnalyzers(StringBuilder output, Throwable throwable, String messageFormat, + Object[] args) { + boolean analyzerResponsesExist = false; - if (answer != null && !answer.isEmpty()) { - analyzerResponsesExist = true; - output.append(analyzer.getName()).append(": ").append(answer).append("\n"); - } - } catch (Throwable t) { - analyzerResponsesExist = true; + // Do a local copy to avoid deadlocks -OLEGSHA + Analyzer[] localAnalyzersCopy = ANALYZERS.toArray(new Analyzer[ANALYZERS.size()]); - output.append("\n"); + for (Analyzer analyzer : localAnalyzersCopy) { + if (analyzer == null) + continue; - String analyzerName; + String answer; + try { + answer = analyzer.analyze(throwable, messageFormat, args); - try { - analyzerName = analyzer.getName(); - } catch (Throwable t1) { - analyzerName = analyzer.getClass().getName(); - } + if (answer != null && !answer.isEmpty()) { + analyzerResponsesExist = true; + output.append(analyzer.getName()).append(": ").append(answer).append("\n"); + } + } catch (Throwable t) { + analyzerResponsesExist = true; - output.append(analyzerName).append(" is broken").append("\n"); - // Analyzer is broken - } - } + output.append("\n"); - return analyzerResponsesExist; - } + String analyzerName; - private static void appendMessageFormat(StringBuilder output, String messageFormat, Object... arg) { - output.append("Provided description: \n").append(String.format(messageFormat, arg)).append("\n"); + try { + analyzerName = analyzer.getName(); + } catch (Throwable t1) { + analyzerName = analyzer.getClass().getName(); + } - addSeparator(output); - } + output.append(analyzerName).append(" is broken").append("\n"); + // Analyzer is broken + } + } - private static void appendStackTrace(StringBuilder output, Throwable throwable) { - output.append("Stacktrace: \n"); + return analyzerResponsesExist; + } - if (throwable == null) { - output.append("no Throwable provided").append("\n"); - return; - } + private static void appendMessageFormat(StringBuilder output, String messageFormat, Object... arg) { + output.append("Provided description: \n").append(String.format(messageFormat, arg)).append("\n"); - // Formatting to a human-readable string - Writer sink = new StringBuilderWriter(output); - try { - throwable.printStackTrace(new PrintWriter(sink)); - } catch (Exception e) { - // PLAK - } - output.append("\n"); - } + addSeparator(output); + } - private static void export(String report) { - try { - LOGGER.fatal("/n" + report); - } catch (Exception e) { - // PLAK - } + private static void appendStackTrace(StringBuilder output, Throwable throwable) { + output.append("Stacktrace: \n"); - System.err.println(report); + if (throwable == null) { + output.append("no Throwable provided").append("\n"); + return; + } - generateCrashReportFiles(report); - } + // Formatting to a human-readable string + Writer sink = new StringBuilderWriter(output); + try { + throwable.printStackTrace(new PrintWriter(sink)); + } catch (Exception e) { + // PLAK + } + output.append("\n"); + } - private static void generateCrashReportFiles(String output) { - Date date = new Date(); - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss"); + private static void export(String report) { + try { + LOGGER.fatal("/n" + report); + } catch (Exception e) { + // PLAK + } - try { - if (!Files.exists(CRASH_REPORTS_PATH)) - Files.createDirectory(CRASH_REPORTS_PATH); + System.err.println(report); - createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/latest.log"); - createFileForCrashReport(output, - CRASH_REPORTS_PATH.toString() + "/crash-" + dateFormat.format(date) + ".log"); - } catch (Throwable t) { - // Crash Report not created - } - } + generateCrashReportFiles(report); + } - private static void createFileForCrashReport(String buffer, String filename) { - try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8)) { - writer.write(buffer); - } catch (IOException ex) { - // Crash Report not created - } - } + private static void generateCrashReportFiles(String output) { + Date date = new Date(); + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss"); - public static void registerProvider(ContextProvider provider) { - PROVIDERS.add(provider); - } + try { + if (!Files.exists(CRASH_REPORTS_PATH)) + Files.createDirectory(CRASH_REPORTS_PATH); - public static void registerAnalyzer(Analyzer analyzer) { - ANALYZERS.add(analyzer); - } + createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/latest.log"); + createFileForCrashReport(output, + CRASH_REPORTS_PATH.toString() + "/crash-" + dateFormat.format(date) + ".log"); + } catch (Throwable t) { + // Crash Report not created + } + } - private static void addSeparator(StringBuilder sb) { - sb.append( - // 80 chars - "--------------------------------------------------------------------------------").append("\n"); - } + private static void createFileForCrashReport(String buffer, String filename) { + try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8)) { + writer.write(buffer); + } catch (IOException ex) { + // Crash Report not created + } + } + + public static void registerProvider(ContextProvider provider) { + PROVIDERS.add(provider); + } + + public static void registerAnalyzer(Analyzer analyzer) { + ANALYZERS.add(analyzer); + } + + private static void addSeparator(StringBuilder sb) { + sb.append( + // 80 chars + "--------------------------------------------------------------------------------").append("\n"); + } } From 996a244649d269db82f8789ea2c215baec51d9f1 Mon Sep 17 00:00:00 2001 From: serega404 Date: Thu, 19 Nov 2020 18:27:44 +0300 Subject: [PATCH 09/10] Added uncaught exception handler --- .../ru/windcorp/progressia/ProgressiaLauncher.java | 13 +++++++++++++ .../progressia/client/ProgressiaClientMain.java | 12 ------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index d42217b..f9dbaba 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -17,10 +17,23 @@ *******************************************************************************/ package ru.windcorp.progressia; +import ru.windcorp.progressia.common.util.crash.CrashReports; +import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; +import ru.windcorp.progressia.common.util.crash.providers.OSContextProvider; + public class ProgressiaLauncher { public static void launch(String[] args, Proxy proxy) { + setupCrashReports(); proxy.initialize(); } + private static void setupCrashReports() { + CrashReports.registerProvider(new OSContextProvider()); + CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer()); + Thread.setDefaultUncaughtExceptionHandler((Thread thread, Throwable t)-> { + CrashReports.report(t,"Uncaught exception in thread %s", thread.getName()); + }); + } + } diff --git a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java index 0b755f0..0ab1bd0 100644 --- a/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java +++ b/src/main/java/ru/windcorp/progressia/client/ProgressiaClientMain.java @@ -20,9 +20,6 @@ package ru.windcorp.progressia.client; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ru.windcorp.progressia.ProgressiaLauncher; -import ru.windcorp.progressia.common.util.crash.CrashReports; -import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; -import ru.windcorp.progressia.common.util.crash.providers.OSContextProvider; public class ProgressiaClientMain { @@ -31,15 +28,6 @@ public class ProgressiaClientMain { public static void main(String[] args) { logger.info("App started!"); - CrashReports.registerProvider(new OSContextProvider()); - CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer()); - try { - @SuppressWarnings("unused") - long[] ssdss = new long[1 << 30]; - } catch (Throwable t) { - CrashReports.report(t, "u %s stupid", "vry"); - } - ProgressiaLauncher.launch(args, new ClientProxy()); } From afa1234ddd48fae6fe107ba37a1493a165cf251f Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Thu, 19 Nov 2020 18:59:41 +0300 Subject: [PATCH 10/10] Fixed English in messages --- .../comms/DefaultClientCommsListener.java | 8 ++- .../graphics/backend/shaders/Program.java | 2 +- .../backend/shaders/attributes/Attribute.java | 2 +- .../backend/shaders/uniforms/Uniform.java | 2 +- .../graphics/font/GNUUnifontLoader.java | 56 ++++++++++--------- .../client/graphics/gui/Component.java | 10 ++-- .../client/graphics/texture/Atlases.java | 4 +- .../graphics/texture/SimpleTextures.java | 2 +- .../graphics/texture/TexturePrimitive.java | 2 +- .../client/localization/Parser.java | 2 +- .../world/entity/EntityRenderRegistry.java | 2 +- .../progressia/common/resource/Resource.java | 4 +- .../world/ImplementedChangeTracker.java | 4 +- 13 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java b/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java index b2c7051..4053672 100644 --- a/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java +++ b/src/main/java/ru/windcorp/progressia/client/comms/DefaultClientCommsListener.java @@ -1,6 +1,8 @@ package ru.windcorp.progressia.client.comms; import java.io.IOException; + +import ru.windcorp.jputil.chars.StringUtil; import ru.windcorp.progressia.client.Client; import ru.windcorp.progressia.client.graphics.world.EntityAnchor; import ru.windcorp.progressia.client.world.ChunkRender; @@ -42,7 +44,11 @@ public class DefaultClientCommsListener implements CommsListener { ); if (entity == null) { - CrashReports.report(null, "Player entity not found"); + CrashReports.report( + null, + "Player entity with ID %s not found", + new String(StringUtil.toFullHex(packet.getLocalPlayerEntityId())) + ); } getClient().setLocalPlayer(entity); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java index 64c54bc..2b63885 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/Program.java @@ -40,7 +40,7 @@ public class Program implements OpenGLDeletable { glLinkProgram(handle); if (glGetProgrami(handle, GL_LINK_STATUS) == GL_FALSE) { - CrashReports.report(null, "Bad program:\n %s", glGetProgramInfoLog(handle)); + CrashReports.report(null, "Bad program:\n%s", glGetProgramInfoLog(handle)); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java index 34624f4..9075085 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/attributes/Attribute.java @@ -27,7 +27,7 @@ public class Attribute { public Attribute(int handle, Program program) { if (handle < 0) { - CrashReports.report(null, "Bad handle: %s", handle); + CrashReports.report(null, "Bad handle: %d", handle); } this.handle = handle; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java index d1475b0..996b1fe 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/shaders/uniforms/Uniform.java @@ -27,7 +27,7 @@ public class Uniform { public Uniform(int handle, Program program) { if (handle < 0) { - CrashReports.report(null, "Bad handle: %s", handle); + CrashReports.report(null, "Bad handle: %d", handle); } this.handle = handle; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java index 61e9666..72f359c 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/GNUUnifontLoader.java @@ -57,7 +57,7 @@ public class GNUUnifontLoader { return createStream(reader).map(GNUUnifontLoader::parse).map(GNUUnifontLoader::addToAtlas) .collect(Collectors.collectingAndThen(createMapper(), GNUUnifont::new)); } catch (IOException | UncheckedIOException e) { - CrashReports.report(e, "Problem with load GNUUnifont"); + CrashReports.report(e, "Could not load GNUUnifont"); return null; } } @@ -72,23 +72,30 @@ public class GNUUnifontLoader { } private static ParsedGlyph parse(String declar) { - int width = getWidth(declar); - checkDeclaration(declar, width); - - char c = getChar(declar); - - TextureDataEditor editor = new TextureDataEditor(width, GNUUnifont.HEIGHT, width, GNUUnifont.HEIGHT, - TEXTURE_SETTINGS); - - for (int y = 0; y < GNUUnifont.HEIGHT; ++y) { - for (int x = 0; x < width; ++x) { - int bit = x + y * width; - - editor.setPixel(x, GNUUnifont.HEIGHT - y - 1, getBit(declar, bit) ? 0xFFFFFFFF : 0x00000000); + try { + + int width = getWidth(declar); + checkDeclaration(declar, width); + + char c = getChar(declar); + + TextureDataEditor editor = new TextureDataEditor(width, GNUUnifont.HEIGHT, width, GNUUnifont.HEIGHT, + TEXTURE_SETTINGS); + + for (int y = 0; y < GNUUnifont.HEIGHT; ++y) { + for (int x = 0; x < width; ++x) { + int bit = x + y * width; + + editor.setPixel(x, GNUUnifont.HEIGHT - y - 1, getBit(declar, bit) ? 0xFFFFFFFF : 0x00000000); + } } + + return new ParsedGlyph(c, editor); + + } catch (IOException e) { + CrashReports.report(e, "Could not load GNUUnifont: could not load character \"%s\"", declar); + return null; } - - return new ParsedGlyph(c, editor); } private static char getChar(String declar) { @@ -117,26 +124,25 @@ public class GNUUnifontLoader { return meaningfulChars / charsPerColumn; } - private static void checkDeclaration(String declar, int width) { + private static void checkDeclaration(String declar, int width) throws IOException { if (!GNUUnifont.WIDTHS.contains(width)) { - CrashReports.report(null, "Width %d is not supported (in declar \"%s\")", width, declar); + throw new IOException("Width " + width + " is not supported (in declar \"" + declar + "\")"); } - + if ((declar.length() - PREFIX_LENGTH) % width != 0) { - CrashReports.report(null, "Declar \"%s\" has invalid length", declar); + throw new IOException("Declar \"" + declar + "\" has invalid length"); } - + for (int i = 0; i < declar.length(); ++i) { if (i == BITS_PER_HEX_DIGIT) { if (declar.charAt(i) != ':') { - CrashReports.report(null, "No colon ':' found in declar \"%s\" at index 4", declar); + throw new IOException("No colon ':' found in declar \"" + declar + "\" at index 4"); } } else { char c = declar.charAt(i); - + if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))) { - CrashReports.report(null, - "Illegal char in declar \"%s\" at index " + i + "; expected 0-9A-F", declar); + throw new IOException("Illegal char in declar \"" + declar + "\" at index " + i + "; expected 0-9A-F"); } } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java index 7ba1b83..1a1b1f4 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -235,7 +235,7 @@ public class Component extends Named { valid = true; } catch (Exception e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Could not layout Component %s", this); } } @@ -248,7 +248,7 @@ public class Component extends Named { try { return getLayout().calculatePreferredSize(this); } catch (Exception e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Could not calculate preferred size for Component %s", this); } } @@ -517,7 +517,7 @@ public class Component extends Named { break; } } catch (Exception e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Could not dispatch input to Component %s", this); } } @@ -609,7 +609,7 @@ public class Component extends Named { try { assembleSelf(target); } catch (Exception e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Could not assemble Component %s", this); } assembleChildren(target); @@ -617,7 +617,7 @@ public class Component extends Named { try { postAssembleSelf(target); } catch (Exception e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Post-assembly failed for Component %s", this); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java index a945f03..0ce64d4 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/Atlases.java @@ -157,7 +157,7 @@ public class Atlases { return loadSprite(data.getData(), group); } catch (IOException e) { - CrashReports.report(e, "Problem with load atlases sprite"); + CrashReports.report(e, "Could not load sprite %s into atlas group %s", resource, group); return null; } } @@ -174,7 +174,7 @@ public class Atlases { Atlas newAtlas = new Atlas(group); if (!newAtlas.canAddSprite(data)) { - CrashReports.report(null, "Could not fit tex into atlas of size %d", newAtlas.getSize()); + CrashReports.report(null, "Could not fit texture into atlas of size %d", newAtlas.getSize()); } atlases.add(newAtlas); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java index e0711db..51a1235 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/SimpleTextures.java @@ -31,7 +31,7 @@ public class SimpleTextures { new Sprite(new TexturePrimitive(data.getData())) ); } catch (IOException e) { - CrashReports.report(e, "Problem with load texture"); + CrashReports.report(e, "Could not load texture %s", resource); return null; } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java index e4f5fdc..b4df4fb 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java @@ -90,7 +90,7 @@ public class TexturePrimitive implements OpenGLDeletable { OpenGLObjectTracker.register(this); if (handle < 0) { - CrashReports.report(null, "Failed to create texture"); + CrashReports.report(null, "Failed to allocate texture"); } } diff --git a/src/main/java/ru/windcorp/progressia/client/localization/Parser.java b/src/main/java/ru/windcorp/progressia/client/localization/Parser.java index c0438d5..239c779 100644 --- a/src/main/java/ru/windcorp/progressia/client/localization/Parser.java +++ b/src/main/java/ru/windcorp/progressia/client/localization/Parser.java @@ -81,7 +81,7 @@ public class Parser { } } catch (IOException | EscapeException e) { - CrashReports.report(e, "Problems with parsing"); + CrashReports.report(e, "Could not parse language file %s", filePath); return null; } return parsedData; diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java index 1e33fd3..ad0c161 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/EntityRenderRegistry.java @@ -29,7 +29,7 @@ public class EntityRenderRegistry extends NamespacedRegistry { ).getData() ); } catch (IOException e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Could not load entity texture %s", name); return null; } } diff --git a/src/main/java/ru/windcorp/progressia/common/resource/Resource.java b/src/main/java/ru/windcorp/progressia/common/resource/Resource.java index d2e42ea..43b1839 100644 --- a/src/main/java/ru/windcorp/progressia/common/resource/Resource.java +++ b/src/main/java/ru/windcorp/progressia/common/resource/Resource.java @@ -51,7 +51,7 @@ public class Resource extends Named { try (Reader reader = getReader()) { return CharStreams.toString(reader); } catch (IOException e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Could not read resource %s as text", this); return null; } } @@ -61,7 +61,7 @@ public class Resource extends Named { try (InputStream stream = getInputStream()) { byteArray = ByteStreams.toByteArray(stream); } catch (IOException e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Could not read resource %s as bytes", this); return null; } diff --git a/src/main/java/ru/windcorp/progressia/server/world/ImplementedChangeTracker.java b/src/main/java/ru/windcorp/progressia/server/world/ImplementedChangeTracker.java index 960f77d..f277cb1 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/ImplementedChangeTracker.java +++ b/src/main/java/ru/windcorp/progressia/server/world/ImplementedChangeTracker.java @@ -134,7 +134,7 @@ public class ImplementedChangeTracker implements Changer { try { entity.write(packet.getWriter(), IOContext.COMMS); } catch (IOException e) { - CrashReports.report(e, "__DOC__ME__"); + CrashReports.report(e, "Could not write entity %s", entity); } } @@ -146,7 +146,7 @@ public class ImplementedChangeTracker implements Changer { try { entity.write(packet.getWriter(), IOContext.COMMS); } catch (IOException e) { - CrashReports.report(e, "Entity could not be written"); + CrashReports.report(e, "Could not write entity %s", entity); } }