Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Celeste64.Launcher/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ public static void Main(string[] args)
Version loaderVersion = typeof(Program).Assembly.GetName().Version!;
Game.LoaderVersion = $"Fuji: v.{loaderVersion.Major}.{loaderVersion.Minor}.{loaderVersion.Build}";
Game.IsDynamicRes = parsedArgs.Has("dynamic-res");
Game.AppArgs = parsedArgs; // Expose our parsed args to the game

// Expose our parsed args to the game
Game.AppArgs = parsedArgs;

LogHelper.Initialize();

if (!string.IsNullOrEmpty(BuildProperties.ModVersion()))
{
Game.LoaderVersion += "-" + BuildProperties.ModVersion();
Expand Down
2 changes: 1 addition & 1 deletion Source/Data/Assets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ internal static void LoadAssetsForMod(GameMod mod)

if (modFs == null)
{
Log.Error($"Error loading assets for {mod.ModInfo.Id}. Mod FileSystem not initialized.");
Log.Error($"Failed to load assets for {mod.ModInfo.Id}. Mod FileSystem not initialized.");
return;
}

Expand Down
3 changes: 1 addition & 2 deletions Source/Data/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,7 @@ public Map(string name, string virtPath, Stream stream)

readExceptionMessage = e.Message;

Log.Error($"Failed to load map {name}, more details below.");
Log.Error(e.ToString());
LogHelper.Error($"Failed to load map {name}", e);
}

if (Data != null)
Expand Down
2 changes: 1 addition & 1 deletion Source/Data/PersistedData/PersistedData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public virtual void Serialize(Utf8JsonWriter writer, object instance)
}
catch (Exception e)
{
Log.Error(e.ToString());
LogHelper.Error("Failed to load persisted data", e);
return null;
}
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Data/PersistedData/VersionedPersistedData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Celeste64;
}
catch (Exception e)
{
Log.Error(e.ToString());
LogHelper.Error("Failed to load versioned persisted data", e);
return null;
}
}
Expand Down
60 changes: 1 addition & 59 deletions Source/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ public override void Shutdown()
instance = null;

Log.Info("Shutting down...");
WriteToLog();
}

public bool IsMidTransition => transitionStep != TransitionStep.None;
Expand Down Expand Up @@ -284,65 +283,10 @@ private void HandleError(Exception e)
}

scenes.Clear();
Log.Error("== ERROR ==\n\n" + e.ToString());
WriteToLog();
LogHelper.Error("An Unhandled Exception occurred: ", e);
UnsafelySetScene(new GameErrorMessage(e));
}

// Fuji Custom
public static void WriteToLog()
{
if (!Settings.WriteLog)
{
return;
}

// construct a log message
const string LogFileName = "Log.txt";
StringBuilder log = new();
lock (Log.Logs)
log.AppendLine(Log.Logs.ToString());

// write to file
string path = LogFileName;
{
if (App.Running)
{
try
{
path = Path.Join(App.UserPath, LogFileName);
}
catch
{
path = LogFileName;
}
}

File.WriteAllText(path, log.ToString());
}
}

internal static void OpenLog()
{
const string LogFileName = "Log.txt";
string path = "";
if (App.Running)
{
try
{
path = Path.Join(App.UserPath, LogFileName);
}
catch
{
path = LogFileName;
}
}
if (File.Exists(path))
{
new Process { StartInfo = new ProcessStartInfo(path) { UseShellExecute = true } }.Start();
}
}

