improved crash reports more

This commit is contained in:
LAX1DUDE 2022-10-17 16:03:34 -07:00
parent 31fd9ef2b1
commit 60896b7a30
3 changed files with 122 additions and 61 deletions

View File

@ -2,12 +2,12 @@ package net.lax1dude.eaglercraft;
import static org.teavm.jso.webgl.WebGLRenderingContext.*; import static org.teavm.jso.webgl.WebGLRenderingContext.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSExceptions;
import org.teavm.jso.JSFunctor;
import org.teavm.jso.JSObject;
import org.teavm.jso.browser.Window; import org.teavm.jso.browser.Window;
import org.teavm.jso.core.JSError; import org.teavm.jso.core.JSError;
import org.teavm.jso.dom.html.HTMLCanvasElement; import org.teavm.jso.dom.html.HTMLCanvasElement;
@ -71,22 +71,22 @@ public class Client {
String serverWorkerURI = conf.optString("serverWorkerURI", null); String serverWorkerURI = conf.optString("serverWorkerURI", null);
EaglerAdapterImpl2.setWorldDatabaseName(conf.optString("worldsFolder", "MAIN")); EaglerAdapterImpl2.setWorldDatabaseName(conf.optString("worldsFolder", "MAIN"));
registerErrorHandler();
try { try {
EaglerAdapterImpl2.initializeContext(rootElement, assetsURI, serverWorkerURI); EaglerAdapterImpl2.initializeContext(rootElement, assetsURI, serverWorkerURI);
ServerList.loadDefaultServers(conf);
AssetRepository.loadOverrides(conf);
LocalStorageManager.loadStorage();
run0();
}catch(Throwable t) { }catch(Throwable t) {
StringWriter s = new StringWriter(); showCrashScreen(t.toString() + "\n\n" + getStackTrace(t));
t.printStackTrace(new PrintWriter(s));
showCrashScreen(s.toString());
return; return;
} }
registerErrorHandler();
ServerList.loadDefaultServers(conf);
AssetRepository.loadOverrides(conf);
LocalStorageManager.loadStorage();
run0();
} }
private static void oldMain() { private static void oldMain() {
@ -100,23 +100,37 @@ public class Client {
crashScreenOptsDump += "\"" + sh + "\""; crashScreenOptsDump += "\"" + sh + "\"";
} }
crashScreenOptsDump += " ]"; crashScreenOptsDump += " ]";
registerErrorHandler();
try { try {
EaglerAdapterImpl2.initializeContext(rootElement = Window.current().getDocument().getElementById(e[0]), e[1], "worker_bootstrap.js"); EaglerAdapterImpl2.initializeContext(rootElement = Window.current().getDocument().getElementById(e[0]), e[1], "worker_bootstrap.js");
LocalStorageManager.loadStorage();
if(e.length > 2 && e[2].length() > 0) {
ServerList.loadDefaultServers(e[2]);
}
if(e.length > 3) {
EaglerAdapterImpl2.setServerToJoinOnLaunch(e[3]);
}
run0();
}catch(Throwable t) { }catch(Throwable t) {
StringWriter s = new StringWriter(); showCrashScreen(t.toString() + "\n\n" + getStackTrace(t));
t.printStackTrace(new PrintWriter(s));
showCrashScreen(s.toString());
return; return;
} }
registerErrorHandler(); }
LocalStorageManager.loadStorage();
if(e.length > 2 && e[2].length() > 0) { private static String getStackTrace(Throwable t) {
ServerList.loadDefaultServers(e[2]); JSObject obj = JSExceptions.getJSException(t);
if(obj != null) {
JSError err = (JSError)obj;
return err.getStack() == null ? "[no stack trace]" : err.getStack();
}else {
return "[no stack trace]";
} }
if(e.length > 3) {
EaglerAdapterImpl2.setServerToJoinOnLaunch(e[3]);
}
run0();
} }
private static void run0() { private static void run0() {
@ -132,28 +146,50 @@ public class Client {
@JSBody(params = { }, script = "return window.minecraftOpts;") @JSBody(params = { }, script = "return window.minecraftOpts;")
public static native String[] getOpts(); public static native String[] getOpts();
@JSBody(params = { }, script = "window.minecraftError = null; window.onerror = function(message, file, line, column, errorObj) { if(errorObj) { window.minecraftError = errorObj; window.minecraftErrorL = \"\"+line+\":\"+column; javaMethods.get(\"net.lax1dude.eaglercraft.Client.handleNativeError()V\").invoke(); } else { alert(\"a native browser exception was thrown but your browser does not support fith argument in onerror\"); } };") public static void registerErrorHandler() {
public static native void registerErrorHandler(); setWindowErrorHandler(new WindowErrorHandler() {
@JSBody(params = { }, script = "return window.minecraftError;") @Override
public static native JSError getWindowError(); public void call(String message, String file, int line, int col, JSError error) {
StringBuilder str = new StringBuilder();
@JSBody(params = { }, script = "return window.minecraftErrorL;") str.append("Native Browser Exception\n");
public static native String getWindowErrorL(); str.append("----------------------------------\n");
str.append(" Line: ").append((file == null ? "unknown" : file) + ":" + line + ":" + col).append('\n');
str.append(" Type: ").append(error == null ? "generic" : error.getName()).append('\n');
public static void handleNativeError() { if(error != null) {
JSError e = getWindowError(); str.append(" Desc: ").append(error.getMessage() == null ? "null" : error.getMessage()).append('\n');
StringBuilder str = new StringBuilder(); }
str.append("Native Browser Exception\n");
str.append("----------------------------------\n"); if(message != null) {
str.append(" Line: ").append(getWindowErrorL()).append('\n'); if(error == null || error.getMessage() == null || !message.endsWith(error.getMessage())) {
str.append(" Type: ").append(e.getName()).append('\n'); str.append(" Desc: ").append(message).append('\n');
str.append(" Message: ").append(e.getMessage()).append('\n'); }
str.append("----------------------------------\n\n"); }
str.append(e.getStack()).append('\n');
showCrashScreen(str.toString()); str.append("----------------------------------\n\n");
str.append(error.getStack() == null ? "No stack trace is available" : error.getStack()).append('\n');
showCrashScreen(str.toString());
}
});
} }
@JSFunctor
private static interface WindowErrorHandler extends JSObject {
void call(String message, String file, int line, int col, JSError error);
}
@JSBody(params = { "handler" }, script = "window.addEventListener(\"error\", function(e) { handler("
+ "(typeof e.message === \"string\") ? e.message : null,"
+ "(typeof e.filename === \"string\") ? e.filename : null,"
+ "(typeof e.lineno === \"number\") ? e.lineno : 0,"
+ "(typeof e.colno === \"number\") ? e.colno : 0,"
+ "(typeof e.error === \"undefined\") ? null : e.error); });")
public static native void setWindowErrorHandler(WindowErrorHandler handler);
private static boolean isCrashed = false; private static boolean isCrashed = false;
private static void showCrashScreen(String t) { private static void showCrashScreen(String t) {
@ -166,7 +202,7 @@ public class Client {
str.append('\n').append('\n'); str.append('\n').append('\n');
str.append("eaglercraft.version = \"").append(ConfigConstants.version).append("\"\n"); str.append("eaglercraft.version = \"").append(ConfigConstants.version).append("\"\n");
str.append("eaglercraft.minecraft = \"1.5.2\"\n"); str.append("eaglercraft.minecraft = \"1.5.2\"\n");
str.append("eaglercraft.brand = \"eagtek\"\n"); str.append("eaglercraft.brand = \"lax1dude\"\n");
str.append("eaglercraft.username = \"").append(EaglerProfile.username).append("\"\n"); str.append("eaglercraft.username = \"").append(EaglerProfile.username).append("\"\n");
str.append('\n'); str.append('\n');
str.append(addWebGLToCrash()); str.append(addWebGLToCrash());
@ -193,8 +229,6 @@ public class Client {
addDebugScreen(str, "colorDepth"); addDebugScreen(str, "colorDepth");
addDebugScreen(str, "pixelDepth"); addDebugScreen(str, "pixelDepth");
str.append('\n'); str.append('\n');
addDebug(str, "currentContext");
str.append('\n');
addDebugLocation(str, "href"); addDebugLocation(str, "href");
str.append("\n----- Begin Minecraft Config -----\n"); str.append("\n----- Begin Minecraft Config -----\n");
str.append(LocalStorageManager.dumpConfiguration()); str.append(LocalStorageManager.dumpConfiguration());
@ -221,14 +255,14 @@ public class Client {
private static String addWebGLToCrash() { private static String addWebGLToCrash() {
StringBuilder ret = new StringBuilder(); StringBuilder ret = new StringBuilder();
HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas");
cvs.setWidth(64);
cvs.setHeight(64);
WebGLRenderingContext ctx = EaglerAdapterImpl2.webgl; WebGLRenderingContext ctx = EaglerAdapterImpl2.webgl;
if(ctx == null) { if(ctx == null) {
HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas");
cvs.setWidth(64);
cvs.setHeight(64);
ctx = (WebGLRenderingContext)cvs.getContext("webgl"); ctx = (WebGLRenderingContext)cvs.getContext("webgl");
} }
@ -236,8 +270,14 @@ public class Client {
if(EaglerAdapterImpl2.webgl != null) { if(EaglerAdapterImpl2.webgl != null) {
ret.append("webgl.version = ").append(ctx.getParameterString(VERSION)).append('\n'); ret.append("webgl.version = ").append(ctx.getParameterString(VERSION)).append('\n');
} }
ret.append("webgl.renderer = ").append(ctx.getParameterString(RENDERER)).append('\n'); if(ctx.getExtension("WEBGL_debug_renderer_info") != null) {
ret.append("webgl.vendor = ").append(ctx.getParameterString(VENDOR)).append('\n'); ret.append("webgl.renderer = ").append(ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246)).append('\n');
ret.append("webgl.vendor = ").append(ctx.getParameterString(/* UNMASKED_VENDOR_WEBGL */ 0x9245)).append('\n');
}else {
ret.append("webgl.renderer = ").append("" + ctx.getParameterString(RENDERER) + " [masked]").append('\n');
ret.append("webgl.vendor = ").append("" + ctx.getParameterString(VENDOR) + " [masked]").append('\n');
}
ret.append("\nwebgl.anisotropicGlitch = ").append(DetectAnisotropicGlitch.hasGlitch()).append('\n');
}else { }else {
ret.append("Failed to query GPU info!\n"); ret.append("Failed to query GPU info!\n");
} }
@ -292,7 +332,15 @@ public class Client {
WebGLRenderingContext ctx = (WebGLRenderingContext)cvs.getContext("webgl"); WebGLRenderingContext ctx = (WebGLRenderingContext)cvs.getContext("webgl");
if(ctx != null) { if(ctx != null) {
String r = ctx.getParameterString(RENDERER); String r;
if(ctx.getExtension("WEBGL_debug_renderer_info") != null) {
r = ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246);
}else {
r = ctx.getParameterString(RENDERER);
if(r != null) {
r += " [masked]";
}
}
if(r != null) { if(r != null) {
webGLRenderer = r; webGLRenderer = r;
} }

View File

@ -15,7 +15,18 @@ import org.teavm.jso.webgl.*;
public class DetectAnisotropicGlitch { public class DetectAnisotropicGlitch {
public static boolean detectGlitch() { private static boolean known = false;
private static boolean detected = false;
public static boolean hasGlitch() {
if(!known) {
detected = detect();
known = true;
}
return detected;
}
public static boolean detect() {
HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas");
cvs.setWidth(400); cvs.setWidth(400);

View File

@ -1032,7 +1032,7 @@ public class EaglerAdapterImpl2 {
return getNavString("platform").toLowerCase().contains("win"); return getNavString("platform").toLowerCase().contains("win");
} }
public static final boolean glNeedsAnisotropicFix() { public static final boolean glNeedsAnisotropicFix() {
return anisotropicFilteringSupported && DetectAnisotropicGlitch.detectGlitch(); return anisotropicFilteringSupported && DetectAnisotropicGlitch.hasGlitch();
} }
private static HTMLCanvasElement imageLoadCanvas = null; private static HTMLCanvasElement imageLoadCanvas = null;
@ -1076,13 +1076,15 @@ public class EaglerAdapterImpl2 {
Uint8ClampedArray pxls = pxlsDat.getData(); Uint8ClampedArray pxls = pxlsDat.getData();
int totalPixels = pxlsDat.getWidth() * pxlsDat.getHeight(); int totalPixels = pxlsDat.getWidth() * pxlsDat.getHeight();
freeDataURL(toLoad.getSrc()); freeDataURL(toLoad.getSrc());
if(pxls.getByteLength() < totalPixels * 4) { if(pxls.getByteLength() < totalPixels << 2) {
ret.complete(null); ret.complete(null);
return; return;
} }
DataView dv = DataView.create(pxls.getBuffer());
int[] pixels = new int[totalPixels]; int[] pixels = new int[totalPixels];
for(int i = 0; i < pixels.length; ++i) { for(int i = 0, j; i < pixels.length; ++i) {
pixels[i] = (pxls.get(i * 4) << 16) | (pxls.get(i * 4 + 1) << 8) | pxls.get(i * 4 + 2) | (pxls.get(i * 4 + 3) << 24); j = dv.getUint32(i << 2, false);
pixels[i] = (j >> 8) | ((j & 0xFF) << 24);
} }
ret.complete(new EaglerImage(pixels, pxlsDat.getWidth(), pxlsDat.getHeight(), true)); ret.complete(new EaglerImage(pixels, pxlsDat.getWidth(), pxlsDat.getHeight(), true));
} }