Merge pull request #288 from toolbox4minecraft/reworked-logging

Reworked logging
master
Stefan Dollase 2016-11-21 05:17:27 +01:00 committed by GitHub
commit ecb8b9e495
55 changed files with 744 additions and 587 deletions

View File

@ -5,7 +5,6 @@ import java.sql.Timestamp;
import java.util.Date;
import java.util.prefs.Preferences;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.kohsuke.args4j.CmdLineException;
@ -17,8 +16,9 @@ import amidst.documentation.CalledByAny;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.gui.crash.CrashWindow;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.logging.FileLogger;
import amidst.logging.Log;
import amidst.mojangapi.file.DotMinecraftDirectoryNotFoundException;
import amidst.util.OperatingSystemDetector;
@ -76,7 +76,7 @@ public class Amidst {
} else if (parameters.printVersion) {
System.out.println(versionString);
} else {
Log.i(versionString);
AmidstLogger.info(versionString);
logTimeAndProperties();
enableGraphicsAcceleration();
startApplication(parameters, metadata, createSettings());
@ -85,19 +85,19 @@ public class Amidst {
private static void initFileLogger(String filename) {
if (filename != null) {
Log.i("using log file: '" + filename + "'");
Log.addListener("file", new FileLogger(new File(filename)));
AmidstLogger.info("using log file: '" + filename + "'");
AmidstLogger.addListener("file", new FileLogger(new File(filename)));
}
}
private static void logTimeAndProperties() {
Log.i("Current system time: " + getCurrentTimeStamp());
Log.i(createPropertyString("os.name"));
Log.i(createPropertyString("os.version"));
Log.i(createPropertyString("os.arch"));
Log.i(createPropertyString("java.version"));
Log.i(createPropertyString("java.vendor"));
Log.i(createPropertyString("sun.arch.data.model"));
AmidstLogger.info("Current system time: " + getCurrentTimeStamp());
AmidstLogger.info(createPropertyString("os.name"));
AmidstLogger.info(createPropertyString("os.version"));
AmidstLogger.info(createPropertyString("os.arch"));
AmidstLogger.info(createPropertyString("java.version"));
AmidstLogger.info(createPropertyString("java.vendor"));
AmidstLogger.info(createPropertyString("sun.arch.data.model"));
}
private static String getCurrentTimeStamp() {
@ -144,10 +144,10 @@ public class Amidst {
*/
private static void enableOpenGLIfNecessary() {
if (OperatingSystemDetector.isMac()) {
Log.i("Enabling OpenGL.");
AmidstLogger.info("Enabling OpenGL.");
System.setProperty("sun.java2d.opengl", "True");
} else {
Log.i("Not using OpenGL.");
AmidstLogger.info("Not using OpenGL.");
}
}
@ -170,13 +170,10 @@ public class Amidst {
try {
new Application(parameters, metadata, settings).run();
} catch (DotMinecraftDirectoryNotFoundException e) {
Log.w(e.getMessage());
e.printStackTrace();
JOptionPane.showMessageDialog(
null,
"Amidst is not able to find your '.minecraft' directory, but it requires a working Minecraft installation.",
AmidstLogger.warn(e);
AmidstMessageBox.displayError(
"Please install Minecraft",
JOptionPane.ERROR_MESSAGE);
"Amidst is not able to find your '.minecraft' directory, but it requires a working Minecraft installation.");
} catch (Exception e) {
handleCrash(e, Thread.currentThread());
}
@ -186,21 +183,12 @@ public class Amidst {
private static void handleCrash(Throwable e, Thread thread) {
String message = "Amidst has encounted an uncaught exception on the thread " + thread;
try {
Log.crash(e, message);
displayCrashWindow(message, Log.getAllMessages());
AmidstLogger.crash(e, message);
CrashWindow.showAfterCrash();
} catch (Throwable t) {
System.err.println("Amidst crashed!");
System.err.println(message);
e.printStackTrace();
}
}
private static void displayCrashWindow(final String message, final String allMessages) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
CrashWindow.show(message, allMessages, () -> System.exit(4));
}
});
}
}

View File

@ -17,7 +17,7 @@ import amidst.clazz.symbolic.SymbolicClasses;
import amidst.clazz.symbolic.declaration.SymbolicClassDeclaration;
import amidst.clazz.translator.ClassTranslator;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
@Immutable
public enum Classes {
@ -31,39 +31,38 @@ public enum Classes {
JarFileParsingException,
SymbolicClassGraphCreationException,
ClassNotFoundException {
Log.i("Reading " + jarFile.getName());
AmidstLogger.info("Reading " + jarFile.getName());
List<RealClass> realClasses = RealClasses.fromJarFile(jarFile);
Log.i("Jar load complete.");
Log.i("Searching for classes...");
AmidstLogger.info("Jar load complete.");
AmidstLogger.info("Searching for classes...");
Map<SymbolicClassDeclaration, String> realClassNamesBySymbolicClassDeclaration = translator
.translate(realClasses);
Log.i("Class search complete.");
Log.i("Loading classes...");
AmidstLogger.info("Class search complete.");
AmidstLogger.info("Loading classes...");
Map<String, SymbolicClass> result = SymbolicClasses.from(realClassNamesBySymbolicClassDeclaration, classLoader);
Log.i("Classes loaded.");
AmidstLogger.info("Classes loaded.");
return result;
}
public static Map<SymbolicClassDeclaration, Integer> countMatches(File jarFile, ClassTranslator translator)
throws FileNotFoundException,
JarFileParsingException {
Log.i("Checking " + jarFile.getName());
AmidstLogger.info("Checking " + jarFile.getName());
List<RealClass> realClasses = RealClasses.fromJarFile(jarFile);
Map<SymbolicClassDeclaration, List<RealClass>> map = translator.translateToAllMatching(realClasses);
Map<SymbolicClassDeclaration, Integer> result = new HashMap<>();
for (Entry<SymbolicClassDeclaration, List<RealClass>> entry : map.entrySet()) {
result.put(entry.getKey(), entry.getValue().size());
if (entry.getValue().isEmpty()) {
Log.w(entry.getKey().getSymbolicClassName() + " has no matching class");
AmidstLogger.warn(entry.getKey().getSymbolicClassName() + " has no matching class");
} else if (entry.getValue().size() > 1) {
StringBuilder builder = new StringBuilder();
for (RealClass realClass : entry.getValue()) {
builder.append(", ").append(realClass.getRealClassName());
}
Log
.w(
entry.getKey().getSymbolicClassName() + " has multiple matching classes: "
+ builder.toString().substring(2));
AmidstLogger.warn(
entry.getKey().getSymbolicClassName() + " has multiple matching classes: "
+ builder.toString().substring(2));
}
}
return result;

View File

@ -5,7 +5,7 @@ import java.util.List;
import amidst.clazz.symbolic.SymbolicClassGraphCreationException;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
@Immutable
public class SymbolicClassDeclaration {
@ -49,16 +49,17 @@ public class SymbolicClassDeclaration {
}
public void handleMultipleMatches(String firstRealClassName, String otherRealClassName) {
Log.w("Found class " + symbolicClassName + " again: " + firstRealClassName + ", " + otherRealClassName);
AmidstLogger
.warn("Found class " + symbolicClassName + " again: " + firstRealClassName + ", " + otherRealClassName);
}
public void handleMatch(String realClassName) {
Log.i("Found class " + symbolicClassName + ": " + realClassName);
AmidstLogger.info("Found class " + symbolicClassName + ": " + realClassName);
}
public void handleNoMatch() throws ClassNotFoundException {
if (isOptional) {
Log.i("Missing class " + symbolicClassName);
AmidstLogger.info("Missing class " + symbolicClassName);
} else {
throw new ClassNotFoundException(
"cannot find a real class matching the symbolic class " + symbolicClassName);
@ -69,7 +70,7 @@ public class SymbolicClassDeclaration {
throws SymbolicClassGraphCreationException {
String message = "unable to find the real class " + realClassName + " -> " + symbolicClassName;
if (isOptional) {
Log.i(message);
AmidstLogger.info(message);
} else {
throw new SymbolicClassGraphCreationException(message, e);
}

View File

@ -2,7 +2,7 @@ package amidst.clazz.symbolic.declaration;
import amidst.clazz.symbolic.SymbolicClassGraphCreationException;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
@Immutable
public class SymbolicConstructorDeclaration {
@ -36,7 +36,7 @@ public class SymbolicConstructorDeclaration {
String message = "unable to find the real class constructor " + realClassName + ".<init>"
+ parameters.getParameterString() + " -> " + symbolicClassName + "." + symbolicName;
if (isOptional) {
Log.i(message);
AmidstLogger.info(message);
} else {
throw new SymbolicClassGraphCreationException(message, e);
}

View File

@ -2,7 +2,7 @@ package amidst.clazz.symbolic.declaration;
import amidst.clazz.symbolic.SymbolicClassGraphCreationException;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
@Immutable
public class SymbolicFieldDeclaration {
@ -33,7 +33,7 @@ public class SymbolicFieldDeclaration {
String message = "unable to find the real class field " + realClassName + "." + realName + " -> "
+ symbolicClassName + "." + symbolicName;
if (isOptional) {
Log.i(message);
AmidstLogger.info(message);
} else {
throw new SymbolicClassGraphCreationException(message, e);
}

View File

@ -2,7 +2,7 @@ package amidst.clazz.symbolic.declaration;
import amidst.clazz.symbolic.SymbolicClassGraphCreationException;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
@Immutable
public class SymbolicMethodDeclaration {
@ -43,7 +43,7 @@ public class SymbolicMethodDeclaration {
String message = "unable to find the real class method " + realClassName + "." + realName
+ parameters.getParameterString() + " -> " + symbolicClassName + "." + symbolicName;
if (isOptional) {
Log.i(message);
AmidstLogger.info(message);
} else {
throw new SymbolicClassGraphCreationException(message, e);
}

View File

@ -8,7 +8,7 @@ import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.ThreadSafe;
import amidst.fragment.constructor.FragmentConstructor;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
@ThreadSafe
public class FragmentCache {
@ -36,12 +36,11 @@ public class FragmentCache {
@CalledOnlyBy(AmidstThread.EDT)
public synchronized void increaseSize() {
Log
.i(
"increasing fragment cache size from " + cache.size() + " to "
+ (cache.size() + NEW_FRAGMENTS_PER_REQUEST));
AmidstLogger.info(
"increasing fragment cache size from " + cache.size() + " to "
+ (cache.size() + NEW_FRAGMENTS_PER_REQUEST));
requestNewFragments();
Log.i("fragment cache size increased to " + cache.size());
AmidstLogger.info("fragment cache size increased to " + cache.size());
}
@CalledOnlyBy(AmidstThread.EDT)

View File

@ -2,7 +2,7 @@ package amidst.fragment.colorprovider;
import amidst.documentation.ThreadSafe;
import amidst.fragment.Fragment;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.world.Dimension;
import amidst.mojangapi.world.biome.BiomeColor;
@ -23,7 +23,7 @@ public class BackgroundColorProvider implements ColorProvider {
} else if (dimension.equals(Dimension.END)) {
return theEndColorProvider.getColorAt(dimension, fragment, cornerX, cornerY, x, y);
} else {
Log.w("unsupported dimension");
AmidstLogger.warn("unsupported dimension");
return BiomeColor.unknown().getRGB();
}
}

View File

@ -11,37 +11,54 @@ import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.logging.AmidstLogger;
import net.miginfocom.swing.MigLayout;
@NotThreadSafe
public enum CrashWindow {
INSTANCE;
CRASHING("Amidst crashed!", true, () -> {
System.exit(4);
}),
INTEREST("Log Messages", false, () -> {
// noop
});
@CalledOnlyBy(AmidstThread.EDT)
public static void show(String message, String logMessages, Runnable executeOnClose) {
INSTANCE.set(message, logMessages, executeOnClose);
public static void showAfterCrash() {
String allMessages = AmidstLogger.getAllMessages();
SwingUtilities.invokeLater(() -> CRASHING.set(allMessages));
}
private final JLabel messageLabel;
public static void showForInterest() {
String allMessages = AmidstLogger.getAllMessages();
SwingUtilities.invokeLater(() -> INTEREST.set(allMessages));
}
private final JLabel pleaseReportLabel;
private final JTextField pleaseReportTextField;
private final JTextArea logMessagesTextArea;
private final JFrame frame;
private volatile Runnable executeOnClose;
private final boolean isCrashing;
private final Runnable executeOnClose;
@CalledOnlyBy(AmidstThread.EDT)
private CrashWindow() {
this.messageLabel = createMessageLabel();
private CrashWindow(String title, boolean isCrashing, Runnable executeOnClose) {
this.isCrashing = isCrashing;
this.executeOnClose = executeOnClose;
if (isCrashing) {
this.pleaseReportLabel = new JLabel("Please report this bug on:");
this.pleaseReportTextField = createReportingTextField();
} else {
this.pleaseReportLabel = null;
this.pleaseReportTextField = null;
}
this.logMessagesTextArea = createLogMessagesTextArea();
this.frame = createFrame();
}
@CalledOnlyBy(AmidstThread.EDT)
private JLabel createMessageLabel() {
return new JLabel();
this.frame = createFrame(title);
}
@CalledOnlyBy(AmidstThread.EDT)
@ -53,18 +70,19 @@ public enum CrashWindow {
}
@CalledOnlyBy(AmidstThread.EDT)
private JFrame createFrame() {
JFrame result = new JFrame("Amidst crashed!");
private JFrame createFrame(String title) {
JFrame result = new JFrame(title);
result.getContentPane().setLayout(new MigLayout());
result.add(messageLabel, "growx, pushx, wrap");
result.add(new JLabel("Please report this bug on:"), "growx, pushx, wrap");
result.add(createReportingTextField(), "growx, pushx, wrap");
if (isCrashing) {
result.add(pleaseReportLabel, "growx, pushx, wrap");
result.add(pleaseReportTextField, "growx, pushx, wrap");
}
result.add(createLogMessagesScrollPane(logMessagesTextArea), "grow, push");
result.setSize(800, 600);
result.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
result.dispose();
result.setVisible(false);
executeOnClose.run();
}
});
@ -88,10 +106,11 @@ public enum CrashWindow {
}
@CalledOnlyBy(AmidstThread.EDT)
public void set(String message, String logMessages, Runnable executeOnClose) {
this.messageLabel.setText(message);
public void set(String logMessages) {
if (isCrashing) {
this.pleaseReportTextField.selectAll();
}
this.logMessagesTextArea.setText(logMessages);
this.executeOnClose = executeOnClose;
this.frame.setVisible(true);
}
}

View File

@ -4,7 +4,7 @@ import java.io.IOException;
import amidst.ResourceLoader;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
@Immutable
public class License {
@ -20,8 +20,7 @@ public class License {
try {
return ResourceLoader.getResourceAsString(path);
} catch (IOException e) {
Log.w("Unable to read license for '" + name + "' at '" + path + "'.");
e.printStackTrace();
AmidstLogger.warn(e, "Unable to read license for '" + name + "' at '" + path + "'.");
return "License text is missing.";
}
}

View File

@ -16,9 +16,10 @@ import amidst.Application;
import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.gui.crash.CrashWindow;
import amidst.gui.main.menu.MovePlayerPopupMenu;
import amidst.gui.main.viewer.ViewerFacade;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.world.WorldSeed;
import amidst.mojangapi.world.WorldType;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
@ -110,7 +111,7 @@ public class Actions {
if (coordinates != null) {
viewerFacade.centerOn(coordinates);
} else {
Log.w("Invalid location entered, ignoring.");
AmidstLogger.warn("Invalid location entered, ignoring.");
mainWindow.displayError("You entered an invalid location.");
}
}
@ -148,6 +149,7 @@ public class Actions {
viewerFacade.centerOn(player);
}
} else {
AmidstLogger.warn("There are no players in this world.");
mainWindow.displayError("There are no players in this world.");
}
}
@ -183,7 +185,7 @@ public class Actions {
@CalledOnlyBy(AmidstThread.EDT)
public void howCanIMoveAPlayer() {
mainWindow.displayMessage(
mainWindow.displayInfo(
"How can I move a player?",
"If you load the world from a save game, you can change the player locations.\n"
+ "1. Scroll the map to and right-click on the new player location, this opens a popup menu.\n"
@ -212,14 +214,16 @@ public class Actions {
if (file != null) {
file = appendPNGFileExtensionIfNecessary(file);
if (file.exists() && !file.isFile()) {
mainWindow.displayError(
"Unable to write capture image, because the target exists but is not a file: "
+ file.getAbsolutePath());
String message = "Unable to write capture image, because the target exists but is not a file: "
+ file.getAbsolutePath();
AmidstLogger.warn(message);
mainWindow.displayError(message);
} else if (!canWriteToFile(file)) {
mainWindow.displayError(
"Unable to write capture image, because you have no writing permissions: "
+ file.getAbsolutePath());
} else if (!file.exists() || mainWindow.askToConfirm(
String message = "Unable to write capture image, because you have no writing permissions: "
+ file.getAbsolutePath();
AmidstLogger.warn(message);
mainWindow.displayError(message);
} else if (!file.exists() || mainWindow.askToConfirmYesNo(
"Replace file?",
"File already exists. Do you want to replace it?\n" + file.getAbsolutePath() + "")) {
saveImageToFile(image, file);
@ -238,6 +242,11 @@ public class Actions {
}
}
@CalledOnlyBy(AmidstThread.EDT)
public void displayLogMessages() {
CrashWindow.showForInterest();
}
@CalledOnlyBy(AmidstThread.EDT)
public void checkForUpdates() {
application.checkForUpdates(mainWindow);
@ -250,7 +259,7 @@ public class Actions {
@CalledOnlyBy(AmidstThread.EDT)
public void about() {
mainWindow.displayMessage(
mainWindow.displayInfo(
"About",
"Amidst - Advanced Minecraft Interfacing and Data/Structure Tracking\n\n"
+ "Author: Skidoodle aka skiphs\n" + "Mail: toolbox4minecraft+amidst@gmail.com\n"
@ -302,7 +311,8 @@ public class Actions {
if (input != null) {
player.moveTo(targetCoordinates, tryParseLong(input, currentHeight), currentCoordinates.getDimension());
viewerFacade.reloadPlayerLayer();
if (mainWindow.askToConfirm("Save Player Locations", "Do you want to save the player locations?")) {
if (mainWindow
.askToConfirmYesNo("Save Player Locations", "Do you want to save the player locations?")) {
if (mainWindow.askToConfirmSaveGameManipulation()) {
viewerFacade.savePlayerLocations();
}
@ -331,8 +341,8 @@ public class Actions {
try {
ImageIO.write(image, "png", file);
} catch (IOException e) {
e.printStackTrace();
mainWindow.displayException(e);
AmidstLogger.warn(e);
mainWindow.displayError(e);
}
}

View File

@ -6,8 +6,6 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@ -27,6 +25,8 @@ import amidst.gui.main.viewer.ViewerFacade;
import amidst.gui.main.viewer.ViewerFacadeBuilder;
import amidst.gui.seedsearcher.SeedSearcher;
import amidst.gui.seedsearcher.SeedSearcherWindow;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.MojangApi;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
@ -149,8 +149,8 @@ public class MainWindow {
try {
setWorld(mojangApi.createWorldFromSeed(worldSeed, worldType));
} catch (IllegalStateException | MinecraftInterfaceException e) {
e.printStackTrace();
displayException(e);
AmidstLogger.warn(e);
displayError(e);
}
}
@ -159,8 +159,8 @@ public class MainWindow {
try {
setWorld(mojangApi.createWorldFromSaveGame(file));
} catch (IllegalStateException | MinecraftInterfaceException | IOException | MojangApiParsingException e) {
e.printStackTrace();
displayException(e);
AmidstLogger.warn(e);
displayError(e);
}
}
@ -282,30 +282,23 @@ public class MainWindow {
}
@CalledOnlyBy(AmidstThread.EDT)
public void displayMessage(String title, String message) {
JOptionPane.showMessageDialog(frame, message, title, JOptionPane.INFORMATION_MESSAGE);
public void displayInfo(String title, String message) {
AmidstMessageBox.displayInfo(frame, title, message);
}
@CalledOnlyBy(AmidstThread.EDT)
public void displayError(String message) {
JOptionPane.showMessageDialog(frame, message, "Error", JOptionPane.ERROR_MESSAGE);
AmidstMessageBox.displayError(frame, "Error", message);
}
@CalledOnlyBy(AmidstThread.EDT)
public void displayException(Exception exception) {
JOptionPane.showMessageDialog(frame, getStackTraceAsString(exception), "Error", JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
private String getStackTraceAsString(Exception exception) {
StringWriter writer = new StringWriter();
exception.printStackTrace(new PrintWriter(writer));
return writer.toString();
public void displayError(Exception e) {
AmidstMessageBox.displayError(frame, "Error", e);
}
@CalledOnlyBy(AmidstThread.EDT)
public boolean askToConfirmSaveGameManipulation() {
return askToConfirm(
return askToConfirmYesNo(
"Save Game Manipulation",
"WARNING: You are about to change the contents of the save game directory. There is a chance that it gets corrupted.\n"
+ "We try to minimize the risk by creating a backup of the changed file, before it is changed.\n"
@ -316,9 +309,8 @@ public class MainWindow {
}
@CalledOnlyBy(AmidstThread.EDT)
public boolean askToConfirm(String title, String message) {
return JOptionPane
.showConfirmDialog(frame, message, title, JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
public boolean askToConfirmYesNo(String title, String message) {
return AmidstMessageBox.askToConfirmYesNo(frame, title, message);
}
@CalledOnlyBy(AmidstThread.EDT)

View File

@ -2,21 +2,18 @@ package amidst.gui.main;
import java.awt.Desktop;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.swing.JOptionPane;
import amidst.AmidstVersion;
import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotNull;
import amidst.documentation.NotThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.threading.WorkerExecutor;
@NotThreadSafe
@ -35,14 +32,14 @@ public class UpdatePrompt {
workerExecutor,
NOOP_CONSUMER,
NOOP,
message -> mainWindow.askToConfirm(TITLE, message));
message -> mainWindow.askToConfirmYesNo(TITLE, message));
} else {
return new UpdatePrompt(
currentVersion,
workerExecutor,
exception -> mainWindow.displayException(exception),
() -> mainWindow.displayMessage(TITLE, NO_UPDATES_AVAILABLE),
message -> mainWindow.askToConfirm(TITLE, message));
e -> mainWindow.displayError(e),
() -> mainWindow.displayInfo(TITLE, NO_UPDATES_AVAILABLE),
message -> mainWindow.askToConfirmYesNo(TITLE, message));
}
} else {
if (silent) {
@ -51,40 +48,18 @@ public class UpdatePrompt {
workerExecutor,
NOOP_CONSUMER,
NOOP,
message -> askToConfirmDirectly(message));
message -> AmidstMessageBox.askToConfirmYesNo(TITLE, message));
} else {
return new UpdatePrompt(
currentVersion,
workerExecutor,
exception -> displayExceptionDirectly(exception),
() -> displayMessageDirectly(NO_UPDATES_AVAILABLE),
message -> askToConfirmDirectly(message));
e -> AmidstMessageBox.displayError(TITLE, e),
() -> AmidstMessageBox.displayInfo(TITLE, NO_UPDATES_AVAILABLE),
message -> AmidstMessageBox.askToConfirmYesNo(TITLE, message));
}
}
}
@CalledOnlyBy(AmidstThread.EDT)
private static void displayExceptionDirectly(Exception exception) {
JOptionPane.showMessageDialog(null, getStackTraceAsString(exception), TITLE, JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
private static String getStackTraceAsString(Exception exception) {
StringWriter writer = new StringWriter();
exception.printStackTrace(new PrintWriter(writer));
return writer.toString();
}
@CalledOnlyBy(AmidstThread.EDT)
private static void displayMessageDirectly(String message) {
JOptionPane.showMessageDialog(null, message, TITLE, JOptionPane.INFORMATION_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
private static boolean askToConfirmDirectly(String message) {
return JOptionPane.showConfirmDialog(null, message, TITLE, JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
}
private static final String TITLE = "Amidst Updater";
private static final String NO_UPDATES_AVAILABLE = "There are no updates available.";
@ -120,13 +95,7 @@ public class UpdatePrompt {
@CalledOnlyBy(AmidstThread.EDT)
private void onCheckFailed(Exception e) {
Log.w("unable to check for updates");
displayError(e);
}
@CalledOnlyBy(AmidstThread.EDT)
private void displayError(Exception e) {
e.printStackTrace();
AmidstLogger.warn(e, "unable to check for updates");
exceptionConsumer.accept(e);
}
@ -136,7 +105,8 @@ public class UpdatePrompt {
try {
openURL(new URI(updateInformation.getDownloadUrl()));
} catch (IOException | UnsupportedOperationException | URISyntaxException e) {
displayError(e);
AmidstLogger.warn(e);
exceptionConsumer.accept(e);
}
}
}
@ -152,6 +122,7 @@ public class UpdatePrompt {
} else if (newVersion.isSameVersionButOldPreReleaseAndNewStable(currentVersion)) {
return askToConfirm(createMessage(message, newVersion, "stable"));
} else {
AmidstLogger.info(NO_UPDATES_AVAILABLE);
noUpdatesDisplayer.run();
return false;
}

View File

@ -148,6 +148,7 @@ public class AmidstMenuBuilder {
JMenu result = new JMenu("Help");
result.setMnemonic(KeyEvent.VK_H);
// @formatter:off
Menus.item(result, actions::displayLogMessages, "Display Log Messages", KeyEvent.VK_M);
Menus.item(result, actions::checkForUpdates, "Check for Updates", KeyEvent.VK_U);
Menus.item(result, actions::viewLicense, "View Licenses", KeyEvent.VK_L);
Menus.item(result, actions::about, "About", KeyEvent.VK_A);

View File

@ -11,7 +11,7 @@ import javax.swing.KeyStroke;
import amidst.documentation.NotThreadSafe;
import amidst.gui.main.Actions;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.settings.biomeprofile.BiomeProfile;
import amidst.settings.biomeprofile.BiomeProfileDirectory;
import amidst.settings.biomeprofile.BiomeProfileVisitor;
@ -76,7 +76,7 @@ public class BiomeProfileMenuFactory {
if (accelerator != null) {
checkBox.setAccelerator(accelerator);
} else {
Log.i("Unable to create keyboard shortcut from: " + shortcut);
AmidstLogger.info("Unable to create keyboard shortcut from: " + shortcut);
}
}
}
@ -125,7 +125,7 @@ public class BiomeProfileMenuFactory {
this.reloadText = reloadText;
this.reloadMnemonic = reloadMnemonic;
this.reloadAccelerator = reloadAccelerator;
Log.i("Checking for additional biome profiles.");
AmidstLogger.info("Checking for additional biome profiles.");
initParentMenu();
}
@ -140,7 +140,7 @@ public class BiomeProfileMenuFactory {
}
private void doReload() {
Log.i("Reloading additional biome profiles.");
AmidstLogger.info("Reloading additional biome profiles.");
initParentMenu();
}
}

View File

@ -10,7 +10,8 @@ import amidst.documentation.NotThreadSafe;
import amidst.fragment.Fragment;
import amidst.fragment.FragmentGraph;
import amidst.gui.main.viewer.FragmentGraphToScreenTranslator;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.world.Dimension;
import amidst.mojangapi.world.biome.Biome;
import amidst.mojangapi.world.biome.UnknownBiomeIndexException;
@ -59,7 +60,7 @@ public class CursorInformationWidget extends TextWidget {
} else if (dimension.equals(Dimension.END)) {
return Biome.theEnd.getName();
} else {
Log.w("unsupported dimension");
AmidstLogger.warn("unsupported dimension");
return UNKNOWN_BIOME_NAME;
}
}
@ -74,8 +75,8 @@ public class CursorInformationWidget extends TextWidget {
try {
return Biome.getByIndex(biome).getName();
} catch (UnknownBiomeIndexException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return UNKNOWN_BIOME_NAME;
}
} else {

View File

@ -8,7 +8,8 @@ import amidst.Application;
import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.MojangApi;
import amidst.mojangapi.file.directory.ProfileDirectory;
import amidst.mojangapi.file.directory.VersionDirectory;
@ -58,7 +59,7 @@ public class LocalProfileComponent extends ProfileComponent {
versionDirectory = profile.createValidVersionDirectory(mojangApi);
return true;
} catch (FileNotFoundException e) {
Log.w(e.getMessage());
AmidstLogger.warn(e);
return false;
}
}
@ -82,24 +83,25 @@ public class LocalProfileComponent extends ProfileComponent {
private boolean tryLoad() {
// TODO: Replace with proper handling for modded profiles.
try {
Log
.i(
"using minecraft launcher profile '" + getProfileName() + "' with versionId '"
+ getVersionName() + "'");
AmidstLogger.info(
"using minecraft launcher profile '" + getProfileName() + "' with versionId '" + getVersionName()
+ "'");
String possibleModProfiles = ".*(optifine|forge).*";
if (Pattern.matches(possibleModProfiles, getVersionName().toLowerCase(Locale.ENGLISH))) {
Log
.e(
"Amidst does not support modded Minecraft profiles! Please select or create an unmodded Minecraft profile via the Minecraft Launcher.");
AmidstLogger.error(
"Amidst does not support modded Minecraft profiles! Please select or create an unmodded Minecraft profile via the Minecraft Launcher.");
AmidstMessageBox.displayError(
"Error",
"Amidst does not support modded Minecraft profiles! Please select or create an unmodded Minecraft profile via the Minecraft Launcher.");
return false;
}
mojangApi.set(getProfileName(), profileDirectory, versionDirectory);
return true;
} catch (LocalMinecraftInterfaceCreationException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
}
}

View File

@ -17,7 +17,8 @@ import amidst.Application;
import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.MojangApi;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.file.json.launcherprofiles.LauncherProfileJson;
@ -112,9 +113,9 @@ public class ProfileSelectWindow {
@CalledOnlyBy(AmidstThread.WORKER)
private LauncherProfilesJson scanAndLoadProfiles() throws MojangApiParsingException, IOException {
Log.i("Scanning for profiles.");
AmidstLogger.info("Scanning for profiles.");
LauncherProfilesJson launcherProfile = mojangApi.getDotMinecraftDirectory().readLauncherProfilesJson();
Log.i("Successfully loaded profile list.");
AmidstLogger.info("Successfully loaded profile list.");
return launcherProfile;
}
@ -128,7 +129,7 @@ public class ProfileSelectWindow {
@CalledOnlyBy(AmidstThread.EDT)
private void createProfileComponentsIfNecessary(LauncherProfilesJson launcherProfile) {
if (launcherProfile.getProfiles().isEmpty()) {
Log.w("No profiles found in launcher_profiles.json");
AmidstLogger.warn("No profiles found in launcher_profiles.json");
profileSelectPanel.setEmptyMessage("No profiles found");
} else {
createProfileComponents(launcherProfile);
@ -154,8 +155,8 @@ public class ProfileSelectWindow {
@CalledOnlyBy(AmidstThread.EDT)
private void scanAndLoadProfilesFailed(Exception e) {
Log.e("Error reading launcher_profiles.json");
e.printStackTrace();
AmidstLogger.error(e, "Error reading launcher_profiles.json");
AmidstMessageBox.displayError("Error", e, "Error reading launcher_profiles.json");
profileSelectPanel.setEmptyMessage("Failed loading");
}

View File

@ -6,6 +6,7 @@ import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.gui.main.MainWindow;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.MojangApi;
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
import amidst.mojangapi.world.World;
@ -67,8 +68,8 @@ public class SeedSearcher {
try {
doSearch(reporter, configuration);
} catch (IllegalStateException | MinecraftInterfaceException e) {
e.printStackTrace();
mainWindow.displayException(e);
AmidstLogger.warn(e);
mainWindow.displayError(e);
} finally {
this.isSearching = false;
this.isStopRequested = false;

View File

@ -18,6 +18,7 @@ import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.gui.main.MainWindow;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.json.filter.WorldFilterJson_MatchAll;
import amidst.mojangapi.world.WorldSeed;
import amidst.mojangapi.world.WorldType;
@ -111,6 +112,7 @@ public class SeedSearcherWindow {
WorldType worldType = seedSearcherConfiguration.getWorldType();
seedSearcher.search(seedSearcherConfiguration, worldSeed -> seedFound(worldSeed, worldType));
} else {
AmidstLogger.warn("invalid configuration");
mainWindow.displayError("invalid configuration");
}
}

View File

@ -0,0 +1,166 @@
package amidst.logging;
import java.util.HashMap;
import java.util.Map;
import amidst.documentation.ThreadSafe;
// TODO: switch to standard logging framework like slf4j + log4j?
@ThreadSafe
public class AmidstLogger {
private static final String DEBUG_TAG = "debug";
private static final String INFO_TAG = "info";
private static final String WARNING_TAG = "warning";
private static final String ERROR_TAG = "error";
private static final String CRASH_TAG = "crash";
private static final ConsoleLogger CONSOLE_LOGGER = new ConsoleLogger();
private static final InMemoryLogger IN_MEMORY_LOGGER = new InMemoryLogger();
private static final Object LOG_LOCK = new Object();
private static final Map<String, Logger> LOGGER = createLoggerMap();
private static Map<String, Logger> createLoggerMap() {
Map<String, Logger> result = new HashMap<>();
result.put("console", CONSOLE_LOGGER);
result.put("master", IN_MEMORY_LOGGER);
return result;
}
public static void addListener(String name, Logger logger) {
synchronized (LOG_LOCK) {
LOGGER.put(name, logger);
}
}
public static void removeListener(String name) {
synchronized (LOG_LOCK) {
LOGGER.remove(name);
}
}
public static void debug(Throwable e) {
log(DEBUG_TAG, MessageFormatter.format(e));
}
public static void debug(String message) {
log(DEBUG_TAG, MessageFormatter.format(message));
}
public static void debug(String message, String part1, String... parts) {
log(DEBUG_TAG, MessageFormatter.format(message, part1, parts));
}
public static void debug(Throwable e, String message) {
log(DEBUG_TAG, MessageFormatter.format(message));
log(DEBUG_TAG, MessageFormatter.format(e));
}
public static void debug(Throwable e, String message, String part1, String... parts) {
log(DEBUG_TAG, MessageFormatter.format(message, part1, parts));
log(DEBUG_TAG, MessageFormatter.format(e));
}
public static void info(Throwable e) {
log(INFO_TAG, MessageFormatter.format(e));
}
public static void info(String message) {
log(INFO_TAG, MessageFormatter.format(message));
}
public static void info(String message, String part1, String... parts) {
log(INFO_TAG, MessageFormatter.format(message, part1, parts));
}
public static void info(Throwable e, String message) {
log(INFO_TAG, MessageFormatter.format(message));
log(INFO_TAG, MessageFormatter.format(e));
}
public static void info(Throwable e, String message, String part1, String... parts) {
log(INFO_TAG, MessageFormatter.format(message, part1, parts));
log(INFO_TAG, MessageFormatter.format(e));
}
public static void warn(Throwable e) {
log(WARNING_TAG, MessageFormatter.format(e));
}
public static void warn(String message) {
log(WARNING_TAG, MessageFormatter.format(message));
}
public static void warn(String message, String part1, String... parts) {
log(WARNING_TAG, MessageFormatter.format(message, part1, parts));
}
public static void warn(Throwable e, String message) {
log(WARNING_TAG, MessageFormatter.format(message));
log(WARNING_TAG, MessageFormatter.format(e));
}
public static void warn(Throwable e, String message, String part1, String... parts) {
log(WARNING_TAG, MessageFormatter.format(message, part1, parts));
log(WARNING_TAG, MessageFormatter.format(e));
}
public static void error(Throwable e) {
log(ERROR_TAG, MessageFormatter.format(e));
}
public static void error(String message) {
log(ERROR_TAG, MessageFormatter.format(message));
}
public static void error(String message, String part1, String... parts) {
log(ERROR_TAG, MessageFormatter.format(message, part1, parts));
}
public static void error(Throwable e, String message) {
log(ERROR_TAG, MessageFormatter.format(message));
log(ERROR_TAG, MessageFormatter.format(e));
}
public static void error(Throwable e, String message, String part1, String... parts) {
log(ERROR_TAG, MessageFormatter.format(message, part1, parts));
log(ERROR_TAG, MessageFormatter.format(e));
}
public static void crash(Throwable e) {
log(CRASH_TAG, MessageFormatter.format(e));
}
public static void crash(String message) {
log(CRASH_TAG, MessageFormatter.format(message));
}
public static void crash(String message, String part1, String... parts) {
log(CRASH_TAG, MessageFormatter.format(message, part1, parts));
}
public static void crash(Throwable e, String message) {
log(CRASH_TAG, MessageFormatter.format(message));
log(CRASH_TAG, MessageFormatter.format(e));
}
public static void crash(Throwable e, String message, String part1, String... parts) {
log(CRASH_TAG, MessageFormatter.format(message, part1, parts));
log(CRASH_TAG, MessageFormatter.format(e));
}
private static void log(String tag, String message) {
synchronized (LOG_LOCK) {
for (Logger listener : LOGGER.values()) {
listener.log(tag, message);
}
}
}
public static String getAllMessages() {
synchronized (LOG_LOCK) {
return IN_MEMORY_LOGGER.getContents();
}
}
}

View File

@ -0,0 +1,100 @@
package amidst.logging;
import java.awt.Component;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
@NotThreadSafe
public enum AmidstMessageBox {
;
public static void displayError(String title, Throwable e) {
displayMessageBox(title, MessageFormatter.format(e), JOptionPane.ERROR_MESSAGE);
}
public static void displayError(String title, Throwable e, String message) {
displayMessageBox(title, MessageFormatter.format(e, message), JOptionPane.ERROR_MESSAGE);
}
public static void displayError(String title, Throwable e, String message, String part1, String[] parts) {
displayMessageBox(title, MessageFormatter.format(e, message, part1, parts), JOptionPane.ERROR_MESSAGE);
}
public static void displayError(String title, String message) {
displayMessageBox(title, MessageFormatter.format(message), JOptionPane.ERROR_MESSAGE);
}
public static void displayError(String title, String message, String part1, String[] parts) {
displayMessageBox(title, MessageFormatter.format(message, part1, parts), JOptionPane.ERROR_MESSAGE);
}
public static void displayInfo(String title, String message) {
displayMessageBox(title, MessageFormatter.format(message), JOptionPane.INFORMATION_MESSAGE);
}
public static void displayInfo(String title, String message, String part1, String[] parts) {
displayMessageBox(title, MessageFormatter.format(message, part1, parts), JOptionPane.INFORMATION_MESSAGE);
}
public static void displayError(Component parent, String title, Throwable e) {
displayMessageBox(parent, title, MessageFormatter.format(e), JOptionPane.ERROR_MESSAGE);
}
public static void displayError(Component parent, String title, Throwable e, String message) {
displayMessageBox(parent, title, MessageFormatter.format(e, message), JOptionPane.ERROR_MESSAGE);
}
public static void displayError(
Component parent,
String title,
Throwable e,
String message,
String part1,
String[] parts) {
displayMessageBox(parent, title, MessageFormatter.format(e, message, part1, parts), JOptionPane.ERROR_MESSAGE);
}
public static void displayError(Component parent, String title, String message) {
displayMessageBox(parent, title, MessageFormatter.format(message), JOptionPane.ERROR_MESSAGE);
}
public static void displayError(Component parent, String title, String message, String part1, String[] parts) {
displayMessageBox(parent, title, MessageFormatter.format(message, part1, parts), JOptionPane.ERROR_MESSAGE);
}
public static void displayInfo(Component parent, String title, String message) {
displayMessageBox(parent, title, MessageFormatter.format(message), JOptionPane.INFORMATION_MESSAGE);
}
public static void displayInfo(Component parent, String title, String message, String part1, String[] parts) {
displayMessageBox(
parent,
title,
MessageFormatter.format(message, part1, parts),
JOptionPane.INFORMATION_MESSAGE);
}
private static void displayMessageBox(String title, String message, int type) {
displayMessageBox(null, title, message, type);
}
private static void displayMessageBox(Component parent, String title, String message, int type) {
SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(parent, message, title, type));
}
@CalledOnlyBy(AmidstThread.EDT)
public static boolean askToConfirmYesNo(String title, String message) {
return askToConfirmYesNo(null, title, message);
}
@CalledOnlyBy(AmidstThread.EDT)
public static boolean askToConfirmYesNo(Component parent, String title, String message) {
return JOptionPane
.showConfirmDialog(parent, message, title, JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
}
}

View File

@ -5,46 +5,7 @@ import amidst.documentation.NotThreadSafe;
@NotThreadSafe
public class ConsoleLogger implements Logger {
@Override
public void debug(Object... messages) {
printWithTag("debug", messages);
}
@Override
public void info(Object... messages) {
printWithTag("info", messages);
}
@Override
public void warning(Object... messages) {
printWithTag("warning", messages);
}
@Override
public void error(Object... messages) {
printWithTag("error", messages);
}
@Override
public void crash(Throwable e, String exceptionText, String message) {
printWithTag("crash", message);
if (!exceptionText.isEmpty()) {
printWithTag("crash", exceptionText);
}
}
private void printWithTag(String tag, Object... messages) {
System.out.print("[" + tag + "] ");
for (int i = 0; i < messages.length; i++) {
System.out.print(messages[i]);
System.out.print(getMessageDelimiter(i, messages));
}
}
private String getMessageDelimiter(int i, Object... messages) {
if (i < messages.length - 1) {
return " ";
} else {
return "\n";
}
public void log(String tag, String message) {
System.out.println("[" + tag + "] " + message);
}
}

View File

@ -65,23 +65,23 @@ public class FileLogger implements Logger {
@CalledOnlyBy(AmidstThread.STARTUP)
private void disableBecauseFileCreationFailed() {
Log.w("Unable to create new file at: " + file + " disabling logging to file. (No exception thrown)");
AmidstLogger
.warn("Unable to create new file at: " + file + " disabling logging to file. (No exception thrown)");
}
@CalledOnlyBy(AmidstThread.STARTUP)
private void disableBecauseFileCreationThrowsException(IOException e) {
Log.w("Unable to create new file at: " + file + " disabling logging to file.");
e.printStackTrace();
AmidstLogger.warn(e, "Unable to create new file at: " + file + " disabling logging to file.");
}
@CalledOnlyBy(AmidstThread.STARTUP)
private void disableBecauseFileIsDirectory() {
Log.w("Unable to log at path: " + file + " because location is a directory.");
AmidstLogger.warn("Unable to log at path: " + file + " because location is a directory.");
}
@CalledOnlyBy(AmidstThread.STARTUP)
private void writeWelcomeMessageToFile() {
write("log", "New FileLogger started.");
log("log", "New FileLogger started.");
}
@CalledOnlyBy(AmidstThread.STARTUP)
@ -116,55 +116,20 @@ public class FileLogger implements Logger {
try (FileWriter writer = new FileWriter(file, true)) {
writer.append(logMessage);
} catch (IOException e) {
Log.w("Unable to write to log file.");
e.printStackTrace();
AmidstLogger.warn(e, "Unable to write to log file.");
}
}
@Override
public void debug(Object... messages) {
write("debug", messages);
}
@Override
public void info(Object... messages) {
write("info", messages);
}
@Override
public void warning(Object... messages) {
write("warning", messages);
}
@Override
public void error(Object... messages) {
write("error", messages);
}
@Override
public void crash(Throwable e, String exceptionText, String message) {
write("crash", message);
if (!exceptionText.isEmpty()) {
write("crash", exceptionText);
}
}
private void write(String tag, Object... messages) {
public void log(String tag, String message) {
String currentTime = new Timestamp(new Date().getTime()).toString();
StringBuilder builder = new StringBuilder(currentTime);
builder.append(" [").append(tag).append("] ");
for (int i = 0; i < messages.length; i++) {
builder.append(messages[i]);
builder.append(getMessageDelimiter(i, messages));
}
StringBuilder builder = new StringBuilder()
.append(currentTime)
.append(" [")
.append(tag)
.append("] ")
.append(message)
.append("\r\n");
logMessageQueue.add(builder.toString());
}
private String getMessageDelimiter(int i, Object... messages) {
if (i < messages.length - 1) {
return " ";
} else {
return "\r\n";
}
}
}

View File

@ -7,47 +7,8 @@ public class InMemoryLogger implements Logger {
private StringBuffer buffer = new StringBuffer();
@Override
public void debug(Object... messages) {
write("debug", messages);
}
@Override
public void info(Object... messages) {
write("info", messages);
}
@Override
public void warning(Object... messages) {
write("warning", messages);
}
@Override
public void error(Object... messages) {
write("error", messages);
}
@Override
public void crash(Throwable e, String exceptionText, String message) {
write("crash", message);
if (!exceptionText.isEmpty()) {
write("crash", exceptionText);
}
}
private void write(String tag, Object... messages) {
buffer.append("[").append(tag).append("] ");
for (int i = 0; i < messages.length; i++) {
buffer.append(messages[i]);
buffer.append(getMessageDelimiter(i, messages));
}
}
private String getMessageDelimiter(int i, Object... messages) {
if (i < messages.length - 1) {
return " ";
} else {
return "\n";
}
public void log(String tag, String message) {
buffer.append("[").append(tag).append("] ").append(message).append("\n");
}
public String getContents() {

View File

@ -1,110 +0,0 @@
package amidst.logging;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JOptionPane;
import amidst.documentation.ThreadSafe;
// TODO: switch to standard logging framework like slf4j + log4j?
@ThreadSafe
public class Log {
private static final ConsoleLogger CONSOLE_LOGGER = new ConsoleLogger();
private static final InMemoryLogger IN_MEMORY_LOGGER = new InMemoryLogger();
private static final Object LOG_LOCK = new Object();
private static final boolean IS_USING_ALERTS = true;
private static final boolean IS_SHOWING_DEBUG = true;
private static final Map<String, Logger> LOGGER = new HashMap<>();
static {
addListener("console", CONSOLE_LOGGER);
addListener("master", IN_MEMORY_LOGGER);
}
public static void addListener(String name, Logger l) {
synchronized (LOG_LOCK) {
LOGGER.put(name, l);
}
}
public static void removeListener(String name) {
synchronized (LOG_LOCK) {
LOGGER.remove(name);
}
}
public static void i(Object... messages) {
synchronized (LOG_LOCK) {
for (Logger listener : LOGGER.values()) {
listener.info(messages);
}
}
}
public static void debug(Object... messages) {
if (IS_SHOWING_DEBUG) {
synchronized (LOG_LOCK) {
for (Logger listener : LOGGER.values()) {
listener.debug(messages);
}
}
}
}
public static void w(Object... messages) {
synchronized (LOG_LOCK) {
for (Logger listener : LOGGER.values()) {
listener.warning(messages);
}
}
}
public static void e(Object... messages) {
synchronized (LOG_LOCK) {
if (IS_USING_ALERTS) {
JOptionPane.showMessageDialog(null, messages, "Error", JOptionPane.ERROR_MESSAGE);
}
for (Logger listener : LOGGER.values()) {
listener.error(messages);
}
}
}
public static void crash(Throwable e, String message) {
synchronized (LOG_LOCK) {
String exceptionText = getExceptionText(e);
for (Logger listener : LOGGER.values()) {
listener.crash(e, exceptionText, message);
}
}
}
public static String getAllMessages() {
synchronized (LOG_LOCK) {
return IN_MEMORY_LOGGER.getContents();
}
}
private static String getExceptionText(Throwable e) {
if (e != null) {
return getStackTraceAsString(e);
} else {
return "";
}
}
public static void printTraceStack(Throwable e) {
w(getStackTraceAsString(e));
}
private static String getStackTraceAsString(Throwable e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
return writer.toString();
}
}

View File

@ -1,13 +1,5 @@
package amidst.logging;
public interface Logger {
public void debug(Object... messages);
public void info(Object... messages);
public void warning(Object... messages);
public void error(Object... messages);
public void crash(Throwable e, String exceptionText, String message);
void log(String tag, String message);
}

View File

@ -0,0 +1,56 @@
package amidst.logging;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Objects;
import amidst.documentation.Immutable;
@Immutable
public enum MessageFormatter {
;
public static String format(Throwable e, String message) {
return format(message) + "\n\n" + format(e);
}
public static String format(Throwable e, String message, String part1, String[] parts) {
return format(message, part1, parts) + "\n\n" + format(e);
}
public static String format(String message) {
return String.valueOf(message);
}
public static String format(Throwable e) {
if (e != null) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
return writer.toString();
} else {
return "null";
}
}
public static String format(String message, String part1, String... parts) {
Objects.requireNonNull(message, "the message cannot be null");
int expectedNumberOfMessageParts = 2 + parts.length;
String[] messageParts = message.split("\\{\\}", expectedNumberOfMessageParts);
if (messageParts.length == 0) {
return "";
} else if (messageParts.length == 1) {
return messageParts[0];
} else {
StringBuilder b = new StringBuilder();
b.append(messageParts[0]);
b.append(format(part1));
b.append(messageParts[1]);
for (int i = 2; i < messageParts.length; i++) {
b.append(format(parts[i - 2]));
b.append(messageParts[i]);
}
return b.toString();
}
}
}

View File

@ -5,7 +5,7 @@ import java.io.File;
import amidst.CommandLineParameters;
import amidst.documentation.Immutable;
import amidst.documentation.NotNull;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.DotMinecraftDirectoryFinder;
import amidst.mojangapi.file.DotMinecraftDirectoryNotFoundException;
import amidst.mojangapi.file.directory.DotMinecraftDirectory;
@ -29,10 +29,9 @@ public class MojangApiBuilder {
LocalMinecraftInterfaceCreationException {
DotMinecraftDirectory dotMinecraftDirectory = createDotMinecraftDirectory();
if (dotMinecraftDirectory.isValid()) {
Log
.i(
"using '.minecraft' directory at: '" + dotMinecraftDirectory.getRoot() + "', libraries: '"
+ dotMinecraftDirectory.getLibraries() + "'");
AmidstLogger.info(
"using '.minecraft' directory at: '" + dotMinecraftDirectory.getRoot() + "', libraries: '"
+ dotMinecraftDirectory.getLibraries() + "'");
} else {
throw new DotMinecraftDirectoryNotFoundException(
"invalid '.minecraft' directory at: '" + dotMinecraftDirectory.getRoot() + "', libraries: '"
@ -59,18 +58,14 @@ public class MojangApiBuilder {
File json = new File(parameters.minecraftJsonFile);
VersionDirectory result = mojangApi.createVersionDirectory(jar, json);
if (result.isValid()) {
Log
.i(
"using minecraft version directory. versionId: '" + result.getVersionId()
+ "', jar file: '" + result.getJar() + "', json file: '" + result.getJson()
+ "'");
AmidstLogger.info(
"using minecraft version directory. versionId: '" + result.getVersionId() + "', jar file: '"
+ result.getJar() + "', json file: '" + result.getJson() + "'");
return result;
} else {
Log
.w(
"invalid minecraft version directory. versionId: '" + result.getVersionId()
+ "', jar file: '" + result.getJar() + "', json file: '" + result.getJson()
+ "'");
AmidstLogger.warn(
"invalid minecraft version directory. versionId: '" + result.getVersionId() + "', jar file: '"
+ result.getJar() + "', json file: '" + result.getJson() + "'");
}
}
return null;

View File

@ -4,7 +4,7 @@ import java.io.File;
import amidst.documentation.Immutable;
import amidst.documentation.NotNull;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.util.OperatingSystemDetector;
@Immutable
@ -18,10 +18,9 @@ public enum DotMinecraftDirectoryFinder {
if (result.isDirectory()) {
return result;
} else {
Log
.w(
"Unable to set Minecraft directory to: " + result
+ " as that location does not exist or is not a folder.");
AmidstLogger.warn(
"Unable to set Minecraft directory to: " + result
+ " as that location does not exist or is not a folder.");
}
}
return getMinecraftDirectory();

View File

@ -8,7 +8,7 @@ import java.util.List;
import amidst.documentation.Immutable;
import amidst.documentation.NotNull;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.json.version.LibraryJson;
import amidst.util.OperatingSystemDetector;
@ -24,13 +24,12 @@ public enum LibraryFinder {
if (libraryFile != null) {
try {
result.add(libraryFile.toURI().toURL());
Log.i("Found library: " + libraryFile);
AmidstLogger.info("Found library: " + libraryFile);
} catch (MalformedURLException e) {
Log.w("Unable to convert library file to URL: " + libraryFile);
e.printStackTrace();
AmidstLogger.warn(e, "Unable to convert library file to URL: " + libraryFile);
}
} else {
Log.i("Skipping library: " + library.getName());
AmidstLogger.info("Skipping library: " + library.getName());
}
}
return result;
@ -74,11 +73,12 @@ public enum LibraryFinder {
if (result != null && result.exists()) {
return result;
} else {
Log.w("Attempted to search for file at path: " + librarySearchPath + " but found nothing. Skipping.");
AmidstLogger.warn(
"Attempted to search for file at path: " + librarySearchPath + " but found nothing. Skipping.");
return null;
}
} else {
Log.w("Failed attempt to load library at: " + librarySearchPath);
AmidstLogger.warn("Failed attempt to load library at: " + librarySearchPath);
return null;
}
}

View File

@ -11,7 +11,7 @@ import org.jnbt.CompoundTag;
import amidst.documentation.Immutable;
import amidst.documentation.NotNull;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.file.nbt.LevelDatNbt;
import amidst.mojangapi.file.nbt.NBTUtils;
@ -163,7 +163,7 @@ public class SaveDirectory {
}
}
if (!result.isEmpty()) {
Log.i("using players from the playerdata directory");
AmidstLogger.info("using players from the playerdata directory");
return result;
}
for (File playersFile : getPlayersFiles()) {
@ -172,10 +172,10 @@ public class SaveDirectory {
}
}
if (!result.isEmpty()) {
Log.i("using players from the players directory");
AmidstLogger.info("using players from the players directory");
return result;
}
Log.i("no multiplayer players found");
AmidstLogger.info("no multiplayer players found");
return result;
}
@ -193,7 +193,7 @@ public class SaveDirectory {
*/
@NotNull
public List<PlayerNbt> createSingleplayerPlayerNbts() {
Log.i("using player from level.dat");
AmidstLogger.info("using player from level.dat");
return Arrays.asList(createLevelDatPlayerNbt());
}

View File

@ -10,7 +10,7 @@ import java.util.List;
import amidst.documentation.Immutable;
import amidst.documentation.NotNull;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.file.json.JsonReader;
import amidst.mojangapi.file.json.version.VersionJson;
@ -60,10 +60,10 @@ public class VersionDirectory {
@NotNull
public URLClassLoader createClassLoader() throws MalformedURLException {
if (json.isFile()) {
Log.i("Loading libraries.");
AmidstLogger.info("Loading libraries.");
return doCreateClassLoader(getJarFileUrl(), getAllLibraryUrls());
} else {
Log.i("Unable to find Minecraft library JSON at: " + json + ". Skipping.");
AmidstLogger.info("Unable to find Minecraft library JSON at: " + json + ". Skipping.");
return doCreateClassLoader(getJarFileUrl());
}
}
@ -78,7 +78,7 @@ public class VersionDirectory {
try {
return readVersionJson().getLibraryUrls(dotMinecraftDirectory.getLibraries());
} catch (IOException | MojangApiParsingException e) {
Log.w("Invalid jar profile loaded. Library loading will be skipped. (Path: " + json + ")");
AmidstLogger.warn("Invalid jar profile loaded. Library loading will be skipped. (Path: " + json + ")");
return new ArrayList<>();
}
}

View File

@ -13,7 +13,7 @@ import com.google.gson.JsonSyntaxException;
import amidst.ResourceLoader;
import amidst.documentation.Immutable;
import amidst.documentation.NotNull;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.file.URIUtils;
import amidst.mojangapi.file.json.launcherprofiles.LauncherProfilesJson;
@ -42,34 +42,34 @@ public enum JsonReader {
@NotNull
public static VersionListJson readRemoteOrLocalVersionList() throws FileNotFoundException {
Log.i("Beginning latest version list load.");
Log.i("Attempting to download remote version list...");
AmidstLogger.info("Beginning latest version list load.");
AmidstLogger.info("Attempting to download remote version list...");
VersionListJson remote = null;
try {
remote = readRemoteVersionList();
} catch (IOException | MojangApiParsingException e) {
Log.w("Unable to read remote version list.");
Log.printTraceStack(e);
Log.w("Aborting version list load. URL: " + REMOTE_VERSION_LIST);
AmidstLogger.warn("Unable to read remote version list.");
AmidstLogger.warn(e);
AmidstLogger.warn("Aborting version list load. URL: " + REMOTE_VERSION_LIST);
}
if (remote != null) {
Log.i("Successfully loaded version list. URL: " + REMOTE_VERSION_LIST);
AmidstLogger.info("Successfully loaded version list. URL: " + REMOTE_VERSION_LIST);
return remote;
}
Log.i("Attempting to load local version list...");
AmidstLogger.info("Attempting to load local version list...");
VersionListJson local = null;
try {
local = readLocalVersionListFromResource();
} catch (IOException | MojangApiParsingException e) {
Log.w("Unable to read local version list.");
Log.printTraceStack(e);
Log.w("Aborting version list load. URL: " + LOCAL_VERSION_LIST);
AmidstLogger.warn("Unable to read local version list.");
AmidstLogger.warn(e);
AmidstLogger.warn("Aborting version list load. URL: " + LOCAL_VERSION_LIST);
}
if (local != null) {
Log.i("Successfully loaded version list. URL: " + LOCAL_VERSION_LIST);
AmidstLogger.info("Successfully loaded version list. URL: " + LOCAL_VERSION_LIST);
return local;
}
Log.w("Failed to load both remote and local version list.");
AmidstLogger.warn("Failed to load both remote and local version list.");
throw new FileNotFoundException("unable to read version list");
}

View File

@ -9,7 +9,7 @@ import java.net.URL;
import javax.imageio.ImageIO;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.file.json.player.PlayerJson;
@ -23,7 +23,7 @@ public enum PlayerInformationRetriever {
try {
return getPlayerJsonByName(name);
} catch (IOException | MojangApiParsingException | NullPointerException e) {
Log.w("unable to load player information by name: " + name);
AmidstLogger.warn("unable to load player information by name: " + name);
return null;
}
}
@ -32,7 +32,7 @@ public enum PlayerInformationRetriever {
try {
return getPlayerJsonByUUID(uuid);
} catch (IOException | MojangApiParsingException | NullPointerException e) {
Log.w("unable to load player information by uuid: " + uuid);
AmidstLogger.warn("unable to load player information by uuid: " + uuid);
return null;
}
}
@ -41,7 +41,7 @@ public enum PlayerInformationRetriever {
try {
return getPlayerHeadByName(name);
} catch (IOException | NullPointerException e) {
Log.w("unable to load player head by name: " + name);
AmidstLogger.warn("unable to load player head by name: " + name);
return null;
}
}
@ -50,7 +50,7 @@ public enum PlayerInformationRetriever {
try {
return getPlayerHeadBySkinUrl(skinUrl);
} catch (IOException | NullPointerException e) {
Log.w("unable to load player head by skin url: " + skinUrl);
AmidstLogger.warn("unable to load player head by skin url: " + skinUrl);
return null;
}
}

View File

@ -11,7 +11,7 @@ import com.google.gson.JsonSyntaxException;
import amidst.documentation.GsonConstructor;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.world.filter.WorldFilter;
import amidst.mojangapi.world.filter.WorldFilter_MatchAll;
@ -56,7 +56,7 @@ public class WorldFilterJson_MatchAll {
return Optional.of(createWorldFilter());
} else {
// TODO: use error messages
Log.debug(getValidationMessages());
AmidstLogger.debug(getValidationMessages().toString());
return Optional.empty();
}
}

View File

@ -4,7 +4,7 @@ import java.io.IOException;
import amidst.documentation.GsonConstructor;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.MojangApi;
import amidst.mojangapi.file.FilenameFactory;
import amidst.mojangapi.file.URIUtils;
@ -78,8 +78,7 @@ public class VersionListEntryJson {
downloadServer(prefix);
return true;
} catch (IOException e) {
Log.w("unable to download server: " + id);
e.printStackTrace();
AmidstLogger.warn(e, "unable to download server: " + id);
}
return false;
}
@ -89,8 +88,7 @@ public class VersionListEntryJson {
downloadClient(prefix);
return true;
} catch (IOException e) {
Log.w("unable to download client: " + id);
e.printStackTrace();
AmidstLogger.warn(e, "unable to download client: " + id);
}
return false;
}

View File

@ -8,7 +8,7 @@ import java.util.Objects;
import amidst.documentation.Immutable;
import amidst.documentation.NotNull;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
/**
* Information about what each supported version is
@ -170,7 +170,7 @@ public enum RecognisedVersion {
return recognisedVersion;
}
}
Log.i("Unable to recognise Minecraft Version with the magic string \"" + magicString + "\".");
AmidstLogger.info("Unable to recognise Minecraft Version with the magic string \"" + magicString + "\".");
return RecognisedVersion.UNKNOWN;
}
@ -182,15 +182,14 @@ public enum RecognisedVersion {
return recognisedVersion;
}
}
Log.i("Unable to recognise Minecraft Version with the name \"" + name + "\".");
AmidstLogger.info("Unable to recognise Minecraft Version with the name \"" + name + "\".");
return RecognisedVersion.UNKNOWN;
}
private static void logFound(RecognisedVersion recognisedVersion) {
Log
.i(
"Recognised Minecraft Version " + recognisedVersion.name + " with the magic string \""
+ recognisedVersion.magicString + "\".");
AmidstLogger.info(
"Recognised Minecraft Version " + recognisedVersion.name + " with the magic string \""
+ recognisedVersion.magicString + "\".");
}
public static boolean isNewerOrEqualTo(RecognisedVersion version1, RecognisedVersion version2) {

View File

@ -5,7 +5,7 @@ import java.lang.reflect.InvocationTargetException;
import amidst.clazz.symbolic.SymbolicClass;
import amidst.clazz.symbolic.SymbolicObject;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.minecraftinterface.MinecraftInterface;
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
import amidst.mojangapi.minecraftinterface.RecognisedVersion;
@ -75,8 +75,8 @@ public class LocalMinecraftInterface implements MinecraftInterface {
public synchronized void createWorld(long seed, WorldType worldType, String generatorOptions)
throws MinecraftInterfaceException {
try {
Log.i("Creating world with seed '" + seed + "' and type '" + worldType.getName() + "'");
Log.i("Using the following generator options: " + generatorOptions);
AmidstLogger.info("Creating world with seed '" + seed + "' and type '" + worldType.getName() + "'");
AmidstLogger.info("Using the following generator options: " + generatorOptions);
initializeBlock();
Object[] genLayers = getGenLayers(seed, worldType, generatorOptions);
quarterResolutionBiomeGenerator = new SymbolicObject(genLayerClass, genLayers[0]);

View File

@ -12,7 +12,7 @@ import amidst.clazz.symbolic.SymbolicClassGraphCreationException;
import amidst.clazz.translator.ClassTranslator;
import amidst.documentation.Immutable;
import amidst.documentation.NotNull;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.directory.VersionDirectory;
import amidst.mojangapi.minecraftinterface.MinecraftInterface;
import amidst.mojangapi.minecraftinterface.RecognisedVersion;
@ -33,7 +33,7 @@ public class LocalMinecraftInterfaceBuilder {
RecognisedVersion recognisedVersion = RecognisedVersion.from(classLoader);
Map<String, SymbolicClass> symbolicClassMap = Classes
.createSymbolicClassMap(versionDirectory.getJar(), classLoader, translator);
Log.i("Minecraft load complete.");
AmidstLogger.info("Minecraft load complete.");
return new LocalMinecraftInterface(
symbolicClassMap.get(SymbolicNames.CLASS_INT_CACHE),
symbolicClassMap.get(SymbolicNames.CLASS_BLOCK_INIT),

View File

@ -1,7 +1,7 @@
package amidst.mojangapi.world;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.world.coordinates.Resolution;
@Immutable
@ -20,7 +20,7 @@ public enum Dimension {
} else if (id == END.getId()) {
return END;
} else {
Log.w("Unsupported dimension id: " + id + ". Falling back to Overworld.");
AmidstLogger.warn("Unsupported dimension id: " + id + ". Falling back to Overworld.");
return OVERWORLD;
}
}

View File

@ -10,14 +10,14 @@ import java.util.Objects;
import amidst.documentation.NotNull;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.minecraftinterface.RecognisedVersion;
@ThreadSafe
public class SeedHistoryLogger {
public static SeedHistoryLogger from(String filename) {
if (filename != null) {
Log.i("using seed history file: '" + filename + "'");
AmidstLogger.info("using seed history file: '" + filename + "'");
return new SeedHistoryLogger(new File(filename), true, true);
} else {
return new SeedHistoryLogger(new File(HISTORY_TXT), false, true);
@ -54,7 +54,7 @@ public class SeedHistoryLogger {
if (file.isFile()) {
writeLine(createLine(recognisedVersion, worldSeed));
} else {
Log.i("Not writing to seed history file, because it does not exist: " + file);
AmidstLogger.info("Not writing to seed history file, because it does not exist: " + file);
}
}
@ -82,8 +82,7 @@ public class SeedHistoryLogger {
try {
file.createNewFile();
} catch (IOException e) {
Log.w("Unable to create seed history file: " + file);
e.printStackTrace();
AmidstLogger.warn(e, "Unable to create seed history file: " + file);
}
}
@ -91,8 +90,7 @@ public class SeedHistoryLogger {
try (PrintStream stream = new PrintStream(new FileOutputStream(file, true))) {
stream.println(line);
} catch (IOException e) {
Log.w("Unable to write to seed history file: " + file);
e.printStackTrace();
AmidstLogger.warn(e, "Unable to write to seed history file: " + file);
}
}
}

View File

@ -4,7 +4,8 @@ import java.util.Arrays;
import java.util.List;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.minecraftinterface.local.SymbolicNames;
@Immutable
@ -51,7 +52,10 @@ public enum WorldType {
if (result != null) {
return result;
} else {
Log.e("Unable to find World Type: " + nameOrSymbolicFieldName + ". Falling back to default world type.");
String message = "Unable to find World Type: " + nameOrSymbolicFieldName
+ ". Falling back to default world type.";
AmidstLogger.error(message);
AmidstMessageBox.displayError("Error", message);
return DEFAULT;
}
}

View File

@ -4,7 +4,7 @@ import java.util.Arrays;
import java.util.List;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.world.Dimension;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
import amidst.mojangapi.world.icon.WorldIcon;
@ -30,7 +30,7 @@ public class SpawnProducer extends CachedWorldIconProducer {
return createWorldIcon(spawnLocation);
} else {
CoordinatesInWorld origin = CoordinatesInWorld.origin();
Log.i("Unable to find spawn biome. Falling back to " + origin.toString() + ".");
AmidstLogger.info("Unable to find spawn biome. Falling back to " + origin.toString() + ".");
return createWorldIcon(origin);
}
}

View File

@ -1,7 +1,8 @@
package amidst.mojangapi.world.icon.type;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
import amidst.mojangapi.world.biome.Biome;
import amidst.mojangapi.world.biome.UnknownBiomeIndexException;
@ -28,16 +29,18 @@ public class TempleWorldIconTypeProvider implements WorldIconTypeProvider<Void>
} else if (biome == Biome.icePlains || biome == Biome.coldTaiga) {
return DefaultWorldIconTypes.IGLOO;
} else {
Log.e("No known structure for this biome type: " + biome.getName());
String message = "No known structure for this biome type: " + biome.getName();
AmidstLogger.error(message);
AmidstMessageBox.displayError("Error", message);
return null;
}
} catch (UnknownBiomeIndexException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return null;
} catch (MinecraftInterfaceException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return null;
}
}

View File

@ -4,7 +4,8 @@ import java.util.List;
import java.util.Random;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.minecraftinterface.MinecraftInterface;
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
import amidst.mojangapi.world.biome.Biome;
@ -30,8 +31,8 @@ public class BiomeDataOracle {
try {
copyToResult(result, width, height, getBiomeData(left, top, width, height, useQuarterResolution));
} catch (MinecraftInterfaceException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
}
}
}
@ -56,12 +57,12 @@ public class BiomeDataOracle {
try {
return validBiomes.contains(getBiomeAt(x, y));
} catch (UnknownBiomeIndexException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
} catch (MinecraftInterfaceException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
}
}
@ -86,12 +87,12 @@ public class BiomeDataOracle {
}
return true;
} catch (UnknownBiomeIndexException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
} catch (MinecraftInterfaceException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return false;
}
}
@ -126,12 +127,12 @@ public class BiomeDataOracle {
}
return result;
} catch (UnknownBiomeIndexException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return null;
} catch (MinecraftInterfaceException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return null;
}
}

View File

@ -6,7 +6,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.directory.SaveDirectory;
import amidst.mojangapi.file.nbt.player.PlayerNbt;
import amidst.threading.WorkerExecutor;
@ -51,7 +51,7 @@ public class MovablePlayerList implements Iterable<Player> {
public void load(WorkerExecutor workerExecutor, Runnable onPlayerFinishedLoading) {
if (saveDirectory != null) {
Log.i("loading player locations");
AmidstLogger.info("loading player locations");
ConcurrentLinkedQueue<Player> players = new ConcurrentLinkedQueue<>();
this.players = players;
loadPlayersLater(players, workerExecutor, onPlayerFinishedLoading);
@ -89,12 +89,12 @@ public class MovablePlayerList implements Iterable<Player> {
public void save() {
if (isSaveEnabled) {
Log.i("saving player locations");
AmidstLogger.info("saving player locations");
for (Player player : players) {
player.trySaveLocation();
}
} else {
Log.i("not saving player locations, because it is disabled for this version");
AmidstLogger.info("not saving player locations, because it is disabled for this version");
}
}

View File

@ -3,7 +3,7 @@ package amidst.mojangapi.world.player;
import java.io.IOException;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.file.nbt.player.PlayerNbt;
import amidst.mojangapi.world.Dimension;
@ -43,15 +43,13 @@ public class Player {
if (saveLocation()) {
return true;
} else {
Log
.w(
"skipping to save player location, because the backup file cannot be created for player: "
+ getPlayerName());
AmidstLogger.warn(
"skipping to save player location, because the backup file cannot be created for player: "
+ getPlayerName());
return false;
}
} catch (MojangApiParsingException e) {
Log.w("error while writing player location for player: " + getPlayerName());
e.printStackTrace();
AmidstLogger.warn(e, "error while writing player location for player: " + getPlayerName());
return false;
}
}
@ -79,8 +77,7 @@ public class Player {
loadLocation();
return true;
} catch (IOException | MojangApiParsingException e) {
Log.w("error while reading player location for player: " + getPlayerName());
e.printStackTrace();
AmidstLogger.warn(e, "error while reading player location for player: " + getPlayerName());
return false;
}
}

View File

@ -5,7 +5,7 @@ import java.util.concurrent.ConcurrentHashMap;
import amidst.documentation.NotNull;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
/**
* Even though this class is thread-safe, it is possible that the same player
@ -27,7 +27,7 @@ public class PlayerInformationCacheImpl implements PlayerInformationCache {
if (result != null) {
return result;
} else {
Log.i("requesting player information for uuid: " + cleanUUID);
AmidstLogger.info("requesting player information for uuid: " + cleanUUID);
result = PlayerInformation.fromUUID(cleanUUID);
put(result);
return result;
@ -41,7 +41,7 @@ public class PlayerInformationCacheImpl implements PlayerInformationCache {
if (result != null) {
return result;
} else {
Log.i("requesting player information for name: " + name);
AmidstLogger.info("requesting player information for name: " + name);
result = PlayerInformation.fromName(name);
put(result);
return result;

View File

@ -13,7 +13,7 @@ import java.util.TreeMap;
import amidst.documentation.GsonConstructor;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.world.biome.Biome;
import amidst.mojangapi.world.biome.BiomeColor;
@ -58,7 +58,7 @@ public class BiomeProfile {
public void validate() {
for (String biomeName : colorMap.keySet()) {
if (!Biome.exists(biomeName)) {
Log.i("Failed to find biome for: " + biomeName + " in profile: " + name);
AmidstLogger.info("Failed to find biome for: " + biomeName + " in profile: " + name);
}
}
}

View File

@ -10,13 +10,13 @@ import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
@Immutable
public class BiomeProfileDirectory {
public static BiomeProfileDirectory create(String root) {
BiomeProfileDirectory result = new BiomeProfileDirectory(getRoot(root));
Log.i("using biome profiles at: '" + result.getRoot() + "'");
AmidstLogger.info("using biome profiles at: '" + result.getRoot() + "'");
return result;
}
@ -53,15 +53,15 @@ public class BiomeProfileDirectory {
public void saveDefaultProfileIfNecessary() {
if (!isValid()) {
Log.i("Unable to find biome profile directory.");
AmidstLogger.info("Unable to find biome profile directory.");
} else {
Log.i("Found biome profile directory.");
AmidstLogger.info("Found biome profile directory.");
if (defaultProfile.isFile()) {
Log.i("Found default biome profile.");
AmidstLogger.info("Found default biome profile.");
} else if (BiomeProfile.getDefaultProfile().save(defaultProfile)) {
Log.i("Saved default biome profile.");
AmidstLogger.info("Saved default biome profile.");
} else {
Log.i("Attempted to save default biome profile, but encountered an error.");
AmidstLogger.info("Attempted to save default biome profile, but encountered an error.");
}
}
}
@ -101,8 +101,7 @@ public class BiomeProfileDirectory {
}
profile.validate();
} catch (JsonSyntaxException | JsonIOException | IOException | NullPointerException e) {
Log.w("Unable to load file: " + file);
e.printStackTrace();
AmidstLogger.warn(e, "Unable to load file: " + file);
}
}
return profile;

View File

@ -1,7 +1,8 @@
package amidst.settings.biomeprofile;
import amidst.documentation.ThreadSafe;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.world.biome.BiomeColor;
import amidst.mojangapi.world.biome.UnknownBiomeIndexException;
@ -17,8 +18,8 @@ public class BiomeProfileSelection {
try {
return getBiomeColor(index);
} catch (UnknownBiomeIndexException e) {
Log.e(e.getMessage());
e.printStackTrace();
AmidstLogger.error(e);
AmidstMessageBox.displayError("Error", e);
return BiomeColor.unknown();
}
}
@ -34,6 +35,6 @@ public class BiomeProfileSelection {
public void set(BiomeProfile biomeProfile) {
this.biomeColors = biomeProfile.createBiomeColorArray();
Log.i("Biome profile activated: " + biomeProfile.getName());
AmidstLogger.info("Biome profile activated: " + biomeProfile.getName());
}
}

View File

@ -7,7 +7,7 @@ import java.util.LinkedList;
import java.util.List;
import amidst.devtools.utils.RecognisedVersionEnumBuilder;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.mojangapi.file.FilenameFactory;
import amidst.mojangapi.file.directory.DotMinecraftDirectory;
import amidst.mojangapi.file.directory.VersionDirectory;
@ -58,7 +58,7 @@ public class GenerateRecognisedVersionList {
}
private void process(String versionId) throws MalformedURLException, ClassNotFoundException {
Log.i("version " + versionId);
AmidstLogger.info("version " + versionId);
VersionDirectory versionDirectory = createVersionDirectory(versionId);
URLClassLoader classLoader = versionDirectory.createClassLoader();
String magicString = RecognisedVersion.generateMagicString(classLoader);

View File

@ -0,0 +1,83 @@
package amidst.logging;
import org.junit.Assert;
import org.junit.Test;
public class MessageFormatterTest {
@Test
public void testEmptyMessage() {
String message = "";
String expected = "";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testSimplyMessage() {
String message = "{}";
String expected = "p1";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testBeforeMessage() {
String message = "{}m1";
String expected = "p1m1";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testAfterMessage() {
String message = "m1{}";
String expected = "m1p1";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testBetweenMessages() {
String message = "m1{}m2";
String expected = "m1p1m2";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testChain1() {
String message = "m1{}m2{}m3{}m4{}m5{}";
String expected = "m1p1m2p2m3p3m4p4m5p5";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2", "p3", "p4", "p5"));
}
@Test
public void testChain2() {
String message = "m1{}m2{}m3{}m4{}m5";
String expected = "m1p1m2p2m3p3m4p4m5";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2", "p3", "p4"));
}
@Test
public void testChain3() {
String message = "{}m1{}m2{}m3{}m4{}m5";
String expected = "p1m1p2m2p3m3p4m4p5m5";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2", "p3", "p4", "p5"));
}
@Test
public void testChain4() {
String message = "{}m1{}m2{}m3{}m4{}";
String expected = "p1m1p2m2p3m3p4m4p5";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2", "p3", "p4", "p5"));
}
@Test
public void testTooManyParts() {
String message = "m1{}m2";
String expected = "m1p1m2";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2"));
}
@Test
public void testTooFewParts() {
String message = "m1{}m2{}";
String expected = "m1p1m2{}";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
}

View File

@ -7,7 +7,8 @@ import java.util.function.Function;
import amidst.documentation.GsonConstructor;
import amidst.documentation.Immutable;
import amidst.logging.Log;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.mocking.FragmentCornerWalker;
import amidst.mojangapi.world.World;
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
@ -38,7 +39,9 @@ public class CoordinatesCollectionJson {
corner -> producer.produce(corner, consumer, additionalDataFactory.apply(corner)));
SortedSet<CoordinatesInWorld> coordinates = createSortedSet(consumer.get());
if (coordinates.size() < minimalNumberOfCoordinates) {
Log.e("not enough coordinates for '" + name + "'");
String message = "not enough coordinates for '" + name + "'";
AmidstLogger.error(message);
AmidstMessageBox.displayError("Error", message);
}
return new CoordinatesCollectionJson(coordinates);
}