Commit c8bbad8b authored by pcy's avatar pcy
Browse files

stuff

parent ed2d8e61
......@@ -6,12 +6,14 @@ using System.Linq;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using log4net;
using MonoMod.Cil;
using ReLogic.OS;
using Terraria;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.ModLoader.Core;
using Terraria.ModLoader.Exceptions;
......@@ -42,7 +44,17 @@ namespace pcytest {
f_activelyModding =
t_modc.GetField("activelyModding", BindingFlags.Static | BindingFlags.Public),
f_prevExn =
typeof(Logging).GetField("previousException", BindingFlags.Static | BindingFlags.NonPublic);
typeof(Logging).GetField("previousException", BindingFlags.Static | BindingFlags.NonPublic),
f_pastExn =
typeof(Logging).GetField("pastExceptions", BindingFlags.Static | BindingFlags.NonPublic),
f_ignCnt =
typeof(Logging).GetField("ignoreContents" , BindingFlags.Static | BindingFlags.NonPublic),
f_ignSrc =
typeof(Logging).GetField("ignoreSources" , BindingFlags.Static | BindingFlags.NonPublic),
f_ignMsg =
typeof(Logging).GetField("ignoreMessages" , BindingFlags.Static | BindingFlags.NonPublic),
f_ignMtd =
typeof(Logging).GetField("ignoreThrowingMethods", BindingFlags.Static | BindingFlags.NonPublic);
static readonly PropertyInfo p_modc_devmode =
t_modc.GetProperty("DeveloperMode", BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty);
......@@ -53,6 +65,12 @@ namespace pcytest {
static string thisModName;
public static HashSet<string> IgnoreSources => (HashSet<string>)f_ignSrc .GetValue(null);
public static List <string> IgnoreContents => (List <string>)f_ignCnt .GetValue(null);
public static List <string> IgnoreMessages => (List <string>)f_ignMsg .GetValue(null);
public static List<string> IgnoreThrowingMethods => (List<string>)f_ignMtd.GetValue(null);
public static HashSet<string> PastExceptions => (HashSet<string>)f_pastExn.GetValue(null);
static ILog tML_bf;
public static ILog tML {
get {
......@@ -106,9 +124,14 @@ namespace pcytest {
return (bool)f_sb_inBEP.GetValue(sb);
}
public static bool DeveloperMode => (bool)p_modc_devmode.GetValue(null);
public static Exception PreviousException => (Exception)f_prevExn.GetValue(null);
public static Exception PreviousException {
get { return (Exception)f_prevExn.GetValue(null); }
set { f_prevExn.SetValue(null, value); }
}
public static void MessageBoxShow(string message, string caption) {
public static void MessageBoxShow(string message, string caption = null) {
caption = caption ??
("Terraria: Error (" + ModLoader.versionedName + ")");
m_uiintf_msgbox.Invoke(null, new[]{message, caption});
}
public static bool GetAsmOwner(Assembly asm, out string modName) {
......@@ -321,11 +344,6 @@ namespace pcytest {
static void Edit_TryResolveLocation(ILContext il) {
var c = new ILCursor(il);
if (!c.TryGotoNext(i => i.MatchLdloc(3))) {
tML.Error("yikes, no ldloc.3!");
return;
}
/*
* code looks like this:
*
......@@ -337,7 +355,7 @@ namespace pcytest {
* ; ^ may return nulll!
* stloc.3
* 0x52:
* ldloc.3
* ldloc.3 ; the search target
* callvirt MethodDebugInformation::get_HasSequencePoints()
* ; ^ nullrefexn happens here!
* brtrue.s 0x5C
......@@ -355,10 +373,10 @@ namespace pcytest {
* callvirt MdbReader::Read()
* stloc.3
* 0x52:
* ->ldloc.3
* ldloc.3 ; the search target
* ->brfalse.s 0x5D
* ; ^ == null check
* ldloc.3
* ->ldloc.3
* callvirt MethodDebugInformation::get_HasSequencePoints()
* brtrue.s 0x5F
* 0x5F:
......@@ -368,23 +386,109 @@ namespace pcytest {
* ...
*/
if (!c.TryGotoNext(i => i.MatchLdloc(3))) {
tML.Error("yikes, no ldloc.3!");
return;
}
c.Index++;
// we're behind the ldloc.3
var lbl = c.DefineLabel();
c.Emit(Brfalse_S, lbl); // 2 byte
c.Emit(Ldloc_3);
c.Emit(Brfalse_S, lbl); // 2 bytes
c.Emit(Ldloc_3); // 1 byte
c.Index++; // callvirt
c.Index++; // brtrue.s
c.MarkLabel(lbl); // ldc.i4.0
}
// TODO: MAYBE we could just override AppDomain.FirstChanceException
// directly?? (tho: how to remove the previous one?)
// see also: System.Delegate: Delegate RemoveAll (Delegate source, Delegate value)
// Event.GetInvocationList()
/*static Delegate[] DisableEvents(this Control ctrl, string eventName) {
PropertyInfo propertyInfo = ctrl.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
EventHandlerList eventHandlerList = propertyInfo.GetValue(ctrl, new object[] { }) as EventHandlerList;
FieldInfo fieldInfo = typeof(Control).GetField("Event"+eventName, BindingFlags.NonPublic | BindingFlags.Static);
object eventKey = fieldInfo.GetValue(ctrl);
var eventHandler = eventHandlerList[eventKey] as Delegate;
Delegate[] invocationList = eventHandler.GetInvocationList();
foreach (EventHandler item in invocationList)
ctrl.GetType().GetEvent(eventName).RemoveEventHandler(ctrl, item);
return invocationList;
}*/
static bool inFCEH = false;
static void Hook_FirstChanceExceptionHandler(
On.Terraria.ModLoader.Logging.orig_FirstChanceExceptionHandler
orig, object sender, FirstChanceExceptionEventArgs fceea) {
previousererExn = previouserExn;
previouserExn = PreviousException;
orig(sender, fceea);
if (inFCEH) return;
var e = fceea.Exception;
bool oom = e is OutOfMemoryException;
// In case of OOM, unload the Main.tile array and do immediate
// garbage collection. If we don't do this, there will be a big
// chance that this method will fail to even quit the game, due to
// another OOM exception being thrown.
if (oom) {
Main.tile = null;
GC.Collect();
}
try {
inFCEH = true;
//orig(sender, fceea);
if (!oom) {
if (e == PreviousException || e is ThreadAbortException
|| IgnoreSources.Contains(e.Source)
|| IgnoreMessages.Any(s => e.Message?.Contains(s) ?? false)
|| IgnoreThrowingMethods.Any(s => e.StackTrace?.Contains(s) ?? false))
return;
}
var stackTrace = new StackTrace(true);
//Logging.PrettifyStackTraceSources(stackTrace.GetFrames());
Hook_PrettifyStackTraceSources(null, stackTrace.GetFrames());
var traceString = stackTrace.ToString();
if (!oom && IgnoreContents.Any(traceString.Contains))
return;
traceString = traceString.Substring(traceString.IndexOf('\n'));
string offendingStr = BuildOffendingModsString(e);
var exString = e.GetType() + ": " + e.Message + offendingStr
+ traceString;
lock (PastExceptions) {
if (!PastExceptions.Add(exString)) return;
}
previousererExn = previouserExn;
previouserExn = PreviousException;
PreviousException = e;
var msg = e.Message + offendingStr + " "
+ Language.GetTextValue("tModLoader.RuntimeErrorSeeLogsForFullTrace",
Path.GetFileName(Logging.LogPath));
if (ActivelyModding) AddChatMessage(msg, Color.OrangeRed);
tML.Warn(Language.GetTextValue("tModLoader.RuntimeErrorSilentlyCaughtException")
+ '\n' + exString);
if (oom) {
MessageBoxShow("Game ran out of memory. You'll have to "
+ "find which mod is consuming lots of memory, and"
+ " contact the devs or remove it. (or go and "
+ "find the 64-bit version of tML)");
Environment.Exit(1);
}
} catch {
tML.Warn("FirstChanceExceptionHandler exception", e);
} finally {
inFCEH = false;
}
}
readonly static string usageFaqUrl =
......@@ -439,8 +543,11 @@ namespace pcytest {
orig, NPC npc) {
bool rv = orig(npc);
if (npc.modNPC == null && rv) {
var trace = new StackTrace(true);
//Logging.PrettifyStackTraceSources(trace.GetFrames());
Hook_PrettifyStackTraceSources(null, trace.GetFrames());
tML.Warn("W: NPC " + npc + " type=" + npc.type + " modNPC is null!");
tML.Warn(new StackTrace(true).ToString());
tML.Warn(trace.ToString());
AddChatMessage("W: NPC " + npc + " type=" + npc.type + " modNPC is null!", Color.OrangeRed);
}
return rv;
......@@ -454,9 +561,12 @@ namespace pcytest {
SpriteSortMode a, BlendState b, SamplerState c,
DepthStencilState d, RasterizerState e, Effect f, Matrix g) {
if (IsInBeginEndPair(self)) {
var trace = lastBegin[self];
//Logging.PrettifyStackTraceSources(trace.GetFrames());
Hook_PrettifyStackTraceSources(null, trace.GetFrames());
tML.Warn("Called SpriteBatch.Begin after already having " +
"called Begin before, prev. stacktrace:\n" +
lastBegin[self]);
trace);
} else lastBegin[self] = new StackTrace(true);
orig(self, a, b, c, d, e, f, g);
}
......@@ -464,9 +574,12 @@ namespace pcytest {
On.Microsoft.Xna.Framework.Graphics.SpriteBatch.orig_End orig,
SpriteBatch self) {
if (!IsInBeginEndPair(self)) {
var trace = lastEnd[self];
//Logging.PrettifyStackTraceSources(trace.GetFrames());
Hook_PrettifyStackTraceSources(null, trace.GetFrames());
tML.Warn("Called SpriteBatch.End after already having " +
"called End before, prev. stacktrace:\n" +
lastEnd[self]);
trace);
} else lastEnd[self] = new StackTrace(true);
orig(self);
}
......@@ -494,8 +607,9 @@ namespace pcytest {
Hook_TryResolveLocation;*/
On.Terraria.ModLoader.Logging.FirstChanceExceptionHandler +=
Hook_FirstChanceExceptionHandler;
IL.Terraria.ModLoader.Core.MdbManager.TryResolveLocation +=
Edit_TryResolveLocation;
// TODO: only if <=0.11.7.2
/*IL.Terraria.ModLoader.Core.MdbManager.TryResolveLocation +=
Edit_TryResolveLocation;*/
On.Terraria.Program.DisplayException += Hook_DisplayException;
On.Terraria.ModLoader.NPCLoader.IsModNPC += Hook_IsModNPC;
// NOTE: enabling these causes a HUGE hit in performance!
......@@ -519,8 +633,9 @@ namespace pcytest {
Hook_TryResolveLocation;*/
On.Terraria.ModLoader.Logging.FirstChanceExceptionHandler -=
Hook_FirstChanceExceptionHandler;
IL.Terraria.ModLoader.Core.MdbManager.TryResolveLocation -=
Edit_TryResolveLocation;
// TODO: only if <=0.11.7.2
/*IL.Terraria.ModLoader.Core.MdbManager.TryResolveLocation -=
Edit_TryResolveLocation;*/
On.Terraria.Program.DisplayException -= Hook_DisplayException;
// NOTE: enabling these causes a HUGE hit in performance!
/*On.Terraria.ModLoader.NPCLoader.IsModNPC -= Hook_IsModNPC;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment