using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using Alpha; using Alpha.Core.Command; using Alpha.Core.Util; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Echo.Core; using Echo.Core.Commands; using Echo.Patches; using HarmonyLib; using Microsoft.CodeAnalysis; using PurrNet; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AndrewLin")] [assembly: AssemblyConfiguration("Publish")] [assembly: AssemblyDescription("Echo: A mod for On-Together with in-game utility commands including scheduled echoers (/echomein, /echolocalin, /echoglobalin), and more. Use /echohelp")] [assembly: AssemblyFileVersion("0.2.5.0")] [assembly: AssemblyInformationalVersion("0.2.5+4e0b7d4a1048390b61c91485bd217c1e7db83993")] [assembly: AssemblyProduct("AndrewLin.Echo")] [assembly: AssemblyTitle("AndrewLin.Echo")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/andrewlimforfun/ot-mods")] [assembly: InternalsVisibleTo("Echo.Tests")] [assembly: AssemblyVersion("0.2.5.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace Echo { public static class BuildInfo { public const string Version = "0.2.5"; } [BepInPlugin("com.andrewlin.ontogether.echo", "Echo", "0.2.5")] public class EchoPlugin : BaseUnityPlugin { public static readonly TokenValidator Validator = new TokenValidator("c7b7df644ec48a2ce66a51e05d084e177b0a01e6ecb77f9bd91808afe6668148"); private static ManualLogSource? _logger; private static readonly ConcurrentQueue _mainThreadQueue = new ConcurrentQueue(); public const string ModGUID = "com.andrewlin.ontogether.echo"; public const string ModName = "Echo"; public const string ModVersion = "0.2.5"; private const string _locationsFileName = "com.andrewlin.ontogether.echo.locations.cfg"; public static ConfigEntry? EnableFeature { get; private set; } public static ConfigEntry? AccessToken { get; private set; } public static SavedLocationManager? Locations { get; private set; } public static void RunOnMainThread(Action action) { ConfigEntry? enableFeature = EnableFeature; if (enableFeature != null && enableFeature.Value) { _mainThreadQueue.Enqueue(action); } } private void Awake() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown _logger = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Echo v0.2.5 is loaded!"); InitConfig(); Locations = new SavedLocationManager(Path.Combine(Paths.ConfigPath, "com.andrewlin.ontogether.echo.locations.cfg")); Harmony val = new Harmony("com.andrewlin.ontogether.echo"); val.PatchAll(typeof(PlayerMovementControllerPatch)); ChatCommandManager commandManager = AlphaPlugin.CommandManager; if (commandManager != null) { commandManager.Register((IChatCommand)(object)new EchoToggleCommand()); } ChatCommandManager commandManager2 = AlphaPlugin.CommandManager; if (commandManager2 != null) { commandManager2.Register((IChatCommand)(object)new EchoTeleportPersonCommand()); } ChatCommandManager commandManager3 = AlphaPlugin.CommandManager; if (commandManager3 != null) { commandManager3.Register((IChatCommand)(object)new EchoTeleportLocationCommand()); } ChatCommandManager commandManager4 = AlphaPlugin.CommandManager; if (commandManager4 != null) { commandManager4.Register((IChatCommand)(object)new EchoLocationListCommand()); } ChatCommandManager commandManager5 = AlphaPlugin.CommandManager; if (commandManager5 != null) { commandManager5.Register((IChatCommand)(object)new EchoLocationRemoveCommand()); } ChatCommandManager commandManager6 = AlphaPlugin.CommandManager; if (commandManager6 != null) { commandManager6.Register((IChatCommand)(object)new EchoFollowCommand()); } ChatCommandManager commandManager7 = AlphaPlugin.CommandManager; if (commandManager7 != null) { commandManager7.Register((IChatCommand)(object)new EchoFollowRelativeCommand()); } ChatCommandManager commandManager8 = AlphaPlugin.CommandManager; if (commandManager8 != null) { commandManager8.Register((IChatCommand)(object)new EchoUnfollowCommand()); } ChatCommandManager commandManager9 = AlphaPlugin.CommandManager; if (commandManager9 != null) { commandManager9.Register((IChatCommand)(object)new EchoSyncRotationCommand()); } ChatCommandManager commandManager10 = AlphaPlugin.CommandManager; if (commandManager10 != null) { commandManager10.Register((IChatCommand)(object)new EchoUnsyncRotationCommand()); } ChatCommandManager commandManager11 = AlphaPlugin.CommandManager; if (commandManager11 != null) { commandManager11.Register((IChatCommand)(object)new EchoRotateCommand()); } ChatCommandManager commandManager12 = AlphaPlugin.CommandManager; if (commandManager12 != null) { commandManager12.Register((IChatCommand)(object)new EchoRotateLockCommand()); } ChatCommandManager commandManager13 = AlphaPlugin.CommandManager; if (commandManager13 != null) { commandManager13.Register((IChatCommand)(object)new EchoRotateUnlockCommand()); } ChatCommandManager commandManager14 = AlphaPlugin.CommandManager; if (commandManager14 != null) { commandManager14.Register((IChatCommand)(object)new EchoLookAtCommand()); } ChatCommandManager commandManager15 = AlphaPlugin.CommandManager; if (commandManager15 != null) { commandManager15.Register((IChatCommand)(object)new EchoCopyNameCommand()); } ChatCommandManager commandManager16 = AlphaPlugin.CommandManager; if (commandManager16 != null) { commandManager16.Register((IChatCommand)(object)new EchoCopyNameStyleCommand()); } ChatCommandManager commandManager17 = AlphaPlugin.CommandManager; if (commandManager17 != null) { commandManager17.Register((IChatCommand)(object)new EchoSetNameCommand()); } ChatCommandManager commandManager18 = AlphaPlugin.CommandManager; if (commandManager18 != null) { commandManager18.Register((IChatCommand)(object)new EchoGetNameCommand()); } ChatCommandManager commandManager19 = AlphaPlugin.CommandManager; if (commandManager19 != null) { commandManager19.Register((IChatCommand)(object)new EchoRevertNameCommand()); } ChatCommandManager commandManager20 = AlphaPlugin.CommandManager; if (commandManager20 != null) { commandManager20.Register((IChatCommand)(object)new EchoCopyOutfitCommand()); } ChatCommandManager commandManager21 = AlphaPlugin.CommandManager; if (commandManager21 != null) { commandManager21.Register((IChatCommand)(object)new EchoRemoveStatusCommand()); } } private void InitConfig() { EnableFeature = ((BaseUnityPlugin)this).Config.Bind("General", "EnableFeature", true, "Enable or disable the mod feature."); AccessToken = ((BaseUnityPlugin)this).Config.Bind("Security", "AccessToken", "put_the_secret_token_here", "Token required to use name/outfit copy commands. Must match the secret embedded in the mod."); } private void Update() { ConfigEntry? enableFeature = EnableFeature; if (enableFeature == null || !enableFeature.Value) { return; } Action result; while (_mainThreadQueue.TryDequeue(out result)) { try { result(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Main thread action failed: " + ex.Message)); } } } private void OnDestroy() { } } public static class MyPluginInfo { public const string PLUGIN_GUID = "AndrewLin.Echo"; public const string PLUGIN_NAME = "AndrewLin.Echo"; public const string PLUGIN_VERSION = "0.2.5"; } } namespace Echo.Patches { [HarmonyPatch(typeof(PlayerMovementController))] public static class PlayerMovementControllerPatch { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.PlayerMovementControllerPatch"); public static Vector3 WarpPosition = Vector3.zero; private static Transform? _followTarget; private static Vector3 _followOffset; private static bool _followRelative; private static Transform? _rotationSyncTarget; private static Transform? _lookAtTarget; public static Quaternion? WarpRotation; public static Quaternion? LockedRotation; public static bool IsFollowing => (Object)(object)_followTarget != (Object)null; public static bool IsSyncingRotation => (Object)(object)_rotationSyncTarget != (Object)null; public static bool IsLookingAt => (Object)(object)_lookAtTarget != (Object)null; public static void StartFollowing(Transform target, Vector3 offset, bool relative = false) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) _followTarget = target; _followOffset = offset; _followRelative = relative; } public static void StopFollowing() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) _followTarget = null; _followOffset = Vector3.zero; } public static void StartSyncingRotation(Transform target) { _rotationSyncTarget = target; } public static void StopSyncingRotation() { _rotationSyncTarget = null; } public static void StartLookingAt(Transform target) { _lookAtTarget = target; } public static void StopLookingAt() { _lookAtTarget = null; } public static Vector3 GetLocalPlayerPosition() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) TextChannelManager i = NetworkSingleton.I; return ((Object)(object)i != (Object)null) ? i.MainPlayer.position : Vector3.zero; } [HarmonyPrefix] [HarmonyPatch("MovePlayer")] public static bool MovePlayer_Prefix(ref CharacterController ____characterController, PlayerMovementController __instance) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) TextChannelManager i = NetworkSingleton.I; if ((Object)(object)i == (Object)null || (Object)(object)__instance != (Object)(object)i.MainMovementController) { return true; } if (WarpPosition != Vector3.zero) { if (IsFollowing) { StopFollowing(); ChatUtils.AddGlobalNotification("Stopped following (teleported)."); } ((Component)____characterController).transform.position = WarpPosition; Logger.LogInfo((object)$"Teleported to {WarpPosition}"); WarpPosition = Vector3.zero; return false; } if (WarpRotation.HasValue) { ((Component)__instance).transform.rotation = WarpRotation.Value; ManualLogSource logger = Logger; Quaternion value = WarpRotation.Value; logger.LogInfo((object)$"Rotated to {((Quaternion)(ref value)).eulerAngles}"); WarpRotation = null; } if (_followTarget != null && (Object)(object)_followTarget != (Object)null) { return false; } return true; } [HarmonyPostfix] [HarmonyPatch("Update")] public static void Update_Postfix(PlayerMovementController __instance) { //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) if (_followTarget == null && _rotationSyncTarget == null && _lookAtTarget == null && !LockedRotation.HasValue) { return; } TextChannelManager i = NetworkSingleton.I; if ((Object)(object)i == (Object)null || (Object)(object)__instance != (Object)(object)i.MainMovementController) { return; } if (_followTarget != null) { if ((Object)(object)_followTarget == (Object)null || (Object)(object)((Component)_followTarget).gameObject == (Object)null || !((Component)_followTarget).gameObject.activeInHierarchy) { StopFollowing(); ChatUtils.AddGlobalNotification("Stopped following (target left)."); } else { Vector3 val = (_followRelative ? (_followTarget.rotation * _followOffset) : _followOffset); Vector3 position = _followTarget.position + val; ((Component)__instance).transform.position = position; i.MainPlayer.position = position; } } ApplyRotationSync(i.MainMovementController, __instance); ApplyLookAt(i.MainMovementController, __instance); if (LockedRotation.HasValue && (Object)(object)__instance == (Object)(object)i.MainMovementController) { ((Component)__instance).transform.rotation = LockedRotation.Value; } } private static void ApplyRotationSync(PlayerMovementController mainCtrl, PlayerMovementController instance) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (_rotationSyncTarget != null) { if ((Object)(object)_rotationSyncTarget == (Object)null || (Object)(object)((Component)_rotationSyncTarget).gameObject == (Object)null || !((Component)_rotationSyncTarget).gameObject.activeInHierarchy) { StopSyncingRotation(); ChatUtils.AddGlobalNotification("Stopped syncing rotation (target left)."); } else if (!((Object)(object)instance != (Object)(object)mainCtrl)) { float y = _rotationSyncTarget.eulerAngles.y; ((Component)instance).transform.rotation = Quaternion.Euler(0f, y, 0f); } } } private static void ApplyLookAt(PlayerMovementController mainCtrl, PlayerMovementController instance) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (_lookAtTarget == null) { return; } if ((Object)(object)_lookAtTarget == (Object)null || (Object)(object)((Component)_lookAtTarget).gameObject == (Object)null || !((Component)_lookAtTarget).gameObject.activeInHierarchy) { StopLookingAt(); ChatUtils.AddGlobalNotification("Stopped looking at target (target left)."); } else if (!((Object)(object)instance != (Object)(object)mainCtrl)) { Vector3 val = _lookAtTarget.position - ((Component)instance).transform.position; val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f)) { ((Component)instance).transform.rotation = Quaternion.LookRotation(val); } } } } } namespace Echo.Core { public class SavedLocationManager { private readonly string _filePath; private readonly Dictionary _locations; public SavedLocationManager(string filePath) { _filePath = filePath; _locations = new Dictionary(StringComparer.OrdinalIgnoreCase); Load(); } public void Save(string name, Vector3 pos) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) _locations[name] = pos; Persist(); } public bool TryGet(string name, out Vector3 pos) { return _locations.TryGetValue(name, out pos); } public bool Delete(string name) { if (!_locations.Remove(name)) { return false; } Persist(); return true; } public IReadOnlyDictionary GetAll() { return new ReadOnlyDictionary(_locations); } private void Load() { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (!File.Exists(_filePath)) { return; } string[] array = File.ReadAllLines(_filePath); foreach (string text in array) { int num = text.IndexOf('='); if (num >= 1) { string key = text.Substring(0, num).Trim(); string[] array2 = text.Substring(num + 1).Split('|'); if (array2.Length == 3 && float.TryParse(array2[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { _locations[key] = new Vector3(result, result2, result3); } } } } private void Persist() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) List list = new List(); foreach (KeyValuePair location in _locations) { string text = location.Value.x.ToString(CultureInfo.InvariantCulture); string text2 = location.Value.y.ToString(CultureInfo.InvariantCulture); string text3 = location.Value.z.ToString(CultureInfo.InvariantCulture); list.Add(location.Key + "=" + text + "|" + text2 + "|" + text3); } File.WriteAllLines(_filePath, list); } } public static class MoveUtil { public static bool IsRotationLocked => PlayerMovementControllerPatch.LockedRotation.HasValue; public static void Teleport(Vector3 targetPosition) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) TextChannelManager i = NetworkSingleton.I; if ((Object)(object)i == (Object)null) { ChatUtils.AddGlobalNotification("Teleport failed: not in a session."); return; } PlayerMovementControllerPatch.WarpPosition = targetPosition; i.MainPlayer.position = targetPosition; } public static void SetRotation(float pitch, float yaw, float roll) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) PlayerMovementControllerPatch.WarpRotation = Quaternion.Euler(pitch, yaw, roll); } public static void LockRotation(float pitch, float yaw, float roll) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) PlayerMovementControllerPatch.LockedRotation = Quaternion.Euler(pitch, yaw, roll); } public static void UnlockRotation() { PlayerMovementControllerPatch.LockedRotation = null; } public static void LookAt(Vector3 targetPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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) Vector3 localPlayerPosition = PlayerMovementControllerPatch.GetLocalPlayerPosition(); Vector3 val = targetPosition - localPlayerPosition; val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f)) { PlayerMovementControllerPatch.WarpRotation = Quaternion.LookRotation(val); } } } internal static class NameStyleTransfer { internal readonly struct StyledSegment { public readonly string Tags; public readonly string Text; public StyledSegment(string tags, string text) { Tags = tags; Text = text; } } internal static List ParseSegments(string input) { List list = new List(); StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder2 = new StringBuilder(); int num = 0; while (num < input.Length) { if (input[num] == '<') { if (stringBuilder2.Length > 0) { list.Add(new StyledSegment(stringBuilder.ToString(), stringBuilder2.ToString())); stringBuilder.Clear(); stringBuilder2.Clear(); } int num2 = input.IndexOf('>', num); if (num2 >= 0) { stringBuilder.Append(input, num, num2 - num + 1); num = num2 + 1; } else { stringBuilder2.Append(input, num, input.Length - num); num = input.Length; } } else { stringBuilder2.Append(input[num]); num++; } } if (stringBuilder.Length > 0 || stringBuilder2.Length > 0) { list.Add(new StyledSegment(stringBuilder.ToString(), stringBuilder2.ToString())); } return list; } internal static string ApplyPositional(List segments, string myChars) { if (segments.Count == 0) { return myChars; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; for (int i = 0; i < segments.Count; i++) { stringBuilder.Append(segments[i].Tags); int length = segments[i].Text.Length; if (i == segments.Count - 1) { if (num < myChars.Length) { stringBuilder.Append(myChars, num, myChars.Length - num); } continue; } int num2 = Math.Min(num + length, myChars.Length); if (num < num2) { stringBuilder.Append(myChars, num, num2 - num); } num = num2; } return stringBuilder.ToString(); } internal static string ApplyEven(List segments, string myChars) { if (segments.Count == 0) { return myChars; } int num = 0; foreach (StyledSegment segment in segments) { if (segment.Text.Length > 0) { num++; } } if (num == 0) { StringBuilder stringBuilder = new StringBuilder(); foreach (StyledSegment segment2 in segments) { stringBuilder.Append(segment2.Tags); } stringBuilder.Append(myChars); return stringBuilder.ToString(); } int num2 = myChars.Length / num; int num3 = myChars.Length % num; StringBuilder stringBuilder2 = new StringBuilder(); int num4 = 0; int num5 = 0; foreach (StyledSegment segment3 in segments) { stringBuilder2.Append(segment3.Tags); if (segment3.Text.Length > 0) { int num6 = num2 + ((num5 < num3) ? 1 : 0); int num7 = Math.Min(num4 + num6, myChars.Length); if (num4 < num7) { stringBuilder2.Append(myChars, num4, num7 - num4); } num4 = num7; num5++; } } if (num4 < myChars.Length) { stringBuilder2.Append(myChars, num4, myChars.Length - num4); } return stringBuilder2.ToString(); } internal static string ApplyEvenKeepNonAscii(List segments, string myChars) { if (segments.Count == 0) { return myChars; } int num = 0; foreach (StyledSegment segment in segments) { string text = segment.Text; foreach (char c in text) { if (c <= '\u007f') { num++; } } } if (num == 0) { StringBuilder stringBuilder = new StringBuilder(); foreach (StyledSegment segment2 in segments) { stringBuilder.Append(segment2.Tags); stringBuilder.Append(segment2.Text); } stringBuilder.Append(myChars); return stringBuilder.ToString(); } int num2 = 0; foreach (StyledSegment segment3 in segments) { string text2 = segment3.Text; foreach (char c2 in text2) { if (c2 <= '\u007f') { num2++; break; } } } int num3 = myChars.Length / num2; int num4 = myChars.Length % num2; StringBuilder stringBuilder2 = new StringBuilder(); int num5 = 0; int num6 = 0; foreach (StyledSegment segment4 in segments) { stringBuilder2.Append(segment4.Tags); bool flag = false; string text3 = segment4.Text; foreach (char c3 in text3) { if (c3 <= '\u007f') { flag = true; break; } } if (!flag) { stringBuilder2.Append(segment4.Text); continue; } int num7 = num3 + ((num6 < num4) ? 1 : 0); int l = 0; string text4 = segment4.Text; foreach (char c4 in text4) { if (c4 > '\u007f') { stringBuilder2.Append(c4); } else if (l < num7 && num5 < myChars.Length) { stringBuilder2.Append(myChars[num5]); num5++; l++; } } for (; l < num7; l++) { if (num5 >= myChars.Length) { break; } stringBuilder2.Append(myChars[num5]); num5++; } num6++; } if (num5 < myChars.Length) { stringBuilder2.Append(myChars, num5, myChars.Length - num5); } return stringBuilder2.ToString(); } } public static class NameUtil { private static readonly ManualLogSource _log = Logger.CreateLogSource("Echo.NU"); private const string OfficerBallsStatusManagerGUID = "officerballs.StatusManager"; public static string? OriginalName { get; private set; } public static string GetName() { DataManager i = MonoSingleton.I; if ((Object)(object)i == (Object)null) { _log.LogWarning((object)"GetName called before DataManager is available."); return OriginalName ?? "Player"; } return i.PlayerData.Name; } public static void SetName(string newName, bool saveOriginal = true) { //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) DataManager i = MonoSingleton.I; TextChannelManager i2 = NetworkSingleton.I; UIManager i3 = MonoSingleton.I; MainSceneManager i4 = MonoSingleton.I; if ((Object)(object)i == (Object)null || (Object)(object)i2 == (Object)null) { _log.LogWarning((object)"SetName called before DataManager/TextChannelManager are available."); return; } PluginInfo value; if (saveOriginal && OriginalName == null) { string text = null; if (Chainloader.PluginInfos.TryGetValue("officerballs.StatusManager", out value)) { text = ((Chainloader.PluginInfos["officerballs.StatusManager"].Instance.Config["General", "PlayerName"] is ConfigEntry val) ? val.Value : null); } if (!string.IsNullOrEmpty(text)) { OriginalName = text; } else { OriginalName = i.PlayerData.Name; } } i.PlayerData.Name = newName; if ((Object)(object)i4 != (Object)null) { i2.MainCustomizationController.UpdatePlayerInfo(i.PlayerData.GetPlayerIdInfo(), default(RPCInfo)); ((TMP_Text)i3.PlayerText).text = newName; i2.UserName = newName; if (Chainloader.PluginInfos.TryGetValue("officerballs.StatusManager", out value)) { ChatUtils.UISendMessage("/setname " + newName); } } _log.LogInfo((object)("Name set to: " + newName)); } public static bool RevertName() { if (OriginalName == null) { return false; } string originalName = OriginalName; OriginalName = null; SetName(originalName, saveOriginal: false); return true; } } } namespace Echo.Core.Commands { public class EchoCopyOutfitSelfCommand : IChatCommand, IComparable { private static ManualLogSource Logger = Logger.CreateLogSource("Echo.ECOSC"); public string Name => "echocopyoutfitself"; public string ShortName => "ecos"; public string Description => "Copy your current outfit/appearance to another slot. Usage: /echocopyoutfit (1-3)"; public string Namespace => "echo"; public void Execute(string[] args) { if (args.Length != 1 || !int.TryParse(args[0], out var result) || result < 1 || result > 3) { ChatUtils.AddGlobalNotification("Usage: /echocopyoutfit (slot = 1, 2, or 3)"); return; } int num = result - 1; DataManager i = MonoSingleton.I; if ((Object)(object)i == (Object)null) { ChatUtils.AddGlobalNotification("DataManager not available."); return; } PlayerDataZip playerDataZip = i.PlayerDataZip; int selectedStyleIndex = playerDataZip.SelectedStyleIndex; if (num == selectedStyleIndex) { ChatUtils.AddGlobalNotification($"Slot {result} is already your active slot - nothing to copy."); return; } CustomizationDataIDs3 currentCustomizationDataIDs = playerDataZip.CurrentCustomizationDataIDs; playerDataZip.SelectedStyleIndex = num; playerDataZip.CurrentCustomizationDataIDs = currentCustomizationDataIDs; playerDataZip.SelectedStyleIndex = selectedStyleIndex; i.SavePlayerZipData(); string slotName = GetSlotName(playerDataZip, selectedStyleIndex); string slotName2 = GetSlotName(playerDataZip, num); Logger.LogInfo((object)$"Copied outfit from slot {selectedStyleIndex + 1} ({slotName}) to slot {result} ({slotName2})."); ChatUtils.AddGlobalNotification($"Copied outfit from slot {selectedStyleIndex + 1} ({slotName}) → slot {result} ({slotName2})."); } private static string GetSlotName(PlayerDataZip pdz, int index) { if (pdz.StyleNames != null && index < pdz.StyleNames.Count) { return pdz.StyleNames[index]; } return $"Slot {index + 1}"; } } public class EchoCopyNameCommand : IChatCommand, IComparable { private static readonly ManualLogSource _log = Logger.CreateLogSource("Echo.ECONC"); public string Name => "echocopyname"; public string ShortName => "ecn"; public string Description => "Copy another player's display name (with TMP tags). Usage: /echocopyname [status_brackets]"; public string Namespace => "echo"; public void Execute(string[] args) { if (!PlayerLists.IsAdmin(SteamUtils.GetPlayerSteamID()) && (EchoPlugin.AccessToken == null || !EchoPlugin.Validator.IsValid(EchoPlugin.AccessToken.Value.Trim()))) { ChatUtils.AddGlobalNotification("Access denied: copy name has high abuse potential. Only Certified Users can use."); return; } if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /echocopyname [status_brackets]"); return; } string text = string.Join(" ", args).Trim(); PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } string userName = val.UserName; string text2 = ChatUtils.CleanTMPTags(userName).Trim(); _log.LogInfo((object)("Copying name from " + text2 + ": \"" + userName + "\"")); NameUtil.SetName(userName); ChatUtils.AddGlobalNotification("Name copied from " + userName); } } public class EchoCopyNameStyleCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.ECNSC"); public string Name => "echocopynamestyle"; public string ShortName => "ecns"; public string Description => "Copy another player's name styling onto your name. Usage: /ecns [-s] . -s to also copy non-ASCII chars as style."; public string Namespace => "echo"; public void Execute(string[] args) { if (!PlayerLists.IsAdmin(SteamUtils.GetPlayerSteamID()) && (EchoPlugin.AccessToken == null || !EchoPlugin.Validator.IsValid(EchoPlugin.AccessToken.Value.Trim()))) { ChatUtils.AddGlobalNotification("Access denied: copy name style has high abuse potential. Only Certified Users can use."); return; } if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /ecns [-s] . -s to also copy non-ASCII chars as style."); return; } bool flag = false; int num = 0; if (args[0].Equals("-s", StringComparison.OrdinalIgnoreCase)) { flag = true; num = 1; } if (num >= args.Length) { ChatUtils.AddGlobalNotification("Usage: /ecns [-s] "); return; } string text = string.Join(" ", args, num, args.Length - num).Trim(); PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } string userName = val.UserName; string text2 = ChatUtils.CleanTMPTags(NameUtil.GetName()).Trim(); if (text2.Length == 0) { ChatUtils.AddGlobalNotification("Your name is empty after cleaning tags."); return; } List segments = NameStyleTransfer.ParseSegments(userName); string text3 = (flag ? NameStyleTransfer.ApplyEvenKeepNonAscii(segments, text2) : NameStyleTransfer.ApplyEven(segments, text2)); Logger.LogInfo((object)("Style copied from " + val.UserNameClean + ": \"" + text3 + "\"")); NameUtil.SetName(text3); ChatUtils.AddGlobalNotification("Name style copied from " + val.UserNameClean + "."); } } public class EchoCopyOutfitCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.ECOC"); private static readonly FieldInfo? CustomizationDataField = typeof(PlayerCustomizationController).GetField("_customizationData", BindingFlags.Instance | BindingFlags.NonPublic); public string Name => "echocopyoutfit"; public string ShortName => "eco"; public string Description => "Copy another player's current outfit. Usage: /echocopyoutfit "; public string Namespace => "echo"; public void Execute(string[] args) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /echocopyoutfit "); return; } string text = string.Join(" ", args).Trim(); PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } if (CustomizationDataField == null) { Logger.LogError((object)"Could not reflect _customizationData on PlayerCustomizationController."); ChatUtils.AddGlobalNotification("Reflection error: outfit field not found."); return; } PlayerCustomizationController component = ((Component)val.PlayerTransform).GetComponent(); if ((Object)(object)component == (Object)null) { ChatUtils.AddGlobalNotification("Could not find customization controller for " + ChatUtils.CleanTMPTags(val.UserName).Trim() + "."); return; } CustomizationData val2 = (CustomizationData)CustomizationDataField.GetValue(component); PlayerCustomizationController val3 = NetworkSingleton.I?.MainCustomizationController; if ((Object)(object)val3 == (Object)null) { ChatUtils.AddGlobalNotification("Local customization controller not available."); return; } MonoSingleton.I.CustomizationData = new CustomizationData(val2); MonoSingleton.I.PlayerDataZip.CurrentCustomizationDataIDs = new CustomizationDataIDs3(MonoSingleton.I.CustomizationData); val3.ApplyCustomization(val2); string text2 = ChatUtils.CleanTMPTags(val.UserName).Trim(); Logger.LogInfo((object)("Copied outfit from " + text2 + ".")); ChatUtils.AddGlobalNotification("Outfit copied from " + text2 + "."); } } public class EchoFollowCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.EchoFollowCommand"); public string Name => "echofollow"; public string ShortName => "ef"; public string Description => "Follow a player at a fixed offset. Usage: /ef [x y z]"; public string Namespace => "echo"; public void Execute(string[] args) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /ef [x y z]"); return; } Vector3? val = null; string text; if (args.Length >= 4 && float.TryParse(args[^3], out var result) && float.TryParse(args[^2], out var result2) && float.TryParse(args[^1], out var result3)) { val = new Vector3(result, result2, result3); text = string.Join(" ", args, 0, args.Length - 3); } else { text = string.Join(" ", args); } text = text.Trim(); PlayerDetail val2 = PlayerUtils.FindPlayerByQuery(text); if (val2 == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } Vector3 localPlayerPosition = PlayerMovementControllerPatch.GetLocalPlayerPosition(); Vector3 val3 = (Vector3)(((??)val) ?? (localPlayerPosition - val2.Position)); string text2 = ChatUtils.CleanTMPTags(val2.UserName).Trim(); PlayerMovementControllerPatch.StartFollowing(((Component)val2.PlayerTransform).transform, val3); Logger.LogInfo((object)$"Following {text2} at offset {val3}"); ChatUtils.AddGlobalNotification($"Following {text2} at offset ({val3.x:F1}, {val3.y:F1}, {val3.z:F1}). Use /eu to stop."); } } public class EchoFollowRelativeCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.EchoFollowRelativeCommand"); private const float DefaultDistance = 1.5f; public string Name => "echofollowrelative"; public string ShortName => "efr"; public string Description => "Follow a player relative to their facing. Usage: /efr [behind|beside|front|x y z]"; public string Namespace => "echo"; public void Execute(string[] args) { //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /efr [behind|beside|front|x y z]"); return; } Vector3 offset = default(Vector3); string text; if (args.Length >= 4 && float.TryParse(args[^3], out var result) && float.TryParse(args[^2], out var result2) && float.TryParse(args[^1], out var result3)) { ((Vector3)(ref offset))..ctor(result, result2, result3); text = string.Join(" ", args, 0, args.Length - 3).Trim(); } else if (args.Length >= 2 && TryParsePreset(args[^1], out offset)) { text = string.Join(" ", args, 0, args.Length - 1).Trim(); } else { ((Vector3)(ref offset))..ctor(0f, 0f, -1.5f); text = string.Join(" ", args).Trim(); } if (string.IsNullOrEmpty(text)) { ChatUtils.AddGlobalNotification("Usage: /efr [behind|beside|front|x y z]"); return; } PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } string text2 = ChatUtils.CleanTMPTags(val.UserName).Trim(); PlayerMovementControllerPatch.StartFollowing(((Component)val.PlayerTransform).transform, offset, relative: true); Logger.LogInfo((object)$"Following {text2} (relative) at offset {offset}"); ChatUtils.AddGlobalNotification($"Following {text2} (relative) at ({offset.x:F1}, {offset.y:F1}, {offset.z:F1}). Use /eu to stop."); } private static bool TryParsePreset(string s, out Vector3 offset) { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: 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_0160: Unknown result type (might be due to invalid IL or missing references) switch (s.ToLowerInvariant()) { case "behind": case "back": offset = new Vector3(0f, 0f, -1.5f); return true; case "beside": case "left": offset = new Vector3(-1.5f, 0f, 0f); return true; case "right": offset = new Vector3(1.5f, 0f, 0f); return true; case "front": case "ahead": offset = new Vector3(0f, 0f, 1.5f); return true; default: offset = Vector3.zero; return false; } } } public class EchoGetNameCommand : IChatCommand, IComparable { private static readonly ManualLogSource _log = Logger.CreateLogSource("Echo.ECONC"); public string Name => "echogetname"; public string ShortName => "egn"; public string Description => "Copy another player's display name (with TMP tags). Usage: /echogetname [status_brackets]"; public string Namespace => "echo"; public void Execute(string[] args) { if (!PlayerLists.IsAdmin(SteamUtils.GetPlayerSteamID()) && (EchoPlugin.AccessToken == null || !EchoPlugin.Validator.IsValid(EchoPlugin.AccessToken.Value.Trim()))) { ChatUtils.AddGlobalNotification("Access denied: get name has high abuse potential. Only Certified Users can use."); return; } if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /echogetname [status_brackets]"); return; } string text = string.Join(" ", args).Trim(); PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } string userName = val.UserName; string userNameClean = val.UserNameClean; _log.LogInfo((object)("Name of " + userNameClean + ": \"" + userName + "\"")); ChatUtils.AddGlobalNotification("Name of " + userNameClean + ": " + userName); } } public class EchoLocationListCommand : IChatCommand, IComparable { public string Name => "echolocationlist"; public string ShortName => "ell"; public string Description => "List all saved locations and their coordinates. Usage: /echolocationlist"; public string Namespace => "echo"; public void Execute(string[] args) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) SavedLocationManager locations = EchoPlugin.Locations; if (locations == null) { ChatUtils.AddGlobalNotification("Location manager not initialized."); return; } IReadOnlyDictionary all = locations.GetAll(); if (all.Count == 0) { ChatUtils.AddGlobalNotification("No saved locations."); return; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Saved locations ({all.Count}):"); foreach (KeyValuePair item in all) { stringBuilder.AppendLine($" {item.Key}: ({item.Value.x:F1}, {item.Value.y:F1}, {item.Value.z:F1})"); } ChatUtils.AddGlobalNotification(stringBuilder.ToString().TrimEnd()); } } public class EchoLocationRemoveCommand : IChatCommand, IComparable { public string Name => "echolocationremove"; public string ShortName => "elr"; public string Description => "Remove a saved location. Usage: /echolocationremove "; public string Namespace => "echo"; public void Execute(string[] args) { if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /echolocationremove "); return; } SavedLocationManager locations = EchoPlugin.Locations; if (locations == null) { ChatUtils.AddGlobalNotification("Location manager not initialized."); return; } string text = string.Join(" ", args).Trim(); if (locations.Delete(text)) { ChatUtils.AddGlobalNotification("Removed location \"" + text + "\"."); } else { ChatUtils.AddGlobalNotification("No saved location named \"" + text + "\"."); } } } public class EchoLookAtCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.EchoLookAtCommand"); public string Name => "echolookat"; public string ShortName => "ela"; public string Description => "Continuously face toward a player. Usage: /ela . Stop with /eru."; public string Namespace => "echo"; public void Execute(string[] args) { if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /ela . Stop with /eru."); return; } string text = string.Join(" ", args).Trim(); PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } string text2 = ChatUtils.CleanTMPTags(val.UserName).Trim(); PlayerMovementControllerPatch.StartLookingAt(((Component)val.PlayerTransform).transform); Logger.LogInfo((object)("Looking at " + text2 + ".")); ChatUtils.AddGlobalNotification("Facing toward " + text2 + ". Use /eru to stop."); } } public class EchoRemoveStatusCommand : IChatCommand, IComparable { private static readonly ManualLogSource _log = Logger.CreateLogSource("Echo.ERSC"); public string Name => "echoremovestatus"; public string ShortName => "ers"; public string Description => "Remove status from my player's display name. Usage: /echoremovestatus "; public string Namespace => "echo"; public void Execute(string[] args) { if (EchoPlugin.AccessToken == null || !EchoPlugin.Validator.IsValid(EchoPlugin.AccessToken.Value.Trim())) { ChatUtils.AddGlobalNotification("Access denied: remove status has high abuse potential. Only Certified Users can use."); return; } if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /echoremovestatus "); return; } if (args.Length == 2) { ChatUtils.AddGlobalNotification("Please provide only one argument with the brackets to remove. Usage: /echoremovestatus "); return; } string text = args[0].Trim(); string text2 = NameUtil.GetName(); if (text.Length == 1) { text2 = text2[..text2.LastIndexOf(text[0])]; } else if (text.Length > 1) { char bracketStart = text[0]; char bracketEnd = text[text.Length - 1]; text2 = RemoveLastBracketedSection(text2, bracketStart, bracketEnd); } NameUtil.SetName(text2, saveOriginal: false); ChatUtils.AddGlobalNotification("Status removed from " + text2); } public static string RemoveLastBracketedSection(string name, char bracketStart, char bracketEnd) { int num = name.LastIndexOf(bracketEnd); if (num == -1) { return name; } int num2 = name.LastIndexOf(bracketStart, num); if (num2 == -1) { return name; } return name.Remove(num2, num - num2 + 1).TrimEnd(); } } public class EchoRevertNameCommand : IChatCommand, IComparable { public string Name => "echorevertname"; public string ShortName => "ern"; public string Description => "Revert your display name to the original before any Echo rename."; public string Namespace => "echo"; public void Execute(string[] args) { if (NameUtil.OriginalName == null) { ChatUtils.AddGlobalNotification("No saved name to revert to."); return; } string originalName = NameUtil.OriginalName; NameUtil.RevertName(); string text = ChatUtils.CleanTMPTags(originalName).Trim(); ChatUtils.AddGlobalNotification("Name reverted to: " + text); } } public class EchoRotateCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.EchoRotateCommand"); public string Name => "echorotate"; public string ShortName => "er"; public string Description => "Set facing direction. Usage: /er "; public string Namespace => "echo"; public void Execute(string[] args) { //IL_0027: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) if (args.Length == 0) { PlayerDetail playerDetail = PlayerUtils.GetPlayerDetail(); Vector3 val = ((playerDetail != null) ? ((Component)playerDetail.PlayerTransform).transform.eulerAngles : Vector3.zero); ChatUtils.AddGlobalNotification($"Current rotation: ({val.x:F1}, {val.y:F1}, {val.z:F1})"); return; } if (args.Length == 3 && float.TryParse(args[0], out var result) && float.TryParse(args[1], out var result2) && float.TryParse(args[2], out var result3)) { MoveUtil.SetRotation(result, result2, result3); ChatUtils.AddGlobalNotification($"Rotation set to ({result}, {result2}, {result3})."); Logger.LogInfo((object)$"One-shot rotation to ({result}, {result2}, {result3})."); return; } string text = string.Join(" ", args).Trim(); if (TryParseCardinal(text, out var angle)) { MoveUtil.SetRotation(0f, angle, 0f); ChatUtils.AddGlobalNotification($"Facing {text} ({angle} degrees)."); Logger.LogInfo((object)$"One-shot rotation to cardinal {text} ({angle})."); return; } if (float.TryParse(text, out var result4)) { MoveUtil.SetRotation(0f, result4, 0f); ChatUtils.AddGlobalNotification($"Facing {result4} degrees."); Logger.LogInfo((object)$"One-shot rotation to yaw {result4}."); return; } PlayerDetail val2 = PlayerUtils.FindPlayerByQuery(text); if (val2 != null) { MoveUtil.LookAt(((Component)val2.PlayerTransform).transform.position); string text2 = ChatUtils.CleanTMPTags(val2.UserName).Trim(); ChatUtils.AddGlobalNotification("Facing toward " + text2 + "."); Logger.LogInfo((object)("One-shot rotation toward player " + text2 + ".")); } else { ChatUtils.AddGlobalNotification("Unknown target \"" + text + "\". Use degrees, cardinal, or player name."); } } private static bool TryParseCardinal(string s, out float angle) { string text = s.ToLowerInvariant(); if (1 == 0) { } float num = text switch { "north" => 0f, "n" => 0f, "east" => 90f, "e" => 90f, "south" => 180f, "s" => 180f, "west" => 270f, "w" => 270f, "northeast" => 45f, "ne" => 45f, "southeast" => 135f, "se" => 135f, "southwest" => 225f, "sw" => 225f, "northwest" => 315f, "nw" => 315f, _ => -1f, }; if (1 == 0) { } angle = num; return angle >= 0f; } } public class EchoRotateLockCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.EchoRotateLockCommand"); public string Name => "echorotatelock"; public string ShortName => "erl"; public string Description => "Lock rotation to a fixed value. Usage: /erl . Unlock with /eru."; public string Namespace => "echo"; public void Execute(string[] args) { //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /erl . Unlock with /eru."); return; } if (args.Length == 3 && float.TryParse(args[0], out var result) && float.TryParse(args[1], out var result2) && float.TryParse(args[2], out var result3)) { MoveUtil.LockRotation(result, result2, result3); ChatUtils.AddGlobalNotification($"Rotation locked to ({result}, {result2}, {result3}). Use /eru to unlock."); Logger.LogInfo((object)$"Rotation locked to ({result}, {result2}, {result3})."); return; } string text = string.Join(" ", args).Trim(); if (TryParseCardinal(text, out var angle)) { MoveUtil.LockRotation(0f, angle, 0f); ChatUtils.AddGlobalNotification($"Rotation locked to {text} ({angle} degrees). Use /eru to unlock."); Logger.LogInfo((object)$"Rotation locked to cardinal {text} ({angle})."); return; } if (float.TryParse(text, out var result4)) { MoveUtil.LockRotation(0f, result4, 0f); ChatUtils.AddGlobalNotification($"Rotation locked to {result4} degrees. Use /eru to unlock."); Logger.LogInfo((object)$"Rotation locked to yaw {result4}."); return; } PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val != null) { Vector3 localPlayerPosition = PlayerMovementControllerPatch.GetLocalPlayerPosition(); Vector3 val2 = ((Component)val.PlayerTransform).transform.position - localPlayerPosition; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { ChatUtils.AddGlobalNotification("Too close to target to determine direction."); return; } Quaternion val3 = Quaternion.LookRotation(val2); Vector3 eulerAngles = ((Quaternion)(ref val3)).eulerAngles; MoveUtil.LockRotation(eulerAngles.x, eulerAngles.y, eulerAngles.z); string text2 = ChatUtils.CleanTMPTags(val.UserName).Trim(); ChatUtils.AddGlobalNotification("Rotation locked toward " + text2 + ". Use /eru to unlock."); Logger.LogInfo((object)("Rotation locked toward player " + text2 + ".")); } else { ChatUtils.AddGlobalNotification("Unknown target \"" + text + "\". Use degrees, cardinal, or player name."); } } private static bool TryParseCardinal(string s, out float angle) { string text = s.ToLowerInvariant(); if (1 == 0) { } float num = text switch { "north" => 0f, "n" => 0f, "east" => 90f, "e" => 90f, "south" => 180f, "s" => 180f, "west" => 270f, "w" => 270f, "northeast" => 45f, "ne" => 45f, "southeast" => 135f, "se" => 135f, "southwest" => 225f, "sw" => 225f, "northwest" => 315f, "nw" => 315f, _ => -1f, }; if (1 == 0) { } angle = num; return angle >= 0f; } } public class EchoRotateUnlockCommand : IChatCommand, IComparable { public string Name => "echorotateunlock"; public string ShortName => "eru"; public string Description => "Stop all rotation overrides (lock, look-at)."; public string Namespace => "echo"; public void Execute(string[] args) { bool isRotationLocked = MoveUtil.IsRotationLocked; bool isLookingAt = PlayerMovementControllerPatch.IsLookingAt; if (!isRotationLocked && !isLookingAt) { ChatUtils.AddGlobalNotification("No rotation override active."); return; } MoveUtil.UnlockRotation(); PlayerMovementControllerPatch.StopLookingAt(); ChatUtils.AddGlobalNotification("Rotation unlocked."); } } public class EchoSetNameCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.EchoSetNameCommand"); public string Name => "echosetname"; public string ShortName => "esn"; public string Description => "Change name text while keeping current style. Usage: /esn "; public string Namespace => "echo"; public void Execute(string[] args) { if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /esn "); return; } string text = string.Join(" ", args).Trim(); if (text.Length == 0) { ChatUtils.AddGlobalNotification("Name cannot be empty."); return; } string name = NameUtil.GetName(); List list = NameStyleTransfer.ParseSegments(name); bool flag = false; foreach (NameStyleTransfer.StyledSegment item in list) { if (item.Tags.Length > 0) { flag = true; break; } } string text2 = (flag ? NameStyleTransfer.ApplyEven(list, text) : text); Logger.LogInfo((object)("Set name to \"" + text2 + "\" (preserving style).")); NameUtil.SetName(text2); ChatUtils.AddGlobalNotification("Name set to \"" + ChatUtils.CleanTMPTags(text2) + "\" with existing style."); } } public class EchoSyncRotationCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.EchoSyncRotationCommand"); public string Name => "echosyncrotation"; public string ShortName => "esr"; public string Description => "Mirror another player's facing direction. Usage: /esr . Stop with /eur."; public string Namespace => "echo"; public void Execute(string[] args) { if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /esr . Stop with /eur."); return; } string text = string.Join(" ", args).Trim(); PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } string text2 = ChatUtils.CleanTMPTags(val.UserName).Trim(); PlayerMovementControllerPatch.StartSyncingRotation(((Component)val.PlayerTransform).transform); Logger.LogInfo((object)("Syncing rotation to " + text2 + ".")); ChatUtils.AddGlobalNotification("Syncing rotation to " + text2 + ". Use /eur to stop."); } } public class EchoTeleportLocationCommand : IChatCommand, IComparable { private static readonly ManualLogSource _log = Logger.CreateLogSource("Echo.ETL"); public string Name => "echoteleportlocation"; public string ShortName => "etl"; public string Description => "Teleport to a saved location or save current spot. Usage: /etl | /etl "; public string Namespace => "echo"; public void Execute(string[] args) { //IL_0059: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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_0178: Unknown result type (might be due to invalid IL or missing references) if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /etl - teleport to or save a location\n /etl - teleport to coordinates"); return; } if (args.Length == 3 && float.TryParse(args[0], out var result) && float.TryParse(args[1], out var result2) && float.TryParse(args[2], out var result3)) { Vector3 targetPosition = default(Vector3); ((Vector3)(ref targetPosition))..ctor(result, result2, result3); MoveUtil.Teleport(targetPosition); ChatUtils.AddGlobalNotification($"Teleported to ({result}, {result2}, {result3})."); _log.LogInfo((object)$"Teleported to coordinates ({result}, {result2}, {result3})."); return; } string text = string.Join(" ", args).Trim(); SavedLocationManager locations = EchoPlugin.Locations; Vector3 pos; if (locations == null) { ChatUtils.AddGlobalNotification("Location manager not initialized."); } else if (locations.TryGet(text, out pos)) { MoveUtil.Teleport(pos); ChatUtils.AddGlobalNotification("Teleported to \"" + text + "\"."); _log.LogInfo((object)$"Teleported to saved location \"{text}\" at {pos}."); } else { PlayerDetail playerDetail = PlayerUtils.GetPlayerDetail(); Vector3 val = ((playerDetail != null) ? playerDetail.Position : Vector3.zero); locations.Save(text, val); ChatUtils.AddGlobalNotification($"Saved location \"{text}\" at {val}."); _log.LogInfo((object)$"Saved location \"{text}\" at {val}."); } } } public class EchoTeleportPersonCommand : IChatCommand, IComparable { private static readonly ManualLogSource Logger = Logger.CreateLogSource("Echo.EchoTpToCommand"); public string Name => "echoteleportperson"; public string ShortName => "etp"; public string Description => "Teleport to a player by name or Steam ID suffix. Usage: /echotpto [x y z]"; public string Namespace => "echo"; public void Execute(string[] args) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (args.Length == 0) { ChatUtils.AddGlobalNotification("Usage: /echotpto [x y z]"); return; } Vector3 zero = Vector3.zero; string text; if (args.Length >= 4 && float.TryParse(args[^3], out var result) && float.TryParse(args[^2], out var result2) && float.TryParse(args[^1], out var result3)) { ((Vector3)(ref zero))..ctor(result, result2, result3); text = string.Join(" ", args, 0, args.Length - 3); } else { text = string.Join(" ", args); } text = text.Trim(); PlayerDetail val = PlayerUtils.FindPlayerByQuery(text); if (val == null) { ChatUtils.AddGlobalNotification("Player \"" + text + "\" not found."); return; } Vector3 val2 = val.Position + zero; string text2 = ChatUtils.CleanTMPTags(val.UserName).Trim(); Logger.LogInfo((object)$"Teleporting to {text2} at {val.Position} + offset {zero} = {val2}"); MoveUtil.Teleport(val2); string text3 = ((zero == Vector3.zero) ? "" : $" (+{zero.x}, +{zero.y}, +{zero.z})"); ChatUtils.AddGlobalNotification("Teleporting to " + text2 + text3 + "."); } } public class EchoToggleCommand : IChatCommand, IComparable { public const string CMD = "echotoggle"; public string Name => "echotoggle"; public string ShortName => "et"; public string Description => "Toggle Echo feature on/off. "; public string Namespace => "echo"; public void Execute(string[] args) { if (EchoPlugin.EnableFeature != null) { EchoPlugin.EnableFeature.Value = !EchoPlugin.EnableFeature.Value; ChatUtils.AddGlobalNotification("Echo feature is now " + (EchoPlugin.EnableFeature.Value ? "enabled" : "disabled") + "."); } } } public class EchoUnfollowCommand : IChatCommand, IComparable { public string Name => "echounfollow"; public string ShortName => "eu"; public string Description => "Stop following the current target."; public string Namespace => "echo"; public void Execute(string[] args) { if (!PlayerMovementControllerPatch.IsFollowing) { ChatUtils.AddGlobalNotification("Not currently following anyone."); return; } PlayerMovementControllerPatch.StopFollowing(); ChatUtils.AddGlobalNotification("Stopped following."); } } public class EchoUnsyncRotationCommand : IChatCommand, IComparable { public string Name => "echounsyncrotation"; public string ShortName => "eur"; public string Description => "Stop syncing rotation to the current target."; public string Namespace => "echo"; public void Execute(string[] args) { if (!PlayerMovementControllerPatch.IsSyncingRotation) { ChatUtils.AddGlobalNotification("Not currently syncing rotation."); return; } PlayerMovementControllerPatch.StopSyncingRotation(); ChatUtils.AddGlobalNotification("Stopped syncing rotation."); } } }