internal void ReloadAssets(bool reloadAll)
{
if (!scenes.TryPeek(out var scene))
Expand Down Expand Up @@ -629,8 +573,6 @@ public override void Update()
// in case new music was played
Settings.SyncSettings();
transitionStep = TransitionStep.FadeIn;

WriteToLog();
}
else if (transitionStep == TransitionStep.FadeIn)
{
Expand Down
113 changes: 113 additions & 0 deletions Source/Helpers/LogHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System.Diagnostics;
using System.Text;
namespace Celeste64;

/// <summary>
/// Fuji Custom
/// This class improves logging functionality by better distinguishing between info messages, warnings, and logs
/// It also provides functions for writing logs to the log file, and opening the log file
/// This wraps fosters Log events by subscribing to the OnInfo, OnWarn, and OnError events
/// </summary>
public static class LogHelper
{
public static readonly StringBuilder Logs = new StringBuilder();

public static void Initialize()
{
Log.OnInfo += Info;
Log.OnWarn += Warn;
Log.OnError += Error;
}

public static void Info(ReadOnlySpan<char> text)
{
Append(text);
Console.Out.WriteLine(text);
WriteToLog();
}

public static void Warn(ReadOnlySpan<char> text)
{
Append($"[Warning] {text}");
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Out.WriteLine($"[Warning] {text}");
Console.ResetColor();
WriteToLog();
}

public static void Error(ReadOnlySpan<char> text)
{
Append($"[Error] {text}");
Console.ForegroundColor = ConsoleColor.Red;
Console.Out.WriteLine($"[Error] {text}");
Console.ResetColor();
WriteToLog();
}

public static void Error(ReadOnlySpan<char> text, Exception ex)
{
Error($"{text}\n {ex}");
}

public static void WriteToLog()
{
if (!Settings.WriteLog)
{
return;
}

// construct a log message
const string LogFileName = "Log.txt";
StringBuilder log = new();
lock (Logs)
log.AppendLine(Logs.ToString());

// write to file
string path = LogFileName;
{
if (App.Running)
{
try
{
path = Path.Join(App.UserPath, LogFileName);
}
catch
{
path = LogFileName;
}
}

File.WriteAllText(path, log.ToString());
}
}

public static void OpenLog()
{
const string LogFileName = "Log.txt";
string path = "";
if (App.Running)
{
try
{
path = Path.Join(App.UserPath, LogFileName);
}
catch
{
path = LogFileName;
}
}
if (File.Exists(path))
{
new Process { StartInfo = new ProcessStartInfo(path) { UseShellExecute = true } }.Start();
}
}

public static void Append(ReadOnlySpan<char> message)
{
lock (Logs)
{
Logs.Append(message);
Logs.Append('\n');
}
}
}
6 changes: 2 additions & 4 deletions Source/Mod/Core/GameMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,7 @@ public bool SaveSettings()
}
catch (Exception e)
{
Log.Error($"Failed to save the settings of {ModInfo.Id}!");
Log.Error(e.Message);
LogHelper.Error($"Failed to save the settings of {ModInfo.Id}!", e);
return false;
}
}
Expand Down Expand Up @@ -219,8 +218,7 @@ public bool LoadSettings()
}
catch (Exception e)
{
Log.Error($"Failed to save the settings of {ModInfo.Id}!");
Log.Error(e.Message);
LogHelper.Error($"Failed to save the settings of {ModInfo.Id}!", e);
return false;
}
}
Expand Down
3 changes: 1 addition & 2 deletions Source/Mod/Core/ModLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,7 @@ internal static bool Load(ModInfo info, IModFilesystem fs)
catch (Exception ex)
{
FailedToLoadMods.Add(info.Id);
Log.Error($"Fuji Error: An error occurred while trying to load mod: {info.Id}");
Log.Error(ex.ToString());
LogHelper.Error($"Fuji Error: An error occurred while trying to load mod: {info.Id}", ex);

return false;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Mod/Helpers/SkinInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSeri
}
catch (Exception ex)
{
Log.Error("Error: Could not parse value in skin file: " + ex.ToString());
LogHelper.Error("Error: Could not parse value in skin file: ", ex);
return 0;
}
}
Expand Down
3 changes: 1 addition & 2 deletions Source/Mod/Menu/ModSelectionMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ internal ModSelectionMenu(Menu? rootMenu)
}));
FailedToLoadModsMenu.Add(new Option("FujiOpenLogFile", () =>
{
Game.WriteToLog();
Game.OpenLog();
LogHelper.OpenLog();
}));
}

Expand Down
3 changes: 1 addition & 2 deletions Source/Scenes/GameErrorMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ public GameErrorMessage(Exception e)

menu.Add(new Menu.Option("FujiOpenLogFile", () =>
{
Game.WriteToLog();
Game.OpenLog();
LogHelper.OpenLog();
}));

menu.Add(new Menu.Option("QuitToMainMenu", () =>
Expand Down
6 changes: 2 additions & 4 deletions Source/Scenes/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ public World(EntryInfo entry)

badMapWarningMenu.Add(new Menu.Option("FujiOpenLogFile", () =>
{
Game.WriteToLog();
Game.OpenLog();
LogHelper.OpenLog();
}));

badMapWarningMenu.Add(new Menu.Option("QuitToMainMenu", () => Game.Instance.Goto(new Transition()
Expand Down Expand Up @@ -522,8 +521,7 @@ public override void Update()
catch (Exception err)
{
string currentModName = ModManager.Instance.CurrentLevelMod != null && ModManager.Instance.CurrentLevelMod.ModInfo != null ? ModManager.Instance.CurrentLevelMod.ModInfo.Id : "unknown";
Log.Error($"--- ERROR in the map {currentModName}:{Entry.Map}. More details below ---");
Log.Error(err.ToString());
LogHelper.Error($"--- ERROR in the map {currentModName}:{Entry.Map}. More details below ---", err);

Panic(err, $"Oops, critical error :(\n{err.Message}\nYou can try to recover from this error by pressing Retry,\nbut we can't promise stability!", Panicked);
} // We wrap most of Update() in a try-catch to hopefully catch errors that occur during gameplay.
Expand Down