Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Furniture Sizes v1.2.2
FurnitureSizes.dll
Decompiled 14 hours agousing System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using UnityEngine; using UnityEngine.InputSystem; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace FurnitureSizes; internal static class ModInfo { public const string GUID = "FurnitureSizes.Config"; public const string NAME = "Furniture Sizes"; public const string VERSION = "1.2.2"; public const string Section = "Furniture Sizes"; public const string LethalConfigGuid = "ainavt.lc.lethalconfig"; public const string InputUtilsGuid = "com.rune580.LethalCompanyInputUtils"; } internal class ScaleState { public Vector3 Original; public Vector3 Applied; public bool External; } internal class PrefabSize { public Vector3 Original; public Vector3 Previous; public Vector3 Desired; } [BepInPlugin("FurnitureSizes.Config", "Furniture Sizes", "1.2.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private void Awake() { Start(((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config, ((Component)this).gameObject); } internal static void Start(ManualLogSource log, ConfigFile config, GameObject managerObject) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown try { ((Object)managerObject).hideFlags = (HideFlags)61; } catch (Exception ex) { log.LogWarning((object)("Could not protect the BepInEx manager object: " + ex.Message)); } try { Sizer.Init(log, config); Harmony harmony = new Harmony("FurnitureSizes.Config"); TryPatch(harmony, typeof(TerminalAwakePatch)); TryPatch(harmony, typeof(LoadUnlockablesPatch)); TryPatch(harmony, typeof(GhostPatch)); Sizer.Log.LogInfo((object)"Furniture Sizes 1.2.2 loaded. The size list is created in the config the first time a ship loads."); } catch (Exception ex2) { log.LogError((object)("Furniture Sizes 1.2.2 could not start and is switched off: " + ex2)); } } private static void TryPatch(Harmony harmony, Type patchClass) { try { harmony.PatchAll(patchClass); } catch (Exception ex) { Sizer.Log.LogWarning((object)("Could not apply " + patchClass.Name + " (sizes are still applied by the periodic check): " + ex.Message)); } } } internal static class Sizer { internal const float MinSize = 0.05f; internal const float MaxSize = 25f; internal static ManualLogSource Log; private static ConfigFile config; private static ConfigEntry<bool> modEnabled; private static ConfigEntry<float> globalMultiplier; private static ConfigEntry<bool> fixPlacement; private static ConfigEntry<float> liftStrength; private static readonly Dictionary<string, ConfigEntry<string>> entries = new Dictionary<string, ConfigEntry<string>>(); private static readonly Dictionary<int, string> indexToKey = new Dictionary<int, string>(); private static readonly Dictionary<GameObject, ScaleState> prefabStates = new Dictionary<GameObject, ScaleState>(); private static readonly Dictionary<GameObject, ScaleState> instanceStates = new Dictionary<GameObject, ScaleState>(); private static readonly Dictionary<string, string> warned = new Dictionary<string, string>(); private static readonly List<Action> pendingGeneral = new List<Action>(); private static StartOfRound lastRound; private static bool applying; private static bool quiet; private static bool generalRegistered; private static GameObject tickerObject; internal static bool IsEnabled => modEnabled != null && modEnabled.Value; internal static bool PlacementEnabled => modEnabled != null && modEnabled.Value && fixPlacement != null && fixPlacement.Value; internal static float LiftStrength => (liftStrength != null) ? Math.Max(0f, liftStrength.Value) : 1f; internal static void Init(ManualLogSource log, ConfigFile configFile) { Log = log; config = configFile; modEnabled = config.Bind<bool>("General", "Enabled", true, "Master switch. Set to false to put every piece back to its normal size without uninstalling the mod."); globalMultiplier = config.Bind<float>("General", "GlobalMultiplier", 1f, "Extra multiplier applied to every piece on top of its own size. Leave it at 1 to size pieces one by one. 1.5 = everything 50% bigger."); fixPlacement = config.Bind<bool>("Placement", "FixPlacement", true, "In build mode, make the see-through preview follow a resized piece: draw it at the piece's real size, rest it on the floor (or wall) instead of sinking into it, and check for obstacles at the real size. Turn this off to get the game's own behaviour back. Pieces that were placed before the change must be picked up and placed again."); liftStrength = config.Bind<float>("Placement", "FloorOffsetStrength", 1f, "How strongly a resized piece is moved up (or away from a wall) so that it rests on the surface. 1 = exactly enough, 0 = not at all. Raise it if big pieces still sink, lower it if they float."); modEnabled.SettingChanged += OnSettingChanged; globalMultiplier.SettingChanged += OnSettingChanged; QueueBool(modEnabled, "Enabled"); QueueFloat(globalMultiplier, "Global multiplier"); QueueBool(fixPlacement, "Fix placement"); QueueFloat(liftStrength, "Floor offset strength"); Keybinds.Init(config); RegisterGeneral(); EnsureTicker(); } private static void EnsureTicker() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown if ((Object)(object)tickerObject != (Object)null) { return; } tickerObject = new GameObject("FurnitureSizes_Ticker"); ((Object)tickerObject).hideFlags = (HideFlags)61; tickerObject.AddComponent<SizerTicker>(); try { tickerObject.AddComponent<SizerOverlay>(); } catch (Exception ex) { Log.LogWarning((object)("The on-screen size readout is not available: " + ex.Message)); } } internal static void Tick() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { lastRound = null; } else { SafeApply((!((Object)(object)instance != (Object)(object)lastRound)) ? "periodic" : "ship scene loaded"); } } private static void OnSettingChanged(object sender, EventArgs e) { SafeApply("config changed"); } internal static void SafeApply(string reason) { if (modEnabled == null || applying) { return; } applying = true; try { EnsureTicker(); ApplyAll(reason); } catch (Exception ex) { Log.LogError((object)("Furniture Sizes could not apply the sizes (" + reason + "): " + ex)); } finally { applying = false; } } internal static void SetQuiet(bool value) { quiet = value; } internal static bool TryGetKey(int unlockableIndex, out string key) { return indexToKey.TryGetValue(unlockableIndex, out key); } internal static string PieceName(int unlockableIndex) { string value; return (!indexToKey.TryGetValue(unlockableIndex, out value)) ? "furniture piece" : value; } internal static ConfigEntry<string> EntryFor(string key) { ConfigEntry<string> value; return (!entries.TryGetValue(key, out value)) ? null : value; } internal static Vector3 FactorFor(GameObject root) { //IL_000c: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return Vector3.one; } if (!instanceStates.TryGetValue(root, out var value) || value.External) { return Vector3.one; } Vector3 localScale = root.transform.localScale; return new Vector3(Ratio(localScale.x, value.Original.x), Ratio(localScale.y, value.Original.y), Ratio(localScale.z, value.Original.z)); } internal static bool IsExternal(GameObject root) { if ((Object)(object)root == (Object)null) { return false; } ScaleState value; return instanceStates.TryGetValue(root, out value) && value.External; } private static float Ratio(float value, float original) { return (!(Math.Abs(original) < 1E-05f)) ? (value / original) : 1f; } private static void ApplyAll(string reason) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.unlockablesList == null || instance.unlockablesList.unlockables == null) { return; } lastRound = instance; RegisterGeneral(); Prune(); bool value = modEnabled.Value; float num = ClampSize(globalMultiplier.Value); List<UnlockableItem> unlockables = instance.unlockablesList.unlockables; Dictionary<int, GameObject> dictionary = FindInstances(instance); indexToKey.Clear(); Dictionary<string, bool> used = new Dictionary<string, bool>(); int num2 = 0; int num3 = 0; int num4 = 0; int changes = 0; for (int i = 0; i < unlockables.Count; i++) { UnlockableItem val = unlockables[i]; try { if (IsFurniture(val)) { string text = UniqueKey(val.unlockableName, used); indexToKey[i] = text; ConfigEntry<string> entry = GetEntry(text, val); num2++; float x = 1f; float y = 1f; float z = 1f; if (value) { ReadSize(text, entry.Value, out x, out y, out z); x = ClampSize(x * num); y = ClampSize(y * num); z = ClampSize(z * num); } if (Math.Abs(x - 1f) > 0.0001f || Math.Abs(y - 1f) > 0.0001f || Math.Abs(z - 1f) > 0.0001f) { num3++; } PrefabSize prefab = null; if ((Object)(object)val.prefabObject != (Object)null) { prefab = ApplyToPrefab(text, val.prefabObject, x, y, z, ref changes); } if (dictionary.TryGetValue(i, out var value2)) { num4++; ApplyToInstance(text, value2, prefab, x, y, z, ref changes); } } } catch (Exception ex) { Log.LogError((object)("Furniture Sizes: could not process '" + ((val != null) ? val.unlockableName : "?") + "': " + ex.Message)); } } if ((reason != "periodic" || changes > 0) && !quiet) { Log.LogInfo((object)("Sizes " + ((!value) ? "reset (the mod is switched off in the config)" : "applied") + " (" + reason + "): " + num2 + " pieces listed, " + num3 + " with a custom size, " + num4 + " found in the ship.")); } } internal static bool IsFurniture(UnlockableItem item) { return item != null && item.unlockableType != 0 && item.IsPlaceable; } private static Dictionary<int, GameObject> FindInstances(StartOfRound round) { Dictionary<int, GameObject> dictionary = new Dictionary<int, GameObject>(); if (round.SpawnedShipUnlockables != null) { foreach (KeyValuePair<int, GameObject> spawnedShipUnlockable in round.SpawnedShipUnlockables) { if ((Object)(object)spawnedShipUnlockable.Value != (Object)null) { dictionary[spawnedShipUnlockable.Key] = spawnedShipUnlockable.Value; } } } PlaceableShipObject[] array = Object.FindObjectsOfType<PlaceableShipObject>(); if (array != null) { foreach (PlaceableShipObject val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.parentObject == (Object)null) && !dictionary.ContainsKey(val.unlockableID)) { dictionary[val.unlockableID] = ((Component)val.parentObject).gameObject; } } } return dictionary; } private static PrefabSize ApplyToPrefab(string label, GameObject prefab, float fx, float fy, float fz, ref int changes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) //IL_0022: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0144: 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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0156: 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_00d4: Unknown result type (might be due to invalid IL or missing references) Transform transform = prefab.transform; Vector3 localScale = transform.localScale; Vector3 val; Vector3 val2; if (prefabStates.TryGetValue(prefab, out var value) && PlacementMath.Close(localScale, value.Applied)) { val = value.Original; val2 = value.Applied; } else { val = localScale; val2 = localScale; } Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(val.x * fx, val.y * fy, val.z * fz); if (!PlacementMath.Close(localScale, val3)) { transform.localScale = val3; } ScaleState scaleState = new ScaleState(); scaleState.Original = val; scaleState.Applied = val3; prefabStates[prefab] = scaleState; if (!PlacementMath.Close(val2, val3)) { changes++; if (!quiet) { Log.LogInfo((object)(label + ": " + ((!PlacementMath.Close(val3, val)) ? ("size set to " + Format(fx) + ", " + Format(fy) + ", " + Format(fz) + " times its normal size for new copies.") : "normal size restored for new copies."))); } } PrefabSize prefabSize = new PrefabSize(); prefabSize.Original = val; prefabSize.Previous = val2; prefabSize.Desired = val3; return prefabSize; } private static void ApplyToInstance(string label, GameObject instance, PrefabSize prefab, float fx, float fy, float fz, ref int changes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_002e: 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_0118: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0194: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0079: Unknown result type (might be due to invalid IL or missing references) Transform transform = instance.transform; Vector3 localScale = transform.localScale; if (!instanceStates.TryGetValue(instance, out var value)) { value = new ScaleState(); if (prefab != null) { if (!PlacementMath.Close(localScale, prefab.Original) && !PlacementMath.Close(localScale, prefab.Previous) && !PlacementMath.Close(localScale, prefab.Desired)) { value.Original = localScale; value.Applied = localScale; value.External = true; instanceStates[instance] = value; return; } value.Original = prefab.Original; } else { value.Original = localScale; } value.Applied = localScale; instanceStates[instance] = value; } if (value.External) { return; } if (!PlacementMath.Close(localScale, value.Applied) && !PlacementMath.Close(localScale, value.Original)) { value.External = true; return; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(value.Original.x * fx, value.Original.y * fy, value.Original.z * fz); if (!PlacementMath.Close(localScale, val)) { transform.localScale = val; changes++; if (!quiet) { Log.LogInfo((object)(label + ": the piece in the ship is now " + Format(fx) + ", " + Format(fy) + ", " + Format(fz) + " times its normal size.")); } } value.Applied = val; } private static void Prune() { RemoveDestroyed(instanceStates); RemoveDestroyed(prefabStates); } private static void RemoveDestroyed<T>(Dictionary<GameObject, T> map) { List<GameObject> list = null; foreach (KeyValuePair<GameObject, T> item in map) { if ((Object)(object)item.Key == (Object)null) { if (list == null) { list = new List<GameObject>(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { map.Remove(list[i]); } } } internal static string Format(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } internal static string FormatSize(float x, float y, float z) { if (Math.Abs(x - y) < 0.0001f && Math.Abs(y - z) < 0.0001f) { return Format(x); } return Format(x) + ", " + Format(y) + ", " + Format(z); } private static ConfigEntry<string> GetEntry(string key, UnlockableItem item) { if (entries.TryGetValue(key, out var value)) { return value; } string text = "Size of '" + item.unlockableName + "'. 1 = normal size, 2 = twice as big, 0.5 = half as big. Use one number for every direction, or three numbers (x, y, z) to stretch it: '1, 2, 1' makes it twice as tall. Use a dot for decimals. Each number can be from " + Format(0.05f) + " to " + Format(25f) + ". You can also look at the piece in the ship and use the resize keys."; if (HasComponentNamed(item.prefabObject, "PocketRoom")) { text += " This piece contains a Pocket Room: changing its size is not supported, leave it at 1."; } if (item.unlockableName == "Terminal") { text += " This is the ship's terminal: sizes other than 1 may break its screen."; } value = config.Bind<string>("Furniture Sizes", key, "1", text); value.SettingChanged += OnSettingChanged; entries[key] = value; RegisterText(value, key); return value; } private static void ReadSize(string key, string text, out float x, out float y, out float z) { if (!TryParseSize(text, out x, out y, out z)) { x = 1f; y = 1f; z = 1f; WarnOnce(key, text, "'" + text + "' is not a valid size. Use one number such as 2, or three such as 1, 2, 1 (with a dot for decimals). Using 1 instead."); return; } float num = ClampSize(x); float num2 = ClampSize(y); float num3 = ClampSize(z); if (num != x || num2 != y || num3 != z) { WarnOnce(key, text, "'" + text + "' is outside the allowed range of " + Format(0.05f) + " to " + Format(25f) + ", it was adjusted."); } x = num; y = num2; z = num3; } private static void WarnOnce(string key, string text, string message) { if (!warned.TryGetValue(key, out var value) || !(value == text)) { warned[key] = text; Log.LogWarning((object)(key + ": " + message)); } } internal static float ClampSize(float value) { if (float.IsNaN(value)) { return 1f; } return Math.Min(25f, Math.Max(0.05f, value)); } internal static bool TryParseSize(string text, out float x, out float y, out float z) { x = 1f; y = 1f; z = 1f; if (string.IsNullOrEmpty(text)) { return false; } string[] array = text.Split(new char[10] { ',', ';', ' ', '\t', '(', ')', '{', '}', '[', ']' }, StringSplitOptions.RemoveEmptyEntries); float[] array2 = new float[array.Length]; for (int i = 0; i < array.Length; i++) { if (!float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return false; } if (float.IsNaN(result) || float.IsInfinity(result) || result <= 0f) { return false; } array2[i] = result; } if (array.Length == 1) { x = array2[0]; y = array2[0]; z = array2[0]; return true; } if (array.Length == 3) { x = array2[0]; y = array2[1]; z = array2[2]; return true; } return false; } internal static string Sanitize(string name) { if (string.IsNullOrEmpty(name)) { return "Unnamed"; } StringBuilder stringBuilder = new StringBuilder(); foreach (char c in name) { if (c != '\n' && c != '\r' && c != '\t' && c != '\\' && c != '"' && c != '\'' && c != '[' && c != ']' && c != '=') { stringBuilder.Append(c); } } string text = stringBuilder.ToString().Trim(); return (text.Length != 0) ? text : "Unnamed"; } internal static string UniqueKey(string name, Dictionary<string, bool> used) { string text = Sanitize(name); string text2 = text; int num = 2; while (used.ContainsKey(text2)) { text2 = text + " (" + num + ")"; num++; } used[text2] = true; return text2; } private static bool HasComponentNamed(GameObject go, string typeName) { if ((Object)(object)go == (Object)null) { return false; } Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true); if (componentsInChildren == null) { return false; } for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && ((object)componentsInChildren[i]).GetType().Name == typeName) { return true; } } return false; } private static bool LethalConfigInstalled() { return Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig"); } internal static void QueueBool(ConfigEntry<bool> entry, string name) { pendingGeneral.Add(delegate { LethalConfigProxy.AddBool(entry, name); }); } internal static void QueueFloat(ConfigEntry<float> entry, string name) { pendingGeneral.Add(delegate { LethalConfigProxy.AddFloat(entry, name); }); } private static void RegisterGeneral() { if (generalRegistered || !LethalConfigInstalled()) { return; } try { for (int i = 0; i < pendingGeneral.Count; i++) { pendingGeneral[i](); } generalRegistered = true; } catch (Exception ex) { WarnOnce("LethalConfig", ex.GetType().Name, "Could not add the General settings to LethalConfig yet (will retry; the .cfg file still works): " + ex.Message); } } private static void RegisterText(ConfigEntry<string> entry, string name) { if (!LethalConfigInstalled()) { return; } try { LethalConfigProxy.AddText(entry, name); } catch (Exception ex) { WarnOnce("LethalConfig", ex.GetType().Name, "Could not add the entries to LethalConfig (the .cfg file still works): " + ex.Message); } } } internal static class PlacementMath { internal const float BoxHalfFactor = 0.285f; internal static bool Close(Vector3 a, Vector3 b) { return Math.Abs(a.x - b.x) < 0.0001f && Math.Abs(a.y - b.y) < 0.0001f && Math.Abs(a.z - b.z) < 0.0001f; } internal static bool IsOne(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Close(v, Vector3.one); } internal static Vector3 Mul(Vector3 a, Vector3 b) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z); } internal static Vector3 Inverse(Vector3 f) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) return new Vector3(Inv(f.x), Inv(f.y), Inv(f.z)); } private static float Inv(float v) { return (!(Math.Abs(v) < 1E-05f)) ? (1f / v) : 1f; } internal static Vector3 AtOriginalSize(Quaternion rootRotation, Vector3 ratio, Vector3 offset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_000f: 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_0015: Unknown result type (might be due to invalid IL or missing references) Vector3 a = Quaternion.Inverse(rootRotation) * offset; return rootRotation * Mul(a, ratio); } internal static float Stretch(Quaternion rootRotation, Vector3 ratio, Vector3 direction) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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) Vector3 val = AtOriginalSize(rootRotation, ratio, ((Vector3)(ref direction)).normalized); float magnitude = ((Vector3)(ref val)).magnitude; return (!(magnitude < 1E-05f)) ? (1f / magnitude) : 1f; } internal static Vector3 Corner(Vector3 center, Vector3 extents, int i) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) return new Vector3(center.x + (((i & 1) != 0) ? extents.x : (0f - extents.x)), center.y + (((i & 2) != 0) ? extents.y : (0f - extents.y)), center.z + (((i & 4) != 0) ? extents.z : (0f - extents.z))); } internal static float Reach(Vector3[] offsets, Quaternion yaw, Vector3 n) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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) float num = float.MinValue; for (int i = 0; i < offsets.Length; i++) { float num2 = 0f - Vector3.Dot(yaw * offsets[i], n); if (num2 > num) { num = num2; } } return num; } internal static float Lift(Vector3[] now, Vector3[] original, Quaternion yaw, Vector3 n) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) return Reach(now, yaw, n) - Reach(original, yaw, n); } internal static Vector3 SameSigns(Vector3 magnitudes, Vector3 signs) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) return new Vector3(Math.Abs(magnitudes.x) * ((!(signs.x < 0f)) ? 1f : (-1f)), Math.Abs(magnitudes.y) * ((!(signs.y < 0f)) ? 1f : (-1f)), Math.Abs(magnitudes.z) * ((!(signs.z < 0f)) ? 1f : (-1f))); } } internal static class PlacementAssist { private enum Aim { Floor, Wall, Lean } private const float PlacementRange = 4f; private const float OutlineGrow = 1.04f; private static bool resolved; private static bool disabled; private static int errors; private static FieldInfo placingField; private static FieldInfo canConfirmField; private static FieldInfo blockersMaskField; private static FieldInfo currentColliderField; private static FieldInfo rayField; private static FieldInfo placementMaskField; private static FieldInfo mainMeshField; private static FieldInfo outlineField; private static FieldInfo allowWallsField; private static FieldInfo pointCheckField; private static FieldInfo pointCheckOffsetField; private static PlaceableShipObject current; private static bool touched; private static bool havePos; private static Vector3 lastSet; private static Vector3 lastDelta; private static Vector3 rootStart; private static float expectedLow; private static bool noted; private static readonly Vector3[] cornersNow = (Vector3[])(object)new Vector3[8]; private static readonly Vector3[] cornersOriginal = (Vector3[])(object)new Vector3[8]; private static PlaceableShipObject settlePiece; private static Vector3 settleStart; private static float settleExpected; private static int settleFrames; private static void Resolve() { if (!resolved) { resolved = true; BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; Type typeFromHandle = typeof(ShipBuildModeManager); Type typeFromHandle2 = typeof(PlaceableShipObject); placingField = Field(typeFromHandle, "placingObject", typeof(PlaceableShipObject), bindingFlags); canConfirmField = Field(typeFromHandle, "CanConfirmPosition", typeof(bool), bindingFlags); blockersMaskField = Field(typeFromHandle, "placementMaskAndBlockers", typeof(int), bindingFlags); rayField = Field(typeFromHandle, "playerCameraRay", typeof(Ray), bindingFlags); placementMaskField = Field(typeFromHandle, "placementMask", typeof(int), bindingFlags); currentColliderField = Field(typeFromHandle, "currentCollider", typeof(Collider), bindingFlags); outlineField = Field(typeFromHandle, "selectionOutlineRenderer", typeof(Component), bindingFlags); mainMeshField = typeFromHandle2.GetField("mainMesh", bindingFlags); allowWallsField = Field(typeFromHandle2, "AllowPlacementOnWalls", typeof(bool), bindingFlags); pointCheckField = Field(typeFromHandle2, "doCollisionPointCheck", typeof(bool), bindingFlags); pointCheckOffsetField = Field(typeFromHandle2, "collisionPointCheck", typeof(Vector3), bindingFlags); if (placingField == null) { Sizer.Log.LogWarning((object)"ShipBuildModeManager.placingObject was not found (a game update?). The build-mode preview will not follow the size of resized pieces."); } else if (canConfirmField == null || blockersMaskField == null) { Sizer.Log.LogWarning((object)"The game's obstacle check fields were not found (a game update?). The preview follows the size, but obstacles are checked the game's way."); } } } private static FieldInfo Field(Type owner, string name, Type type, BindingFlags flags) { FieldInfo field = owner.GetField(name, flags); if (field == null) { return null; } if (field.FieldType == type) { return field; } if (!type.IsValueType && type.IsAssignableFrom(field.FieldType)) { return field; } return null; } internal static void Settle() { //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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)settlePiece == (Object)null) { return; } settleFrames--; if (settleFrames > 0) { return; } PlaceableShipObject val = settlePiece; settlePiece = null; try { if ((Object)(object)val == (Object)null) { return; } Transform val2 = ((!((Object)(object)val.parentObject != (Object)null)) ? ((Component)val).transform : ((Component)val.parentObject).transform); if ((Object)(object)val2 == (Object)null) { return; } Vector3 val3 = val2.position - settleStart; if (((Vector3)(ref val3)).magnitude <= 0.02f || float.IsNaN(settleExpected)) { return; } Transform val4 = MeshOf(val); MeshFilter val5 = FilterOf(val); if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val5 == (Object)null) && !((Object)(object)val5.sharedMesh == (Object)null)) { Bounds bounds = val5.sharedMesh.bounds; float num = float.MaxValue; for (int i = 0; i < 8; i++) { num = Math.Min(num, val4.TransformPoint(PlacementMath.Corner(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents, i)).y); } float num2 = num - settleExpected; string text = Sizer.PieceName(val.unlockableID); if (Math.Abs(num2) <= 0.03f) { Sizer.Log.LogInfo((object)(text + ": placed. The piece rests where the preview showed it (difference " + Sizer.Format(num2) + " m).")); return; } Sizer.Log.LogInfo((object)(text + ": placed. The base of the piece is " + Sizer.Format(Math.Abs(num2)) + " m " + ((!(num2 < 0f)) ? "above" : "below") + " where the preview showed it. If it looks wrong in the game, please send this line with the log.")); } } catch (Exception ex) { Sizer.Log.LogWarning((object)("Could not check where the piece was placed: " + ex.Message)); } } internal static PlaceableShipObject Carried() { ShipBuildModeManager instance = ShipBuildModeManager.Instance; if ((Object)(object)instance == (Object)null || !instance.InBuildMode) { return null; } Resolve(); return (PlaceableShipObject)((!(placingField == null)) ? /*isinst with value type is only supported in some contexts*/: null); } internal static void AfterGhost(ShipBuildModeManager manager) { if (disabled || (Object)(object)manager == (Object)null) { return; } try { Resolve(); Process(manager); } catch (Exception ex) { errors++; if (errors <= 3) { Sizer.Log.LogError((object)("The placement fix hit an error: " + ex)); } if (errors >= 5) { disabled = true; Sizer.Log.LogError((object)"The placement fix was switched off for this session after repeated errors. Everything else keeps working."); } } } private static void Process(ShipBuildModeManager manager) { //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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_0492: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) Transform ghostObject = manager.ghostObject; PlaceableShipObject val = null; if (manager.InBuildMode && placingField != null) { object? value = placingField.GetValue(manager); val = (PlaceableShipObject)((value is PlaceableShipObject) ? value : null); } if ((Object)(object)ghostObject == (Object)null || (Object)(object)val == (Object)null || !Sizer.PlacementEnabled) { Finish(); return; } Transform val2 = ((!((Object)(object)val.parentObject != (Object)null)) ? ((Component)val).transform : ((Component)val.parentObject).transform); if ((Object)(object)val2 == (Object)null) { Finish(); return; } if ((Object)(object)val != (Object)(object)current) { Finish(); current = val; touched = false; havePos = false; noted = false; expectedLow = float.NaN; rootStart = val2.position; } Vector3 val3 = Sizer.FactorFor(((Component)val2).gameObject); if (!PlacementMath.IsOne(val3)) { touched = true; } if (!touched) { return; } Transform val4 = MeshOf(val); Transform val5 = ((!((Object)(object)val.placeObjectCollider != (Object)null)) ? null : ((Component)val.placeObjectCollider).transform); MeshFilter val6 = FilterOf(val); bool flag = (Object)(object)val4 != (Object)null && (Object)(object)val5 != (Object)null && (Object)(object)val6 != (Object)null && (Object)(object)val6.sharedMesh != (Object)null && val4.IsChildOf(val2) && val5.IsChildOf(val2); if (!flag && !noted) { noted = true; Sizer.Log.LogWarning((object)(Sizer.PieceName(val.unlockableID) + ": the piece's model or placement collider could not be read, so the build-mode preview is left to the game for this piece.")); } if (!flag) { return; } Vector3 position = ghostObject.position; Vector3 val7 = ((!havePos || !PlacementMath.Close(position, lastSet)) ? position : (lastSet - lastDelta)); Quaternion yaw = ghostObject.rotation * Quaternion.Inverse(val4.rotation); Bounds bounds = val6.sharedMesh.bounds; Vector3 position2 = val5.position; Vector3 ratio = PlacementMath.Inverse(val3); Vector3[] array = cornersNow; Vector3[] array2 = cornersOriginal; for (int i = 0; i < 8; i++) { Vector3 val8 = val4.TransformPoint(PlacementMath.Corner(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents, i)); ref Vector3 reference = ref array[i]; reference = val8 - position2; ref Vector3 reference2 = ref array2[i]; reference2 = PlacementMath.AtOriginalSize(val2.rotation, ratio, array[i]); } Vector3 normal; Aim aim = AimAt(manager, val, out normal); float liftStrength = Sizer.LiftStrength; Vector3 val9; if (aim == Aim.Wall) { val9 = normal * (PlacementMath.Lift(array, array2, yaw, normal) * liftStrength); } else { val9 = Vector3.up * (PlacementMath.Lift(array, array2, yaw, Vector3.up) * liftStrength); Vector3 normalized = default(Vector3); ((Vector3)(ref normalized))..ctor(normal.x, 0f, normal.z); if (aim == Aim.Lean && ((Vector3)(ref normalized)).magnitude > 0.2f) { normalized = ((Vector3)(ref normalized)).normalized; val9 += normalized * (PlacementMath.Lift(array, array2, yaw, normalized) * liftStrength); } } ghostObject.position = val7 + val9; lastSet = ghostObject.position; lastDelta = lastSet - val7; havePos = true; expectedLow = lastSet.y - PlacementMath.Reach(array, yaw, Vector3.up); if (!noted) { noted = true; Vector3 val10 = default(Vector3); ((Vector3)(ref val10))..ctor(lastDelta.x, 0f, lastDelta.z); Sizer.Log.LogInfo((object)(Sizer.PieceName(val.unlockableID) + ": build-mode preview now follows the size (" + Sizer.FormatSize(val3.x, val3.y, val3.z) + "), moved " + Sizer.Format(lastDelta.y) + " m up/down and " + Sizer.Format(((Vector3)(ref val10)).magnitude) + " m sideways to rest on the surface.")); } DrawPreview(manager, ghostObject, val4, val5, yaw); Vector3 axes = default(Vector3); ((Vector3)(ref axes))..ctor(PlacementMath.Stretch(val2.rotation, ratio, val4.right), PlacementMath.Stretch(val2.rotation, ratio, val4.up), PlacementMath.Stretch(val2.rotation, ratio, val4.forward)); CheckObstacles(manager, val, ghostObject, axes, val7); } private static Aim AimAt(ShipBuildModeManager manager, PlaceableShipObject placing, out Vector3 normal) { //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_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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_008a: 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) normal = Vector3.up; if (rayField == null || placementMaskField == null) { return Aim.Floor; } Ray val = (Ray)rayField.GetValue(manager); int num = (int)placementMaskField.GetValue(manager); RaycastHit val2 = default(RaycastHit); if (!Physics.Raycast(val, ref val2, 4f, num, (QueryTriggerInteraction)1)) { return Aim.Floor; } if (Vector3.Angle(((RaycastHit)(ref val2)).normal, Vector3.up) < 45f) { return Aim.Floor; } Vector3 normal2 = ((RaycastHit)(ref val2)).normal; normal = ((Vector3)(ref normal2)).normalized; return (allowWallsField != null && (bool)allowWallsField.GetValue(placing)) ? Aim.Wall : Aim.Lean; } private static void DrawPreview(ShipBuildModeManager manager, Transform ghost, Transform mesh, Transform collider, Quaternion yaw) { //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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) Vector3 lossyScale = mesh.lossyScale; Transform val = ((!((Object)(object)manager.ghostObjectRenderer != (Object)null)) ? null : ((Component)manager.ghostObjectRenderer).transform); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)ghost) { val.position = ghost.position + yaw * (mesh.position - collider.position); if ((Object)(object)val.parent != (Object)(object)ghost) { val.rotation = ghost.rotation; } SetWorldScale(val, PlacementMath.SameSigns(lossyScale, val.localScale)); } Transform val2 = OutlineOf(manager); if ((Object)(object)val2 != (Object)null) { val2.position = mesh.position; val2.rotation = mesh.rotation; SetWorldScale(val2, PlacementMath.SameSigns(lossyScale * 1.04f, val2.localScale)); } } private static Transform OutlineOf(ShipBuildModeManager manager) { if (outlineField == null) { return null; } object? value = outlineField.GetValue(manager); Component val = (Component)((value is Component) ? value : null); return (!((Object)(object)val != (Object)null)) ? null : val.transform; } private static void SetWorldScale(Transform t, Vector3 world) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_00db: Unknown result type (might be due to invalid IL or missing references) if (!(Math.Abs(world.x) < 1E-05f) && !(Math.Abs(world.y) < 1E-05f) && !(Math.Abs(world.z) < 1E-05f)) { Vector3 val = ((!((Object)(object)t.parent != (Object)null)) ? Vector3.one : t.parent.lossyScale); if (!(Math.Abs(val.x) < 1E-05f) && !(Math.Abs(val.y) < 1E-05f) && !(Math.Abs(val.z) < 1E-05f)) { t.localScale = new Vector3(world.x / val.x, world.y / val.y, world.z / val.z); } } } private static void CheckObstacles(ShipBuildModeManager manager, PlaceableShipObject placing, Transform ghost, Vector3 axes, Vector3 vanillaPos) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //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_0132: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014c: 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) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) if (canConfirmField == null || blockersMaskField == null || !(bool)canConfirmField.GetValue(manager)) { return; } bool flag = false; StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.shipInnerRoomBounds != (Object)null) { Bounds bounds = instance.shipInnerRoomBounds.bounds; if (((Bounds)(ref bounds)).Contains(vanillaPos) && !((Bounds)(ref bounds)).Contains(ghost.position)) { flag = true; } } int num = (int)blockersMaskField.GetValue(manager); if (!flag) { BoxCollider val = null; if (currentColliderField != null) { object? value = currentColliderField.GetValue(manager); val = (BoxCollider)((value is BoxCollider) ? value : null); } if ((Object)(object)val == (Object)null) { Collider placeObjectCollider = placing.placeObjectCollider; val = (BoxCollider)(object)((placeObjectCollider is BoxCollider) ? placeObjectCollider : null); } if ((Object)(object)val != (Object)null) { Vector3 size = val.size; Vector3 val2 = new Vector3(Math.Abs(size.x * axes.x), Math.Abs(size.y * axes.y), Math.Abs(size.z * axes.z)) * 0.285f; flag = Physics.CheckBox(ghost.position, val2, ghost.rotation, num, (QueryTriggerInteraction)1); } } if (!flag && pointCheckField != null && pointCheckOffsetField != null && (bool)pointCheckField.GetValue(placing)) { Vector3 val3 = (Vector3)pointCheckOffsetField.GetValue(placing); Vector3 val4 = ghost.position + ghost.forward * (val3.z * axes.z) + ghost.right * (val3.x * axes.x) + ghost.up * (val3.y * axes.y); flag = Physics.CheckSphere(val4, 1f, num, (QueryTriggerInteraction)1); } if (flag) { canConfirmField.SetValue(manager, false); if ((Object)(object)manager.ghostObjectRenderer != (Object)null && (Object)(object)manager.ghostObjectRed != (Object)null) { ((Renderer)manager.ghostObjectRenderer).sharedMaterial = manager.ghostObjectRed; } } } private static Transform MeshOf(PlaceableShipObject placing) { if (mainMeshField == null) { return null; } object value = mainMeshField.GetValue(placing); Component val = (Component)((value is Component) ? value : null); if ((Object)(object)val != (Object)null) { return val.transform; } GameObject val2 = (GameObject)((value is GameObject) ? value : null); return (!((Object)(object)val2 != (Object)null)) ? null : val2.transform; } private static MeshFilter FilterOf(PlaceableShipObject placing) { if (mainMeshField == null) { return null; } object value = mainMeshField.GetValue(placing); MeshFilter val = (MeshFilter)((value is MeshFilter) ? value : null); if ((Object)(object)val != (Object)null) { return val; } Component val2 = (Component)((value is Component) ? value : null); if ((Object)(object)val2 != (Object)null) { return val2.GetComponent<MeshFilter>(); } GameObject val3 = (GameObject)((value is GameObject) ? value : null); return (!((Object)(object)val3 != (Object)null)) ? null : val3.GetComponent<MeshFilter>(); } private static void Finish() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)current == (Object)null)) { if (touched) { settlePiece = current; settleStart = rootStart; settleExpected = expectedLow; settleFrames = 20; } current = null; touched = false; havePos = false; noted = false; } } } internal static class Keybinds { private const int DefaultPlaceableMask = 67108864; private const int ActionCount = 7; private const int ResetIndex = 6; private const float RepeatDelay = 0.4f; private const float RepeatInterval = 0.1f; private static readonly float[] nextRepeat = new float[7]; private static ConfigEntry<bool> enabled; private static ConfigEntry<bool> holdToRepeat; private static ConfigEntry<bool> showReadout; private static ConfigEntry<float> step; private static ConfigEntry<float> range; private static bool inputReady; internal static void Init(ConfigFile config) { enabled = config.Bind<bool>("Keybinds", "Enabled", true, "Look at a piece of furniture (or carry it in build mode) and use the resize keys (see the game's controls menu to change them). Needs LethalCompany InputUtils."); step = config.Bind<float>("Keybinds", "Step", 0.1f, "How much one key press changes the size of the axis."); holdToRepeat = config.Bind<bool>("Keybinds", "HoldToRepeat", true, "Keep changing the size while the key is held down."); range = config.Bind<float>("Keybinds", "Range", 8f, "How far away, in metres, a piece can be to resize it by looking at it."); showReadout = config.Bind<bool>("Keybinds", "ShowReadout", true, "Show the piece's name and size on screen for a moment after a key press."); Sizer.QueueBool(enabled, "Resize keys enabled"); Sizer.QueueFloat(step, "Step per key press"); Sizer.QueueBool(holdToRepeat, "Hold to repeat"); Sizer.QueueFloat(range, "Range"); Sizer.QueueBool(showReadout, "Show size on screen"); if (!Chainloader.PluginInfos.ContainsKey("com.rune580.LethalCompanyInputUtils")) { Sizer.Log.LogInfo((object)"LethalCompany InputUtils is not installed, so the resize keys are off. Sizes can still be set in the config."); return; } try { InputProxy.Create(); inputReady = true; Sizer.Log.LogInfo((object)"Resize keys ready: Insert/Delete = X, Home/End = Y, PageUp/PageDown = Z, \\ = reset (rebind them in the game's controls menu)."); } catch (Exception ex) { Sizer.Log.LogWarning((object)("Could not create the resize keys (sizes can still be set in the config): " + ex.Message)); } } internal static void Poll() { if (!inputReady || !enabled.Value) { return; } try { float unscaledTime = Time.unscaledTime; for (int i = 0; i < 7; i++) { if (InputProxy.Pressed(i)) { nextRepeat[i] = ((!holdToRepeat.Value || i == 6) ? 0f : (unscaledTime + 0.4f)); Act(i, repeating: false); } else if (nextRepeat[i] > 0f) { if (!InputProxy.Held(i)) { nextRepeat[i] = 0f; } else if (unscaledTime >= nextRepeat[i]) { nextRepeat[i] = unscaledTime + 0.1f; Act(i, repeating: true); } } } } catch (Exception ex) { inputReady = false; Sizer.Log.LogError((object)("The resize keys stopped working: " + ex)); } } internal static void Act(int index, bool repeating) { if (!CanUseKeys()) { return; } PlaceableShipObject val = FindTarget(); if ((Object)(object)val == (Object)null) { if (!repeating) { Readout("Furniture size", "Look at a piece of furniture first."); } return; } if (!Sizer.TryGetKey(val.unlockableID, out var key)) { if (!repeating) { Readout("Furniture size", "This piece is not in the size list."); } return; } if (!Sizer.IsEnabled) { if (!repeating) { Readout("Furniture size", "Furniture Sizes is switched off in the config."); } return; } Transform val2 = ((!((Object)(object)val.parentObject != (Object)null)) ? ((Component)val).transform : ((Component)val.parentObject).transform); if ((Object)(object)val2 != (Object)null && Sizer.IsExternal(((Component)val2).gameObject)) { if (!repeating) { Readout(key, "Another mod has resized this piece, so the keys leave it alone."); } return; } ConfigEntry<string> val3 = Sizer.EntryFor(key); if (val3 != null) { if (!Sizer.TryParseSize(val3.Value, out var x, out var y, out var z)) { x = 1f; y = 1f; z = 1f; } float num = Math.Max(0.01f, step.Value); switch (index) { case 0: x += num; break; case 1: x -= num; break; case 2: y += num; break; case 3: y -= num; break; case 4: z += num; break; case 5: z -= num; break; default: x = 1f; y = 1f; z = 1f; break; } x = Round(Sizer.ClampSize(x)); y = Round(Sizer.ClampSize(y)); z = Round(Sizer.ClampSize(z)); string text = Sizer.FormatSize(x, y, z); Sizer.SetQuiet(value: true); try { val3.Value = text; } finally { Sizer.SetQuiet(value: false); } if (!repeating) { Sizer.Log.LogInfo((object)("Resize keys: " + key + " is now " + text + ".")); } Readout(key, "X " + Sizer.Format(x) + " Y " + Sizer.Format(y) + " Z " + Sizer.Format(z)); } } private static float Round(float value) { return (float)Math.Round(value * 1000f) / 1000f; } private static void Readout(string title, string body) { if (showReadout == null || showReadout.Value) { SizerOverlay.Show(title, body); } } private static bool CanUseKeys() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return false; } PlayerControllerB localPlayerController = instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { return false; } if (ReadBool(localPlayerController, "inTerminalMenu") || ReadBool(localPlayerController, "isTypingChat")) { return false; } QuickMenuManager val = Object.FindObjectOfType<QuickMenuManager>(); if ((Object)(object)val != (Object)null && val.isMenuOpen) { return false; } return true; } private static bool ReadBool(object target, string name) { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = target.GetType().GetField(name, bindingAttr); if (field != null && field.FieldType == typeof(bool)) { return (bool)field.GetValue(target); } PropertyInfo property = target.GetType().GetProperty(name, bindingAttr); if (property != null && property.PropertyType == typeof(bool) && property.CanRead) { return (bool)property.GetValue(target, null); } return false; } internal static PlaceableShipObject FindTarget() { PlaceableShipObject val = PlacementAssist.Carried(); if ((Object)(object)val != (Object)null) { return val; } return LookedAtPiece(); } private static PlaceableShipObject LookedAtPiece() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.localPlayerController == (Object)null) { return null; } Camera val = CameraOf(instance.localPlayerController); if ((Object)(object)val == (Object)null) { return null; } Transform transform = ((Component)val).transform; Ray val2 = default(Ray); ((Ray)(ref val2))..ctor(transform.position, transform.forward); RaycastHit[] array = Physics.RaycastAll(val2, Math.Max(1f, range.Value), PlaceableLayers(), (QueryTriggerInteraction)2); if (array == null || array.Length == 0) { return null; } Array.Sort(array, CompareHits); for (int i = 0; i < array.Length; i++) { Collider collider = ((RaycastHit)(ref array[i])).collider; if (!((Object)(object)collider == (Object)null)) { PlaceableShipObject val3 = PieceOf(collider); if ((Object)(object)val3 != (Object)null) { return val3; } } } return null; } private static int CompareHits(RaycastHit a, RaycastHit b) { return ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance); } private static PlaceableShipObject PieceOf(Collider collider) { PlaceableShipObject componentInParent = ((Component)collider).GetComponentInParent<PlaceableShipObject>(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } AutoParentToShip componentInParent2 = ((Component)collider).GetComponentInParent<AutoParentToShip>(); return (!((Object)(object)componentInParent2 == (Object)null)) ? ((Component)componentInParent2).GetComponentInChildren<PlaceableShipObject>(true) : null; } private static int PlaceableLayers() { int num = 0; PlaceableShipObject[] array = Object.FindObjectsOfType<PlaceableShipObject>(); if (array != null) { foreach (PlaceableShipObject val in array) { if (!((Object)(object)val == (Object)null)) { num |= 1 << ((Component)val).gameObject.layer; Collider placeObjectCollider = val.placeObjectCollider; if ((Object)(object)placeObjectCollider != (Object)null) { num |= 1 << ((Component)placeObjectCollider).gameObject.layer; } } } } return (num == 0) ? 67108864 : num; } private static Camera CameraOf(PlayerControllerB player) { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = ((object)player).GetType().GetField("gameplayCamera", bindingAttr); if (field != null) { object? value = field.GetValue(player); Camera val = (Camera)((value is Camera) ? value : null); if ((Object)(object)val != (Object)null) { return val; } } return Camera.main; } } public class SizerTicker : MonoBehaviour { private int frame; private void Update() { Keybinds.Poll(); PlacementAssist.Settle(); frame++; if (frame % 45 == 0) { Sizer.Tick(); } } } public class SizerOverlay : MonoBehaviour { internal const float Lifetime = 2.2f; internal const float FadeTime = 0.5f; private static string title = ""; private static string body = ""; private static float shownAt = -100f; private static bool broken; internal static void Show(string heading, string text) { title = heading; body = text; shownAt = Time.unscaledTime; } private void OnGUI() { if (broken) { return; } float num = Time.unscaledTime - shownAt; if (num < 0f || num > 2.2f) { return; } try { OverlayDraw.Draw(title, body, num); } catch (Exception ex) { broken = true; if (Sizer.Log != null) { Sizer.Log.LogWarning((object)("The on-screen size readout was switched off: " + ex.Message)); } } } } internal static class OverlayDraw { private static GUIStyle titleStyle; private static GUIStyle bodyStyle; [MethodImpl(MethodImplOptions.NoInlining)] internal static void Draw(string title, string body, float age) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) if (titleStyle == null) { titleStyle = new GUIStyle(GUI.skin.label); titleStyle.fontSize = 22; titleStyle.normal.textColor = Color.white; bodyStyle = new GUIStyle(GUI.skin.label); bodyStyle.fontSize = 20; bodyStyle.normal.textColor = new Color(0.85f, 0.95f, 1f, 1f); } Vector2 val = titleStyle.CalcSize(new GUIContent(title)); Vector2 val2 = bodyStyle.CalcSize(new GUIContent(body)); float num = Math.Max(val.x, val2.x) + 40f; float num2 = val.y + val2.y + 22f; float num3 = ((float)Screen.width - num) * 0.5f; float num4 = (float)Screen.height * 0.66f; float num5 = 1.7f; float num6 = ((!(age > num5)) ? 1f : Math.Max(0f, (2.2f - age) / 0.5f)); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.6f * num6); GUI.DrawTexture(new Rect(num3, num4, num, num2), (Texture)(object)Texture2D.whiteTexture); GUI.color = new Color(1f, 1f, 1f, num6); GUI.Label(new Rect(num3 + (num - val.x) * 0.5f, num4 + 9f, val.x, val.y), title, titleStyle); GUI.Label(new Rect(num3 + (num - val2.x) * 0.5f, num4 + 9f + val.y, val2.x, val2.y), body, bodyStyle); GUI.color = color; } } public class SizerInputActions : LcInputActions { [InputAction("<Keyboard>/insert", Name = "Furniture size: X bigger")] public InputAction IncreaseX { get; set; } [InputAction("<Keyboard>/delete", Name = "Furniture size: X smaller")] public InputAction DecreaseX { get; set; } [InputAction("<Keyboard>/home", Name = "Furniture size: Y bigger")] public InputAction IncreaseY { get; set; } [InputAction("<Keyboard>/end", Name = "Furniture size: Y smaller")] public InputAction DecreaseY { get; set; } [InputAction("<Keyboard>/pageUp", Name = "Furniture size: Z bigger")] public InputAction IncreaseZ { get; set; } [InputAction("<Keyboard>/pageDown", Name = "Furniture size: Z smaller")] public InputAction DecreaseZ { get; set; } [InputAction("<Keyboard>/backslash", Name = "Furniture size: reset")] public InputAction ResetSize { get; set; } } internal static class InputProxy { private static SizerInputActions actions; [MethodImpl(MethodImplOptions.NoInlining)] internal static void Create() { if (actions == null) { actions = new SizerInputActions(); } } [MethodImpl(MethodImplOptions.NoInlining)] internal static bool Pressed(int index) { InputAction val = Get(index); return val != null && val.WasPressedThisFrame(); } [MethodImpl(MethodImplOptions.NoInlining)] internal static bool Held(int index) { InputAction val = Get(index); return val != null && val.IsPressed(); } private static InputAction Get(int index) { if (actions == null) { return null; } return (InputAction)(index switch { 0 => actions.IncreaseX, 1 => actions.DecreaseX, 2 => actions.IncreaseY, 3 => actions.DecreaseY, 4 => actions.IncreaseZ, 5 => actions.DecreaseZ, _ => actions.ResetSize, }); } } internal static class LethalConfigProxy { [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddText(ConfigEntry<string> entry, string name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown TextInputFieldOptions val = new TextInputFieldOptions(); ((BaseOptions)val).RequiresRestart = false; ((BaseOptions)val).Name = name; LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(entry, val)); } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddBool(ConfigEntry<bool> entry, string name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown BoolCheckBoxOptions val = new BoolCheckBoxOptions(); ((BaseOptions)val).RequiresRestart = false; ((BaseOptions)val).Name = name; LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(entry, val)); } [MethodImpl(MethodImplOptions.NoInlining)] internal static void AddFloat(ConfigEntry<float> entry, string name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown FloatInputFieldOptions val = new FloatInputFieldOptions(); ((BaseOptions)val).RequiresRestart = false; ((BaseOptions)val).Name = name; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(entry, val)); } } [HarmonyPatch(typeof(Terminal), "Awake")] internal static class TerminalAwakePatch { [HarmonyPostfix] private static void Apply() { Sizer.SafeApply("after Terminal.Awake"); } } [HarmonyPatch(typeof(StartOfRound), "LoadUnlockables")] internal static class LoadUnlockablesPatch { [HarmonyPriority(800)] [HarmonyPrefix] private static void Before() { Sizer.SafeApply("before the furniture is spawned"); } [HarmonyPostfix] private static void After() { Sizer.SafeApply("after the furniture is spawned"); } } [HarmonyPatch(typeof(ShipBuildModeManager), "Update")] internal static class GhostPatch { [HarmonyPriority(0)] [HarmonyPostfix] private static void After(ShipBuildModeManager __instance) { PlacementAssist.AfterGhost(__instance); } }