using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("HowToFish.ModConsole")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HowToFish.ModConsole")]
[assembly: AssemblyTitle("HowToFish.ModConsole")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HowToFish.ModConsole;
internal static class CommandLineTokenizer
{
internal static bool TryTokenize(string line, out string[] tokens, out string error)
{
List<string> list = new List<string>();
StringBuilder stringBuilder = new StringBuilder();
bool flag = false;
bool flag2 = false;
string text = line ?? string.Empty;
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
switch (c)
{
case '"':
flag = !flag;
flag2 = true;
continue;
case '\\':
if (i + 1 < text.Length)
{
char c2 = text[i + 1];
if (c2 == '"' || c2 == '\\' || char.IsWhiteSpace(c2))
{
stringBuilder.Append(c2);
flag2 = true;
i++;
continue;
}
}
break;
}
if (!flag && char.IsWhiteSpace(c))
{
if (flag2)
{
list.Add(stringBuilder.ToString());
stringBuilder.Length = 0;
flag2 = false;
}
}
else
{
stringBuilder.Append(c);
flag2 = true;
}
}
if (flag)
{
tokens = null;
error = "A quoted argument was not closed.";
return false;
}
if (flag2)
{
list.Add(stringBuilder.ToString());
}
tokens = list.ToArray();
error = null;
return true;
}
}
internal sealed class CommandDefinition
{
internal long Id;
internal string OwnerGuid;
internal string Name;
internal string Description;
internal string Usage;
internal string[] Aliases;
internal Func<string[], string> Handler;
}
internal sealed class CommandRegistry
{
private sealed class Registration : IDisposable
{
private CommandRegistry _registry;
private readonly long _id;
internal Registration(CommandRegistry registry, long id)
{
_registry = registry;
_id = id;
}
public void Dispose()
{
CommandRegistry registry = _registry;
_registry = null;
registry?.Remove(_id);
}
}
private readonly object _gate = new object();
private readonly Dictionary<string, CommandDefinition> _lookup = new Dictionary<string, CommandDefinition>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<long, CommandDefinition> _registrations = new Dictionary<long, CommandDefinition>();
private long _nextId;
internal IDisposable Register(string ownerGuid, string name, string description, string usage, Func<string[], string> handler, params string[] aliases)
{
string canonical = NormalizeName(name);
if (string.IsNullOrWhiteSpace(ownerGuid))
{
throw new ArgumentException("ownerGuid is required.", "ownerGuid");
}
if (handler == null)
{
throw new ArgumentNullException("handler");
}
string[] array = (from alias in (aliases ?? Array.Empty<string>()).Where((string alias) => !string.IsNullOrWhiteSpace(alias)).Select(NormalizeName).Distinct<string>(StringComparer.OrdinalIgnoreCase)
where !alias.Equals(canonical, StringComparison.OrdinalIgnoreCase)
select alias).ToArray();
lock (_gate)
{
if (_lookup.ContainsKey(canonical))
{
throw new InvalidOperationException("Command '" + canonical + "' is already registered.");
}
string[] array2 = array;
foreach (string text in array2)
{
if (_lookup.ContainsKey(text))
{
throw new InvalidOperationException("Alias '" + text + "' is already registered.");
}
}
CommandDefinition commandDefinition = new CommandDefinition
{
Id = ++_nextId,
OwnerGuid = ownerGuid,
Name = canonical,
Description = (description ?? string.Empty),
Usage = (string.IsNullOrWhiteSpace(usage) ? canonical : usage.Trim()),
Aliases = array,
Handler = handler
};
_registrations.Add(commandDefinition.Id, commandDefinition);
_lookup.Add(commandDefinition.Name, commandDefinition);
array2 = commandDefinition.Aliases;
foreach (string key in array2)
{
_lookup.Add(key, commandDefinition);
}
return new Registration(this, commandDefinition.Id);
}
}
internal string Execute(string line)
{
if (!CommandLineTokenizer.TryTokenize(line, out var tokens, out var error))
{
return "ERRO: " + error;
}
if (tokens.Length == 0)
{
return string.Empty;
}
CommandDefinition value;
lock (_gate)
{
_lookup.TryGetValue(tokens[0], out value);
}
if (value == null)
{
return "Unknown command: " + tokens[0] + ". Use help.";
}
string[] array = new string[tokens.Length - 1];
Array.Copy(tokens, 1, array, 0, array.Length);
try
{
return value.Handler(array) ?? string.Empty;
}
catch (Exception ex)
{
return "ERROR in " + value.Name + ": " + ex.GetBaseException().Message;
}
}
internal CommandDefinition[] Snapshot()
{
lock (_gate)
{
return _registrations.Values.OrderBy<CommandDefinition, string>((CommandDefinition command) => command.Name, StringComparer.OrdinalIgnoreCase).ToArray();
}
}
internal CommandDefinition Find(string name)
{
lock (_gate)
{
_lookup.TryGetValue(name ?? string.Empty, out var value);
return value;
}
}
internal string[] Complete(string prefix)
{
string value = (prefix ?? string.Empty).Trim();
lock (_gate)
{
return _lookup.Keys.Where((string name) => name.StartsWith(value, StringComparison.OrdinalIgnoreCase)).OrderBy<string, string>((string name) => name, StringComparer.OrdinalIgnoreCase).ToArray();
}
}
private void Remove(long id)
{
lock (_gate)
{
if (_registrations.TryGetValue(id, out var value))
{
_registrations.Remove(id);
_lookup.Remove(value.Name);
string[] aliases = value.Aliases;
foreach (string key in aliases)
{
_lookup.Remove(key);
}
}
}
}
private static string NormalizeName(string value)
{
string text = (value ?? string.Empty).Trim().ToLowerInvariant();
if (text.Length == 0)
{
throw new ArgumentException("Command name is required.", "value");
}
string text2 = text;
foreach (char c in text2)
{
if (!char.IsLetterOrDigit(c) && c != '_' && c != '-' && c != '.' && c != '?')
{
throw new ArgumentException("Invalid command name: " + text, "value");
}
}
return text;
}
}
internal sealed class ConsoleOverlay : IDisposable
{
private const string InputControlName = "HowToFish.ModConsole.Input";
private readonly ManualLogSource _log;
private readonly ConfigEntry<KeyCode> _toggleKey;
private readonly ConfigEntry<int> _maxLines;
private readonly List<string> _lines = new List<string>();
private readonly List<string> _history = new List<string>();
private readonly string _historyPath;
private string _input = string.Empty;
private string _historyDraft = string.Empty;
private int _historyIndex;
private Vector2 _scroll;
private Rect _windowRect;
private bool _requestFocus;
private bool _scrollToBottom;
private int _openedFrame = -1;
private CursorLockMode _previousCursorLock;
private bool _previousCursorVisible;
private PlayerInput _playerInput;
private bool _playerInputWasActive;
private Texture2D _background;
private GUIStyle _windowStyle;
private GUIStyle _titleStyle;
private GUIStyle _lineStyle;
private GUIStyle _inputStyle;
internal ConsoleOverlay(ManualLogSource log, ConfigEntry<KeyCode> toggleKey, ConfigEntry<int> maxLines)
{
_log = log;
_toggleKey = toggleKey;
_maxLines = maxLines;
_historyPath = Path.Combine(Paths.ConfigPath, "fernando.howtofish.modconsole.history.txt");
LoadHistory();
_historyIndex = _history.Count;
AddLine("Console Mod 1.0.0 ready. Type help to list commands.", "info");
}
internal void Tick()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
ModConsoleApi.DrainPending(AddLine);
if (Input.GetKeyDown(_toggleKey.Value))
{
if (ModConsoleApi.IsOpen || !ChatManager.IsTyping)
{
SetOpen(!ModConsoleApi.IsOpen);
}
}
else
{
_ = ModConsoleApi.IsOpen;
}
}
internal void Draw()
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Invalid comparison between Unknown and I4
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Invalid comparison between Unknown and I4
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Expected O, but got Unknown
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
if (!ModConsoleApi.IsOpen)
{
return;
}
Event current = Event.current;
if ((int)current.type == 4 && (current.keyCode == _toggleKey.Value || ((int)_toggleKey.Value == 96 && current.character == '`')))
{
if (Time.frameCount != _openedFrame)
{
SetOpen(open: false);
}
current.Use();
if (!ModConsoleApi.IsOpen)
{
return;
}
}
EnsureStyles();
if (((Rect)(ref _windowRect)).width <= 0f || ((Rect)(ref _windowRect)).height <= 0f || ((Rect)(ref _windowRect)).xMax > (float)Screen.width + 2f)
{
_windowRect = new Rect((float)Screen.width * 0.08f, 28f, (float)Screen.width * 0.84f, Mathf.Max(310f, (float)Screen.height * 0.54f));
}
_windowRect = GUI.Window(4001890, _windowRect, new WindowFunction(DrawWindow), GUIContent.none, _windowStyle);
}
private void DrawWindow(int id)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Invalid comparison between Unknown and I4
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Invalid comparison between Unknown and I4
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Invalid comparison between Unknown and I4
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Invalid comparison between Unknown and I4
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Invalid comparison between Unknown and I4
//IL_028f: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Unknown result type (might be due to invalid IL or missing references)
//IL_020a: Invalid comparison between Unknown and I4
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: Invalid comparison between Unknown and I4
//IL_0222: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Invalid comparison between Unknown and I4
//IL_0239: Unknown result type (might be due to invalid IL or missing references)
//IL_023f: Invalid comparison between Unknown and I4
//IL_0250: Unknown result type (might be due to invalid IL or missing references)
//IL_0253: Invalid comparison between Unknown and I4
//IL_0263: Unknown result type (might be due to invalid IL or missing references)
//IL_0266: Invalid comparison between Unknown and I4
Event current = Event.current;
bool flag = (int)current.type == 4 && (GUI.GetNameOfFocusedControl() == "HowToFish.ModConsole.Input" || (int)current.keyCode == 27);
KeyCode val = (KeyCode)(flag ? ((int)current.keyCode) : 0);
GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
GUILayout.Label("HOW TO FISH • CONSOLE DE MODS", _titleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) });
_scroll = GUILayout.BeginScrollView(_scroll, false, true, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
foreach (string line in _lines)
{
GUILayout.Label(line, _lineStyle, Array.Empty<GUILayoutOption>());
}
if (_scrollToBottom && (int)Event.current.type == 7)
{
_scroll.y = float.MaxValue;
_scrollToBottom = false;
}
GUILayout.EndScrollView();
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label(">", _titleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(18f) });
GUI.SetNextControlName("HowToFish.ModConsole.Input");
string input = _input;
_input = GUILayout.TextField(_input, 4096, _inputStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
bool flag2 = (int)_toggleKey.Value == 96 && _input == input + "`";
if (flag2)
{
_input = input;
}
GUILayout.EndHorizontal();
GUILayout.Label("Enter runs • ↑/↓ history • Tab completes • Esc closes", _lineStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(21f) });
GUILayout.EndVertical();
if (flag2)
{
SetOpen(open: false);
current.Use();
return;
}
if (_requestFocus && (int)Event.current.type == 7)
{
GUI.FocusControl("HowToFish.ModConsole.Input");
_requestFocus = false;
}
if (flag)
{
if ((int)val == 13 || (int)val == 271)
{
ExecuteInput();
current.Use();
}
else if ((int)val == 273)
{
NavigateHistory(-1);
current.Use();
}
else if ((int)val == 274)
{
NavigateHistory(1);
current.Use();
}
else if ((int)val == 9)
{
CompleteInput();
current.Use();
}
else if ((int)val == 27)
{
SetOpen(open: false);
current.Use();
}
}
GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, 30f));
}
internal void AddLine(string text, string level)
{
string text2 = (string.Equals(level, "error", StringComparison.OrdinalIgnoreCase) ? "[ERRO] " : (string.Equals(level, "warning", StringComparison.OrdinalIgnoreCase) ? "[AVISO] " : string.Empty));
string[] array = (text ?? string.Empty).Replace("\r\n", "\n").Replace('\r', '\n').Split('\n');
foreach (string text3 in array)
{
_lines.Add(text2 + text3);
}
int num = Mathf.Clamp(_maxLines.Value, 50, 1000);
if (_lines.Count > num)
{
_lines.RemoveRange(0, _lines.Count - num);
}
_scrollToBottom = true;
}
internal void Clear()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
_lines.Clear();
_scroll = Vector2.zero;
}
private void ExecuteInput()
{
string text = (_input ?? string.Empty).Trim();
_input = string.Empty;
_requestFocus = true;
if (text.Length == 0)
{
return;
}
if (text.Length > 4096)
{
AddLine("Comando maior que 4.096 caracteres.", "error");
return;
}
AddLine("> " + text, "command");
if (_history.Count == 0 || !_history[_history.Count - 1].Equals(text, StringComparison.Ordinal))
{
_history.Add(text);
if (_history.Count > 100)
{
_history.RemoveAt(0);
}
SaveHistory();
}
_historyIndex = _history.Count;
_historyDraft = string.Empty;
string text2 = ModConsoleApi.Commands.Execute(text);
if (!string.IsNullOrEmpty(text2))
{
AddLine(text2, text2.StartsWith("ERRO", StringComparison.OrdinalIgnoreCase) ? "error" : "info");
}
}
private void NavigateHistory(int direction)
{
if (_history.Count != 0)
{
if (_historyIndex == _history.Count)
{
_historyDraft = _input;
}
_historyIndex = Mathf.Clamp(_historyIndex + direction, 0, _history.Count);
_input = ((_historyIndex == _history.Count) ? _historyDraft : _history[_historyIndex]);
_requestFocus = true;
}
}
private void CompleteInput()
{
string text = (_input ?? string.Empty).TrimStart();
int num = text.IndexOf(' ');
if (num >= 0)
{
text = text.Substring(0, num);
}
string[] array = ModConsoleApi.Commands.Complete(text);
if (array.Length == 1)
{
_input = array[0] + " ";
}
else if (array.Length > 1)
{
AddLine("Matches: " + string.Join(", ", array), "info");
}
_requestFocus = true;
}
private void SetOpen(bool open)
{
if (ModConsoleApi.IsOpen != open)
{
if (open)
{
OpenSafely();
}
else
{
CloseSafely();
}
}
}
private void OpenSafely()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
CursorLockMode lockState = Cursor.lockState;
bool visible = Cursor.visible;
PlayerInput val = null;
bool flag = false;
try
{
try
{
val = GameInfo.Input;
}
catch (Exception ex)
{
_log.LogDebug((object)("Player input was not available while opening Console Mod: " + ex.Message));
}
if (Object.op_Implicit((Object)(object)val))
{
flag = val.inputIsActive;
if (flag)
{
val.DeactivateInput();
}
}
Cursor.lockState = (CursorLockMode)0;
Cursor.visible = true;
_previousCursorLock = lockState;
_previousCursorVisible = visible;
_playerInput = val;
_playerInputWasActive = flag;
_requestFocus = true;
_scrollToBottom = true;
_openedFrame = Time.frameCount;
ModConsoleApi.SetOpen(value: true);
}
catch (Exception ex2)
{
try
{
if (Object.op_Implicit((Object)(object)val) && flag)
{
val.ActivateInput();
}
}
catch
{
}
Cursor.lockState = lockState;
Cursor.visible = visible;
_playerInput = null;
_playerInputWasActive = false;
ModConsoleApi.SetOpen(value: false);
_log.LogWarning((object)("Console Mod could not be opened safely: " + ex2.Message));
}
}
private void CloseSafely()
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
try
{
if (Object.op_Implicit((Object)(object)_playerInput) && _playerInputWasActive)
{
_playerInput.ActivateInput();
}
}
catch (Exception ex)
{
_log.LogWarning((object)("Player input could not be reactivated while closing Console Mod: " + ex.Message));
}
try
{
Cursor.lockState = _previousCursorLock;
Cursor.visible = _previousCursorVisible;
}
catch (Exception ex2)
{
_log.LogWarning((object)("Cursor state could not be restored while closing Console Mod: " + ex2.Message));
}
_playerInput = null;
_playerInputWasActive = false;
_openedFrame = -1;
ModConsoleApi.SetOpen(value: false);
}
private void EnsureStyles()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Expected O, but got Unknown
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Expected O, but got Unknown
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Expected O, but got Unknown
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Expected O, but got Unknown
if (_windowStyle == null)
{
_background = new Texture2D(1, 1, (TextureFormat)4, false)
{
name = "ModConsole.Background",
hideFlags = (HideFlags)61
};
_background.SetPixel(0, 0, new Color(0.018f, 0.024f, 0.035f, 0.96f));
_background.Apply(false, true);
_windowStyle = new GUIStyle(GUI.skin.window);
_windowStyle.normal.background = _background;
_windowStyle.padding = new RectOffset(14, 14, 10, 12);
GUIStyle val = new GUIStyle(GUI.skin.label)
{
fontSize = 15,
fontStyle = (FontStyle)1
};
val.normal.textColor = new Color(0.38f, 0.86f, 1f);
_titleStyle = val;
GUIStyle val2 = new GUIStyle(GUI.skin.label)
{
fontSize = 13,
wordWrap = true,
richText = false
};
val2.normal.textColor = new Color(0.87f, 0.91f, 0.94f);
_lineStyle = val2;
GUIStyle val3 = new GUIStyle(GUI.skin.textField)
{
fontSize = 14,
padding = new RectOffset(8, 8, 6, 5)
};
val3.normal.textColor = Color.white;
val3.focused.textColor = Color.white;
_inputStyle = val3;
}
}
private void LoadHistory()
{
try
{
if (!File.Exists(_historyPath))
{
return;
}
foreach (string item in File.ReadAllLines(_historyPath).TakeLast(100))
{
if (!string.IsNullOrWhiteSpace(item) && item.Length <= 4096)
{
_history.Add(item);
}
}
}
catch (Exception ex)
{
_log.LogWarning((object)("Console history could not be loaded: " + ex.Message));
}
}
private void SaveHistory()
{
try
{
File.WriteAllLines(_historyPath, _history);
}
catch (Exception ex)
{
_log.LogWarning((object)("Console history could not be saved: " + ex.Message));
}
}
public void Dispose()
{
if (ModConsoleApi.IsOpen)
{
SetOpen(open: false);
}
SaveHistory();
if (Object.op_Implicit((Object)(object)_background))
{
Object.Destroy((Object)(object)_background);
}
_background = null;
}
}
public static class ModConsoleApi
{
private sealed class PendingLine
{
internal readonly string Text;
internal readonly string Level;
internal PendingLine(string text, string level)
{
Text = text;
Level = level;
}
}
public const int ApiVersion = 1;
private const int MaxPendingLines = 2000;
private const int MaxLinesPerDrain = 250;
private static readonly CommandRegistry Registry = new CommandRegistry();
private static readonly ConcurrentQueue<PendingLine> PendingLines = new ConcurrentQueue<PendingLine>();
private static int _pendingLineCount;
public static bool IsAvailable { get; private set; }
public static bool IsOpen { get; private set; }
internal static CommandRegistry Commands => Registry;
public static IDisposable RegisterCommand(string ownerGuid, string name, string description, string usage, Func<string[], string> handler, params string[] aliases)
{
return Registry.Register(ownerGuid, name, description, usage, handler, aliases);
}
public static void WriteLine(string text, string level = "info")
{
PendingLines.Enqueue(new PendingLine(text ?? string.Empty, level ?? "info"));
int num = Interlocked.Increment(ref _pendingLineCount);
PendingLine result;
while (num > 2000 && PendingLines.TryDequeue(out result))
{
num = Interlocked.Decrement(ref _pendingLineCount);
}
}
internal static void Attach()
{
IsAvailable = true;
}
internal static void DrainPending(Action<string, string> writer)
{
if (writer == null)
{
return;
}
for (int i = 0; i < 250; i++)
{
if (!PendingLines.TryDequeue(out var result))
{
break;
}
Interlocked.Decrement(ref _pendingLineCount);
writer(result.Text, result.Level);
}
}
internal static void Detach()
{
IsOpen = false;
IsAvailable = false;
PendingLine result;
while (PendingLines.TryDequeue(out result))
{
Interlocked.Decrement(ref _pendingLineCount);
}
}
internal static void SetOpen(bool value)
{
IsOpen = value;
}
}
[BepInPlugin("fernando.howtofish.modconsole", "Console Mod", "1.0.0")]
[BepInProcess("How to Fish.exe")]
public sealed class Plugin : BaseUnityPlugin
{
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
private static class BlockPlayerInputPatch
{
private static void Postfix(ref bool __result)
{
__result |= ModConsoleApi.IsOpen;
}
}
[HarmonyPatch(typeof(ChatManager), "Update")]
private static class BlockChatPatch
{
private static bool Prefix()
{
return !ModConsoleApi.IsOpen;
}
}
[HarmonyPatch(typeof(EventSystem), "Update")]
private static class BlockUiPatch
{
private static bool Prefix()
{
return !ModConsoleApi.IsOpen;
}
}
public const string PluginGuid = "fernando.howtofish.modconsole";
public const string PluginName = "Console Mod";
public const string PluginVersion = "1.0.0";
private readonly List<IDisposable> _registrations = new List<IDisposable>();
private ConfigEntry<KeyCode> _toggleKey;
private ConfigEntry<int> _maxLines;
private ConsoleOverlay _overlay;
private Harmony _harmony;
private void Awake()
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Console", "Tecla", (KeyCode)96, "Key used to open and close Console Mod.");
_maxLines = ((BaseUnityPlugin)this).Config.Bind<int>("Console", "MaximoDeLinhas", 250, new ConfigDescription("Maximum number of lines kept on screen.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 1000), Array.Empty<object>()));
_overlay = new ConsoleOverlay(((BaseUnityPlugin)this).Logger, _toggleKey, _maxLines);
ModConsoleApi.Attach();
RegisterBuiltIns();
_harmony = Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "fernando.howtofish.modconsole");
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. Key: {2}.", "Console Mod", "1.0.0", _toggleKey.Value));
}
private void Update()
{
_overlay?.Tick();
}
private void OnGUI()
{
_overlay?.Draw();
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
for (int num = _registrations.Count - 1; num >= 0; num--)
{
_registrations[num].Dispose();
}
_registrations.Clear();
_overlay?.Dispose();
_overlay = null;
ModConsoleApi.Detach();
}
private void RegisterBuiltIns()
{
_registrations.Add(ModConsoleApi.RegisterCommand("fernando.howtofish.modconsole", "help", "Lists commands or explains a command.", "help [command]", Help, "ajuda", "?"));
_registrations.Add(ModConsoleApi.RegisterCommand("fernando.howtofish.modconsole", "clear", "Clears the visible console output.", "clear", delegate
{
_overlay.Clear();
return string.Empty;
}, "limpar"));
_registrations.Add(ModConsoleApi.RegisterCommand("fernando.howtofish.modconsole", "plugins", "Lists loaded BepInEx plugins.", "plugins [filter]", Plugins, "mods"));
_registrations.Add(ModConsoleApi.RegisterCommand("fernando.howtofish.modconsole", "scene", "Shows the active and loaded scenes.", "scene", Scene, "cena"));
_registrations.Add(ModConsoleApi.RegisterCommand("fernando.howtofish.modconsole", "echo", "Prints text back to the console.", "echo <text>", (string[] args) => string.Join(" ", args)));
_registrations.Add(ModConsoleApi.RegisterCommand("fernando.howtofish.modconsole", "console", "Shows Console Mod version and API status.", "console", (string[] args) => string.Format("Console Mod {0}; API {1}; {2} registered commands.", "1.0.0", 1, ModConsoleApi.Commands.Snapshot().Length)));
}
private static string Help(string[] args)
{
if (args.Length != 0)
{
CommandDefinition commandDefinition = ModConsoleApi.Commands.Find(args[0]);
if (commandDefinition == null)
{
return "Unknown command: " + args[0];
}
string text = ((commandDefinition.Aliases.Length == 0) ? string.Empty : ("\nAliases: " + string.Join(", ", commandDefinition.Aliases)));
return commandDefinition.Name + " — " + commandDefinition.Description + "\nUsage: " + commandDefinition.Usage + text + "\nMod: " + commandDefinition.OwnerGuid;
}
StringBuilder stringBuilder = new StringBuilder("Available commands:");
CommandDefinition[] array = ModConsoleApi.Commands.Snapshot();
foreach (CommandDefinition commandDefinition2 in array)
{
stringBuilder.Append("\n ").Append(commandDefinition2.Name.PadRight(12)).Append(" ")
.Append(commandDefinition2.Description);
}
return stringBuilder.ToString();
}
private static string Plugins(string[] args)
{
string filter = ((args.Length != 0) ? args[0] : string.Empty);
PluginInfo[] array = Chainloader.PluginInfos.Values.Where((PluginInfo info) => string.IsNullOrEmpty(filter) || info.Metadata.Name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0 || info.Metadata.GUID.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0).OrderBy<PluginInfo, string>((PluginInfo info) => info.Metadata.Name, StringComparer.OrdinalIgnoreCase).ToArray();
if (array.Length == 0)
{
return "No plugins found.";
}
return string.Join("\n", array.Select((PluginInfo info) => info.Metadata.Name + " " + info.Metadata.Version?.ToString() + " [" + info.Metadata.GUID + "]"));
}
private static string Scene(string[] args)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
List<string> list = new List<string>();
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene sceneAt = SceneManager.GetSceneAt(i);
list.Add(((Scene)(ref sceneAt)).name + ((sceneAt == activeScene) ? " (active)" : string.Empty));
}
return "Loaded scenes: " + string.Join(", ", list);
}
}