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 StationPacks v0.3.0
plugins\StationPacks.dll
Decompiled 10 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using StationPacks.Compat; using StationPacks.Config; using StationPacks.Core; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("StationPacks")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Wearable crafting stations for building in the field.")] [assembly: AssemblyFileVersion("0.3.0.0")] [assembly: AssemblyInformationalVersion("0.3.0+42a8634a570e5675f3bf6cdaa8b2729f5009a226")] [assembly: AssemblyProduct("StationPacks")] [assembly: AssemblyTitle("StationPacks")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace StationPacks { [BepInPlugin("LosGoobers.StationPacks", "StationPacks", "0.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal sealed class Plugin : BaseUnityPlugin { public const string Guid = "LosGoobers.StationPacks"; public const string Name = "StationPacks"; public const string Version = "0.3.0"; internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; SPConfig.Bind(((BaseUnityPlugin)this).Config); _harmony = new Harmony("LosGoobers.StationPacks"); _harmony.PatchAll(); PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable; ZNetSceneReady.Subscribe(PhantomStationRegistry.Build); DebugCommands.Register(); ((Component)this).gameObject.AddComponent<TuningPanel>(); Log.LogInfo((object)"StationPacks 0.3.0 loaded."); } private void OnVanillaPrefabsAvailable() { PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable; PackRegistry.Register(); AdventureBackpacksCompat.ReportOnce(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetSceneReady { private static Action _callback; public static void Subscribe(Action callback) { _callback = callback; } [HarmonyPostfix] private static void Postfix() { _callback?.Invoke(); } } } namespace StationPacks.Patches { [HarmonyPatch(typeof(VisEquipment), "AttachArmor")] internal static class BackBonePatch { private static bool _loggedBone; [HarmonyPostfix] private static void Bind(VisEquipment __instance) { //IL_007d: 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_009c: 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_00b4: Unknown result type (might be due to invalid IL or missing references) if (!SPConfig.ShowBackMesh.Value) { return; } SkinnedMeshRenderer bodyModel = __instance.m_bodyModel; if ((Object)(object)bodyModel == (Object)null) { return; } PackBackTag[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<PackBackTag>(true); if (componentsInChildren.Length == 0) { return; } Transform val = FindSpineBone(bodyModel); if ((Object)(object)val == (Object)null) { return; } PackBackTag[] array = componentsInChildren; foreach (PackBackTag packBackTag in array) { if (!packBackTag.Bound) { packBackTag.Source = ((Component)packBackTag).transform.parent; ((Component)packBackTag).transform.SetParent(val, false); ((Component)packBackTag).transform.localScale = Vector3.one * packBackTag.TargetScale; ((Component)packBackTag).transform.localPosition = packBackTag.TargetOffset; ((Component)packBackTag).transform.localRotation = Quaternion.Euler(packBackTag.TargetEuler); packBackTag.Bound = true; } } } private static Transform FindSpineBone(SkinnedMeshRenderer bodyModel) { Transform[] bones = bodyModel.bones; if (bones == null || bones.Length == 0) { return bodyModel.rootBone; } Transform val = null; Transform[] array = bones; foreach (Transform val2 in array) { if (!((Object)(object)val2 == (Object)null)) { string text = ((Object)val2).name.ToLowerInvariant(); if ((text.Contains("spine") || text.Contains("chest") || text.Contains("back")) && ((Object)(object)val == (Object)null || CompareDepth(val2, val) > 0)) { val = val2; } } } if ((Object)(object)val != (Object)null && !_loggedBone) { _loggedBone = true; Plugin.Log.LogInfo((object)("Back mesh bound to spine bone '" + ((Object)val).name + "'.")); } return val ?? bodyModel.rootBone; } private static int CompareDepth(Transform a, Transform b) { int num = TrailingNumber(((Object)a).name); int num2 = TrailingNumber(((Object)b).name); if (num != num2) { return num - num2; } return Depth(a) - Depth(b); } private static int TrailingNumber(string name) { int num = name.Length; while (num > 0 && char.IsDigit(name[num - 1])) { num--; } if (num >= name.Length || !int.TryParse(name.Substring(num), out var result)) { return 0; } return result; } private static int Depth(Transform t) { int num = 0; while ((Object)(object)t.parent != (Object)null) { num++; t = t.parent; } return num; } } [HarmonyPatch] internal static class BuildPatches { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "PlacePiece")] private static void OnPlacePiece(Player __instance, Piece piece) { PackCharge.SpendFor(__instance, piece, SPConfig.PlaceCost.Value); } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "RemovePiece")] private static void BeforeRemovePiece(Player __instance, out Piece __state) { __state = null; Piece hoveringPiece = __instance.m_hoveringPiece; if ((Object)(object)hoveringPiece != (Object)null) { __state = hoveringPiece; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "RemovePiece")] private static void AfterRemovePiece(Player __instance, bool __result, Piece __state) { if (__result && !((Object)(object)__state == (Object)null)) { PackCharge.SpendFor(__instance, __state, SPConfig.RemoveCost.Value); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Repair")] private static void OnRepair(Player __instance, Piece repairPiece) { PackCharge.SpendFor(__instance, repairPiece, SPConfig.RepairCost.Value); } } [HarmonyPatch] internal static class CraftingStationPatches { private const float MaxGrantDistance = 64f; [HarmonyPostfix] [HarmonyPatch(typeof(CraftingStation), "HaveBuildStationInRange")] private static void GrantFromPack(string name, Vector3 point, ref CraftingStation __result) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) if ((Object)(object)__result != (Object)null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated()) || Vector3.Distance(point, ((Component)localPlayer).transform.position) > 64f) { return; } ItemData val = EquippedPackResolver.TryGetPack(localPlayer, name); if (val == null) { return; } CraftingStation val2 = PhantomStationRegistry.Get(name); if (!((Object)(object)val2 == (Object)null)) { ((Component)val2).transform.position = point; PackCharge.NoteGrant(name); __result = val2; if (SPConfig.Verbose.Value) { Plugin.Log.LogInfo((object)$"granted '{name}' from {val.m_shared.m_name} ({val.m_durability:0.#} left)"); } } } [HarmonyPrefix] [HarmonyPatch(typeof(CraftingStation), "GetLevel")] private static bool GetLevel(CraftingStation __instance, ref int __result) { if (!PhantomStationRegistry.IsPhantom(__instance)) { return true; } __result = 1; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(CraftingStation), "GetStationBuildRange")] private static bool GetStationBuildRange(CraftingStation __instance, ref float __result) { if (!PhantomStationRegistry.IsPhantom(__instance)) { return true; } __result = SPConfig.BuildRange.Value; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(CraftingStation), "CheckUsable")] private static bool CheckUsable(CraftingStation __instance, ref bool __result) { if (!PhantomStationRegistry.IsPhantom(__instance)) { return true; } __result = true; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(CraftingStation), "InUseDistance")] private static bool InUseDistance(CraftingStation __instance, ref bool __result) { if (!PhantomStationRegistry.IsPhantom(__instance)) { return true; } __result = true; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(CraftingStation), "ShowAreaMarker")] private static bool ShowAreaMarker(CraftingStation __instance) { return !PhantomStationRegistry.IsPhantom(__instance); } [HarmonyPrefix] [HarmonyPatch(typeof(CraftingStation), "HideMarker")] private static bool HideMarker(CraftingStation __instance) { return !PhantomStationRegistry.IsPhantom(__instance); } [HarmonyPrefix] [HarmonyPatch(typeof(CraftingStation), "GetExtensions")] private static bool GetExtensions(CraftingStation __instance, ref List<StationExtension> __result) { if (!PhantomStationRegistry.IsPhantom(__instance)) { return true; } __result = __instance.m_attachedExtensions; return false; } } } namespace StationPacks.Core { internal sealed class DebugCommands : ConsoleCommand { public override string Name => "stationpacks"; public override string Help => "stationpacks <give|phantoms|invariant|stations|buildstations|meshes> - StationPacks dev diagnostics"; public override List<string> CommandOptionList() { return new List<string> { "give", "phantoms", "invariant", "stations", "buildstations", "meshes" }; } public static void Register() { CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DebugCommands()); } public override void Run(string[] args) { if (!SPConfig.DevTools.Value) { Console.instance.Print("<color=orange>StationPacks dev tools are off. Enable 'Enable dev tools' in the config to use these commands.</color>"); return; } switch ((args.Length != 0) ? args[0].ToLowerInvariant() : "phantoms") { case "give": Give(); break; case "phantoms": Phantoms(); break; case "invariant": Invariant(); break; case "stations": NearbyStations(); break; case "buildstations": ListBuildStations(); break; case "meshes": ListMeshes(args); break; default: Console.instance.Print(((ConsoleCommand)this).Help); break; } } private static void Give() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } List<string> list = new List<string>(); foreach (PackDefinition item in PackDefinition.All) { if ((Object)(object)ObjectDB.instance.GetItemPrefab(item.PrefabName) == (Object)null) { Console.instance.Print("<color=red>" + item.PrefabName + " not in ObjectDB.</color>"); continue; } ((Humanoid)localPlayer).GetInventory().AddItem(item.PrefabName, 1, 1, 0, 0L, "", false); list.Add(item.DisplayName); } Console.instance.Print("<color=lime>Gave: " + string.Join(", ", list) + "</color>"); } private static void Phantoms() { Console.instance.Print("<color=yellow>StationPacks phantoms</color>"); foreach (PackDefinition item in PackDefinition.All) { string text = PhantomStationRegistry.StationNameFor(item.StationPrefab); string text2 = (((Object)(object)((text == null) ? null : PhantomStationRegistry.Get(text)) == (Object)null) ? "<color=red>MISSING</color>" : "<color=lime>ok</color>"); Console.instance.Print(string.Format(" {0,-20} {1,-22} {2,-24} {3}", item.DisplayName, item.StationPrefab, text ?? "?", text2)); } } private static void Invariant() { List<CraftingStation> allStations = CraftingStation.m_allStations; int num = allStations.Count(PhantomStationRegistry.IsPhantom); Console.instance.Print($"m_allStations.Count = {allStations.Count}"); Console.instance.Print((num == 0) ? "<color=lime>OK: no phantom is registered. Station extensions cannot re-target onto a pack.</color>" : $"<color=red>LEAK: {num} phantom(s) in m_allStations. Real station levels are at risk.</color>"); } private static void NearbyStations() { Player player = Player.m_localPlayer; if ((Object)(object)player == (Object)null) { return; } List<CraftingStation> list = CraftingStation.m_allStations.Where((CraftingStation s) => (Object)(object)s != (Object)null && Vector3.Distance(((Component)s).transform.position, ((Component)player).transform.position) < 30f).ToList(); if (list.Count == 0) { Console.instance.Print("No real crafting stations within 30m."); return; } Console.instance.Print("<color=yellow>Real stations within 30m</color>"); foreach (CraftingStation item in list) { Console.instance.Print($" {item.m_name,-24} level={item.GetLevel(true)} extensions={item.GetExtensions().Count}"); } } private static void ListBuildStations() { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { Print("ZNetScene not ready."); return; } Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (GameObject prefab in instance.m_prefabs) { Piece val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null); CraftingStation val2 = (((Object)(object)val != (Object)null) ? val.m_craftingStation : null); if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(val2.m_name)) { dictionary.TryGetValue(val2.m_name, out var value); dictionary[val2.m_name] = value + 1; } } Print("=== stations that gate building (piece count) ==="); foreach (KeyValuePair<string, int> item in dictionary.OrderByDescending((KeyValuePair<string, int> k) => k.Value)) { Print($" {item.Key,-28} {item.Value} piece(s)"); } Print((dictionary.Count == 0) ? " (none found)" : $" {dictionary.Count} station(s) gate building."); } private static void ListMeshes(string[] args) { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_014e: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) if (args.Length < 2) { Print("Usage: stationpacks meshes <prefabName> [all]"); return; } GameObject prefab = PrefabManager.Instance.GetPrefab(args[1]); if ((Object)(object)prefab == (Object)null) { Console.instance.Print("<color=orange>No prefab named '" + args[1] + "'.</color>"); return; } bool flag = args.Length > 2 && args[2].ToLowerInvariant() == "all"; HashSet<string> hashSet = new HashSet<string>(PackVisual.PickedPartNames(prefab, null)); Print("=== mesh parts of " + args[1] + " (" + (flag ? "all" : "used") + ") ==="); int num = 0; int num2 = 0; Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer)) { continue; } SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); object obj; if (val2 == null) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); obj = ((component != null) ? component.sharedMesh : null); } else { obj = val2.sharedMesh; } Mesh val3 = (Mesh)obj; if (!((Object)(object)val3 == (Object)null)) { bool flag2 = hashSet.Contains(((Object)((Component)val).gameObject).name); if (!flag2 && !flag) { num2++; continue; } Bounds bounds = val3.bounds; Vector3 size = ((Bounds)(ref bounds)).size; string text = ((val is SkinnedMeshRenderer) ? "skin" : "mesh"); string text2 = (flag2 ? "USED " : (((Object)((Component)val).gameObject).name.ToLowerInvariant().Contains("destruction") ? "destr" : "off ")); Print($" [{text2}][{text}] {((Object)((Component)val).gameObject).name,-28} {size.x:0.##} x {size.y:0.##} x {size.z:0.##}"); num++; } } Print($" {num} shown" + ((num2 > 0) ? $", {num2} hidden (add 'all')." : ".")); } private static void Print(string line) { if ((Object)(object)Console.instance != (Object)null) { Console.instance.Print(line); } Plugin.Log.LogInfo((object)("[cmd] " + line)); } } public static class EquippedPackResolver { private static readonly Dictionary<string, PackDefinition> ByItemName = new Dictionary<string, PackDefinition>(); public static void Register(PackDefinition def) { ByItemName[def.NameToken] = def; } public static PackDefinition DefinitionOf(ItemData item) { if (item == null || !ByItemName.TryGetValue(item.m_shared.m_name, out var value)) { return null; } return value; } public static ItemData TryGetPack(Player player, string stationName) { if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(stationName)) { return null; } switch (SPConfig.Slot.Value) { case SlotMode.AnyInventory: { Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return null; } foreach (ItemData allItem in inventory.GetAllItems()) { if (Matches(allItem, stationName)) { return allItem; } } return null; } case SlotMode.Shoulder: if (!Matches(((Humanoid)player).m_shoulderItem, stationName)) { return null; } return ((Humanoid)player).m_shoulderItem; default: if (!Matches(((Humanoid)player).m_utilityItem, stationName)) { return null; } return ((Humanoid)player).m_utilityItem; } } private static bool Matches(ItemData item, string stationName) { PackDefinition packDefinition = DefinitionOf(item); if (packDefinition == null) { return false; } if (item.m_durability <= 0f) { return false; } return PhantomStationRegistry.StationNameFor(packDefinition.StationPrefab) == stationName; } } internal sealed class PackBackTag : MonoBehaviour { public bool Bound; public Transform Source; public float TargetScale = 0.16f; public Vector3 TargetOffset = Vector3.zero; public Vector3 TargetEuler = Vector3.zero; private void LateUpdate() { if (Bound && (Object)(object)Source == (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } public static class PackCharge { private static string _grantedStation; private static int _grantedFrame = -1; public static void NoteGrant(string stationName) { _grantedStation = stationName; _grantedFrame = Time.frameCount; } private static bool GrantedThisFrame(string stationName) { if (_grantedFrame == Time.frameCount) { return _grantedStation == stationName; } return false; } public static bool SpendFor(Player player, Piece piece, float cost) { if ((Object)(object)player == (Object)null || (Object)(object)piece == (Object)null || cost <= 0f) { return false; } if ((Object)(object)piece.m_craftingStation == (Object)null) { return false; } string name = piece.m_craftingStation.m_name; if (!GrantedThisFrame(name)) { return false; } ItemData val = EquippedPackResolver.TryGetPack(player, name); if (val == null) { return false; } float durability = val.m_durability; val.m_durability = Mathf.Max(0f, durability - cost); if (val.m_durability <= 0f && durability > 0f) { ((Character)player).Message((MessageType)2, "$sp_pack_depleted", 0, (Sprite)null); } else if (SPConfig.ShowChargeMessages.Value) { ((Character)player).Message((MessageType)1, Localization.instance.Localize(val.m_shared.m_name) + " " + $"{Mathf.CeilToInt(val.m_durability)}/{Mathf.CeilToInt(val.GetMaxDurability())}", 0, (Sprite)null); } return true; } } public sealed class PackDefinition { public string PrefabName; public string ClonedCape; public string StationPrefab; public string CraftedAt; public int MinStationLevel; public string RepairedAt; public string DisplayName; public string Description; public float Weight; public float MovementModifier; public RequirementConfig[] Requirements; public string BackMeshDonor; public float BackScale = 0.0032f; public Vector3 BackOffset = new Vector3(0f, -0.0007f, -0.0001f); public Vector3 BackEuler = new Vector3(55f, 160f, -6.3f); public string Tag; public string[] BackIncludeParts; public string[] BackExcludeParts; public static readonly List<PackDefinition> All = new List<PackDefinition> { new PackDefinition { PrefabName = "SP_PackWorkbench", Tag = "workbench", ClonedCape = "CapeDeerHide", StationPrefab = CraftingStations.Workbench, CraftedAt = CraftingStations.Workbench, MinStationLevel = 1, RepairedAt = CraftingStations.Workbench, DisplayName = "Workbench Pack", Description = "A carpenter's bench lashed to a hide frame. Heavy, awkward, and it means you never have to plant another bench mid-build.", Weight = 8f, MovementModifier = -0.03f, Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("Wood", 20, 10, true), new RequirementConfig("LeatherScraps", 8, 4, true), new RequirementConfig("Flint", 6, 3, true) } }, new PackDefinition { PrefabName = "SP_PackStonecutter", Tag = "stonecutter", ClonedCape = "CapeTrollHide", StationPrefab = CraftingStations.Stonecutter, CraftedAt = CraftingStations.Forge, MinStationLevel = 1, RepairedAt = CraftingStations.Stonecutter, DisplayName = "Stonecutter Pack", Description = "Chisels, saws and a dust-caked apron. The stone will not cut itself, but at least now it will cut where you are standing.", Weight = 14f, MovementModifier = -0.06f, Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("Wood", 10, 5, true), new RequirementConfig("Iron", 8, 4, true), new RequirementConfig("Stone", 20, 10, true) } }, new PackDefinition { PrefabName = "SP_PackForge", Tag = "forge", ClonedCape = "CapeWolf", StationPrefab = CraftingStations.Forge, CraftedAt = CraftingStations.Forge, MinStationLevel = 2, RepairedAt = CraftingStations.Forge, DisplayName = "Forge Pack", Description = "A field anvil and a bellows you will regret carrying uphill.", Weight = 16f, MovementModifier = -0.07f, BackScale = 0.0032f, BackOffset = new Vector3(0f, -0.0001f, -0.0001f), BackEuler = new Vector3(55f, 160f, -6.3f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("Bronze", 8, 4, true), new RequirementConfig("DeerHide", 6, 3, true), new RequirementConfig("Wood", 10, 5, true) } }, new PackDefinition { PrefabName = "SP_PackArtisan", Tag = "artisan", ClonedCape = "CapeLinen", StationPrefab = CraftingStations.ArtisanTable, CraftedAt = CraftingStations.ArtisanTable, MinStationLevel = 1, RepairedAt = CraftingStations.ArtisanTable, DisplayName = "Artisan Pack", Description = "Fine tools, rolled in oilcloth. For work that does not forgive a shaking hand.", Weight = 12f, MovementModifier = -0.05f, BackScale = 0.0032f, BackOffset = new Vector3(0f, -0.0011f, -0.0001f), BackEuler = new Vector3(55f, 160f, -6.3f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("Iron", 8, 4, true), new RequirementConfig("Silver", 4, 2, true), new RequirementConfig("WolfPelt", 6, 3, true) } }, new PackDefinition { PrefabName = "SP_PackBlackForge", Tag = "blackforge", ClonedCape = "CapeFeather", StationPrefab = CraftingStations.BlackForge, CraftedAt = CraftingStations.BlackForge, MinStationLevel = 1, RepairedAt = CraftingStations.BlackForge, DisplayName = "Black Forge Pack", Description = "Black metal, still warm. It hums against your spine as you walk.", Weight = 20f, MovementModifier = -0.08f, BackScale = 0.0032f, BackOffset = new Vector3(0.0002f, 0.001f, 0.0001f), BackEuler = new Vector3(-78.7f, -11.3f, 1.2f), Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig("BlackMetal", 12, 6, true), new RequirementConfig("YggdrasilWood", 8, 4, true) } }, new PackDefinition { PrefabName = "SP_PackGaldr", Tag = "galdr", ClonedCape = "CapeLox", StationPrefab = CraftingStations.GaldrTable, CraftedAt = CraftingStations.GaldrTable, MinStationLevel = 1, RepairedAt = CraftingStations.GaldrTable, DisplayName = "Galdr Pack", Description = "Runes stitched into the lining. Carrying it feels like being watched.", Weight = 10f, MovementModifier = -0.04f, BackScale = 0.0032f, BackOffset = new Vector3(0.0008f, 0.001f, -0.0016f), BackEuler = new Vector3(-78.7f, -11.3f, 1.2f), Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("Eitr", 20, 10, true), new RequirementConfig("YggdrasilWood", 8, 4, true), new RequirementConfig("LinenThread", 10, 5, true) } } }; public string IconResource => "StationPacks.Assets.icon_" + Tag + ".png"; public string EffectiveBackMeshDonor { get { if (!string.IsNullOrEmpty(BackMeshDonor)) { return BackMeshDonor; } return StationPrefab; } } public string NameToken => "$sp_" + PrefabName.ToLowerInvariant(); public string DescToken => NameToken + "_desc"; } public static class PackRegistry { public static void Register() { //IL_00a8: 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_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015e: 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_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown foreach (PackDefinition item in PackDefinition.All) { GameObject val = PrefabManager.Instance.CreateClonedPrefab(item.PrefabName, item.ClonedCape); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)("Could not clone '" + item.ClonedCape + "' for " + item.PrefabName + "; skipping.")); continue; } SharedData shared = val.GetComponent<ItemDrop>().m_itemData.m_shared; shared.m_name = item.NameToken; shared.m_description = item.DescToken; shared.m_itemType = (ItemType)18; shared.m_weight = item.Weight; shared.m_movementModifier = item.MovementModifier; shared.m_useDurability = true; shared.m_canBeReparied = true; shared.m_maxDurability = SPConfig.MaxDurability.Value; shared.m_durabilityPerLevel = SPConfig.DurabilityPerLevel.Value; shared.m_durabilityDrain = 0f; shared.m_useDurabilityDrain = 0f; StripInheritedPerks(shared, item); shared.m_maxQuality = 3; Sprite val2 = LoadIcon(item); if ((Object)(object)val2 != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 }; } PackVisual.Apply(val, item); ItemConfig val3 = new ItemConfig { Name = item.NameToken, Description = item.DescToken, CraftingStation = item.CraftedAt, MinStationLevel = item.MinStationLevel, RepairStation = item.RepairedAt, Requirements = item.Requirements }; ItemManager.Instance.AddItem(new CustomItem(val, true, val3)); EquippedPackResolver.Register(item); Plugin.Log.LogInfo((object)("Registered " + item.DisplayName + " (clone of " + item.ClonedCape + ").")); } AddLocalization(); } private static void StripInheritedPerks(SharedData shared, PackDefinition def) { shared.m_armor = 0f; shared.m_armorPerLevel = 0f; shared.m_damageModifiers = new List<DamageModPair>(); shared.m_equipStatusEffect = null; shared.m_setStatusEffect = null; shared.m_setName = string.Empty; shared.m_setSize = 0; shared.m_eitrRegenModifier = 0f; shared.m_heatResistanceModifier = 0f; shared.m_jumpStaminaModifier = 0f; shared.m_attackStaminaModifier = 0f; shared.m_blockStaminaModifier = 0f; shared.m_dodgeStaminaModifier = 0f; shared.m_swimStaminaModifier = 0f; shared.m_sneakStaminaModifier = 0f; shared.m_runStaminaModifier = 0f; shared.m_homeItemsStaminaModifier = 0f; shared.m_weight = def.Weight; shared.m_movementModifier = def.MovementModifier; } private static Sprite LoadIcon(PackDefinition def) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) try { using Stream stream = typeof(PackRegistry).Assembly.GetManifestResourceStream(def.IconResource); if (stream == null) { Plugin.Log.LogWarning((object)(def.DisplayName + ": icon resource '" + def.IconResource + "' not found.")); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = AssetUtils.LoadImage(array); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)(def.DisplayName + ": failed to decode icon PNG.")); return null; } ((Texture)val).filterMode = (FilterMode)1; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } catch (Exception ex) { Plugin.Log.LogWarning((object)(def.DisplayName + ": icon load threw " + ex.GetType().Name + ": " + ex.Message)); return null; } } private static void AddLocalization() { Dictionary<string, string> dictionary = new Dictionary<string, string> { { "sp_pack_depleted", "Your pack is spent. Repair it at the station it replaces." } }; foreach (PackDefinition item in PackDefinition.All) { dictionary[item.NameToken.TrimStart(new char[1] { '$' })] = item.DisplayName; dictionary[item.DescToken.TrimStart(new char[1] { '$' })] = item.Description; } CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, dictionary); } } public static class PackVisual { private struct Pick { public Mesh mesh; public Material[] mats; public Transform src; } private const string BackNode = "SP_BackMesh"; public static void Apply(GameObject packPrefab, PackDefinition def) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //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_00d8: 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_0123: 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_013a: 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_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: 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_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (!SPConfig.ShowBackMesh.Value) { return; } Transform val = FindAttachSkin(packPrefab); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)(def.DisplayName + ": no attach_skin node on the cloned cape; back mesh skipped (pack still works, just looks like the cape).")); return; } GameObject prefab = PrefabManager.Instance.GetPrefab(def.EffectiveBackMeshDonor); if ((Object)(object)prefab == (Object)null) { Plugin.Log.LogWarning((object)(def.DisplayName + ": donor prefab '" + def.EffectiveBackMeshDonor + "' not found; back mesh skipped.")); return; } List<Pick> list = CollectPicks(prefab, def); if (list.Count == 0) { Plugin.Log.LogWarning((object)(def.DisplayName + ": donor '" + def.EffectiveBackMeshDonor + "' has no mesh to borrow; back mesh skipped.")); return; } GameObject val2 = new GameObject("SP_BackMesh"); PackBackTag packBackTag = val2.AddComponent<PackBackTag>(); packBackTag.TargetScale = def.BackScale; packBackTag.TargetOffset = def.BackOffset; packBackTag.TargetEuler = def.BackEuler; val2.transform.SetParent(((Component)val).transform, false); Transform transform = prefab.transform; foreach (Pick item in list) { GameObject val3 = new GameObject(((Object)((Component)item.src).gameObject).name); val3.transform.SetParent(val2.transform, false); val3.transform.localPosition = transform.InverseTransformPoint(item.src.position); val3.transform.localRotation = Quaternion.Inverse(transform.rotation) * item.src.rotation; val3.transform.localScale = item.src.lossyScale; val3.AddComponent<MeshFilter>().sharedMesh = item.mesh; MeshRenderer obj = val3.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterials = ((IEnumerable<Material>)item.mats).Select((Func<Material, Material>)((Material m) => ((Object)(object)m != (Object)null) ? new Material(m) : ((Material)null))).ToArray(); ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1; } int count = list.Count; if (SPConfig.HideCape.Value) { SkinnedMeshRenderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<SkinnedMeshRenderer>(true); for (int num = 0; num < componentsInChildren.Length; num++) { ((Renderer)componentsInChildren[num]).enabled = false; } } Plugin.Log.LogInfo((object)($"{def.DisplayName}: mounted {count} mesh part(s) from " + "'" + def.EffectiveBackMeshDonor + "'.")); } public static List<string> PickedPartNames(GameObject donor, PackDefinition def) { return (from p in CollectPicks(donor, def) select ((Object)((Component)p.src).gameObject).name).ToList(); } private static List<Pick> CollectPicks(GameObject donor, PackDefinition def) { List<Pick> list = Renderers(donor, def, requireActive: true); if (list.Count <= 0) { return Renderers(donor, def, requireActive: false); } return list; } private static List<Pick> Renderers(GameObject donor, PackDefinition def, bool requireActive) { HashSet<Renderer> hashSet = LodDrops(donor); List<Pick> list = new List<Pick>(); Renderer[] componentsInChildren = donor.GetComponentsInChildren<Renderer>(!requireActive); foreach (Renderer val in componentsInChildren) { if ((val is MeshRenderer || val is SkinnedMeshRenderer) && (!requireActive || val.enabled) && !hashSet.Contains(val) && !IsDestruction(((Component)val).transform, donor.transform) && KeepPart(((Object)((Component)val).gameObject).name, def)) { SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); object obj; if (val2 == null) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); obj = ((component != null) ? component.sharedMesh : null); } else { obj = val2.sharedMesh; } Mesh val3 = (Mesh)obj; if (!((Object)(object)val3 == (Object)null)) { list.Add(new Pick { mesh = val3, mats = val.sharedMaterials, src = ((Component)val).transform }); } } } return list; } private static bool IsDestruction(Transform t, Transform stopAt) { Transform val = t; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)stopAt.parent) { if (((Object)val).name.ToLowerInvariant().Contains("destruction")) { return true; } val = val.parent; } return false; } private static HashSet<Renderer> LodDrops(GameObject donor) { HashSet<Renderer> hashSet = new HashSet<Renderer>(); LODGroup[] componentsInChildren = donor.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren.Length; i++) { LOD[] lODs = componentsInChildren[i].GetLODs(); for (int j = 1; j < lODs.Length; j++) { Renderer[] renderers = lODs[j].renderers; foreach (Renderer val in renderers) { if ((Object)(object)val != (Object)null) { hashSet.Add(val); } } } } return hashSet; } private static bool KeepPart(string partName, PackDefinition def) { if (def == null) { return true; } string name = partName.ToLowerInvariant(); if (def.BackExcludeParts != null && def.BackExcludeParts.Any((string x) => name.Contains(x.ToLowerInvariant()))) { return false; } if (def.BackIncludeParts != null && def.BackIncludeParts.Length != 0) { return def.BackIncludeParts.Any((string x) => name.Contains(x.ToLowerInvariant())); } return true; } private static Transform FindAttachSkin(GameObject prefab) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown foreach (Transform item in prefab.transform) { Transform val = item; string name = ((Object)((Component)val).gameObject).name; if (name.StartsWith("attach_") && name.Substring("attach_".Length).StartsWith("skin")) { return val; } } return null; } } public static class PhantomStationRegistry { private static readonly Dictionary<string, CraftingStation> ByStationName = new Dictionary<string, CraftingStation>(); private static readonly Dictionary<string, string> PrefabToStationName = new Dictionary<string, string>(); private static readonly HashSet<CraftingStation> Phantoms = new HashSet<CraftingStation>(); private static GameObject _holder; public static bool IsPhantom(CraftingStation station) { if ((Object)(object)station != (Object)null) { return Phantoms.Contains(station); } return false; } public static string StationNameFor(string stationPrefab) { if (!PrefabToStationName.TryGetValue(stationPrefab, out var value)) { return null; } return value; } public static CraftingStation Get(string stationName) { if (!ByStationName.TryGetValue(stationName, out var value) || !((Object)(object)value != (Object)null)) { return null; } return value; } public static void Build() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_00c8: 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) ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { Plugin.Log.LogWarning((object)"ZNetScene not ready; phantom stations not built."); return; } int count = CraftingStation.m_allStations.Count; Clear(); _holder = new GameObject("StationPacks_Phantoms"); _holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_holder); foreach (GameObject prefab in instance.m_prefabs) { if ((Object)(object)prefab == (Object)null) { continue; } CraftingStation component = prefab.GetComponent<CraftingStation>(); if (!((Object)(object)component == (Object)null) && !string.IsNullOrEmpty(component.m_name) && !ByStationName.ContainsKey(component.m_name)) { GameObject val = new GameObject("SP_Phantom_" + ((Object)prefab).name); val.transform.SetParent(_holder.transform, false); CraftingStation val2 = val.AddComponent<CraftingStation>(); CopyFrom(component, val2); ByStationName[val2.m_name] = val2; PrefabToStationName[((Object)prefab).name] = val2.m_name; Phantoms.Add(val2); if (SPConfig.Verbose.Value) { Plugin.Log.LogInfo((object)(" phantom: " + ((Object)prefab).name + " -> m_name '" + val2.m_name + "'")); } } } int count2 = CraftingStation.m_allStations.Count; if (count2 != count) { Plugin.Log.LogError((object)($"INVARIANT VIOLATED: m_allStations changed {count} -> {count2} while building phantoms. " + "A phantom registered itself; station extensions may re-target onto it. Disabling grants.")); Clear(); } else { Plugin.Log.LogInfo((object)$"Built {ByStationName.Count} phantom stations; m_allStations unchanged at {count2}."); ValidatePackDefinitions(); } } private static void ValidatePackDefinitions() { foreach (PackDefinition item in PackDefinition.All) { if (!PrefabToStationName.ContainsKey(item.StationPrefab)) { Plugin.Log.LogError((object)(item.DisplayName + " points at station prefab '" + item.StationPrefab + "', which no loaded prefab provides. This pack will never grant anything. Did the game rename it?")); } } } private static void CopyFrom(CraftingStation src, CraftingStation dst) { //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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown dst.m_name = src.m_name; dst.m_icon = src.m_icon; dst.m_craftingSkill = src.m_craftingSkill; dst.m_useDistance = src.m_useDistance; dst.m_useAnimation = src.m_useAnimation; dst.m_rangeBuild = SPConfig.BuildRange.Value; dst.m_buildRange = SPConfig.BuildRange.Value; dst.m_extraRangePerLevel = 0f; dst.m_craftRequireRoof = false; dst.m_craftRequireFire = false; dst.m_discoverRange = 0f; dst.m_attachedExtensions = new List<StationExtension>(); dst.m_craftItemEffects = new EffectList(); dst.m_craftItemDoneEffects = new EffectList(); dst.m_repairItemDoneEffects = new EffectList(); dst.m_areaMarker = null; dst.m_areaMarkerCircle = null; dst.m_inUseObject = null; dst.m_haveFireObject = null; dst.m_roofCheckPoint = null; dst.m_connectionPoint = null; dst.m_effectAreaCollider = null; dst.m_nview = null; } private static void Clear() { ByStationName.Clear(); PrefabToStationName.Clear(); Phantoms.Clear(); if ((Object)(object)_holder != (Object)null) { Object.Destroy((Object)(object)_holder); } _holder = null; } } internal sealed class TuningPanel : MonoBehaviour { private bool _open; private bool _seeded; private Rect _win = new Rect(20f, 60f, 320f, 430f); private float _scale = 0.002f; private Vector3 _pos; private Vector3 _rot; private void Update() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!SPConfig.DevTools.Value) { _open = false; return; } KeyboardShortcut value = SPConfig.TuneKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { _open = !_open; if (_open) { Seed(); } } } private List<Transform> Instances() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } return (from t in ((Component)localPlayer).GetComponentsInChildren<PackBackTag>(true) select ((Component)t).transform).ToList(); } private void Seed() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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) List<Transform> list = Instances(); if (list == null || list.Count == 0) { _seeded = false; return; } Transform val = list[0]; _scale = val.localScale.x; _pos = val.localPosition; _rot = val.localEulerAngles; if (_rot.x > 180f) { _rot.x -= 360f; } if (_rot.y > 180f) { _rot.y -= 360f; } if (_rot.z > 180f) { _rot.z -= 360f; } _seeded = true; } private void OnGUI() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (_open && SPConfig.DevTools.Value) { _win = GUILayout.Window(23164, _win, new WindowFunction(DrawWindow), "StationPacks - back mesh", Array.Empty<GUILayoutOption>()); } } private void DrawWindow(int id) { //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: 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) List<Transform> list = Instances(); if (list == null || list.Count == 0) { GUILayout.Label("Equip a pack to tune it.", Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Close", Array.Empty<GUILayoutOption>())) { _open = false; } GUI.DragWindow(); return; } if (!_seeded) { Seed(); } _scale = Slider("Scale", _scale, 0.0005f, 0.02f, "0.####"); GUILayout.Space(4f); _pos.x = Slider("Pos X (left/right)", _pos.x, -0.03f, 0.03f, "0.####"); _pos.y = Slider("Pos Y (up back)", _pos.y, -0.03f, 0.03f, "0.####"); _pos.z = Slider("Pos Z (from spine)", _pos.z, -0.03f, 0.03f, "0.####"); GUILayout.Space(4f); _rot.x = Slider("Pitch", _rot.x, -180f, 180f, "0.#"); _rot.y = Slider("Yaw", _rot.y, -180f, 180f, "0.#"); _rot.z = Slider("Roll", _rot.z, -180f, 180f, "0.#"); foreach (Transform item in list) { item.localScale = Vector3.one * _scale; item.localPosition = _pos; item.localRotation = Quaternion.Euler(_rot); } GUILayout.Space(8f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Resync", Array.Empty<GUILayoutOption>())) { Seed(); } if (GUILayout.Button("Copy bake line", Array.Empty<GUILayoutOption>())) { CopyBakeLine(); } if (GUILayout.Button("Close", Array.Empty<GUILayoutOption>())) { _open = false; } GUILayout.EndHorizontal(); GUILayout.Label(BakeLine(), Array.Empty<GUILayoutOption>()); GUI.DragWindow(); } private static float Slider(string label, float value, float min, float max, string fmt) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) }); GUILayout.Label(value.ToString(fmt), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); GUILayout.EndHorizontal(); return GUILayout.HorizontalSlider(value, min, max, Array.Empty<GUILayoutOption>()); } private string BakeLine() { return $"BackScale={_scale:0.####} BackOffset=({_pos.x:0.####},{_pos.y:0.####},{_pos.z:0.####}) " + $"BackEuler=({_rot.x:0.#},{_rot.y:0.#},{_rot.z:0.#})"; } private void CopyBakeLine() { string text = (GUIUtility.systemCopyBuffer = BakeLine()); if ((Object)(object)Console.instance != (Object)null) { Console.instance.Print("<color=lime>copied: " + text + "</color>"); } Plugin.Log.LogInfo((object)("[tune] " + text)); } } } namespace StationPacks.Config { public enum SlotMode { Utility, Shoulder, AnyInventory } public static class SPConfig { public static ConfigEntry<SlotMode> Slot; public static ConfigEntry<bool> Verbose; public static ConfigEntry<bool> ShowChargeMessages; public static ConfigEntry<bool> ShowBackMesh; public static ConfigEntry<bool> HideCape; public static ConfigEntry<bool> DevTools; public static ConfigEntry<KeyboardShortcut> TuneKey; public static ConfigEntry<float> MaxDurability; public static ConfigEntry<float> DurabilityPerLevel; public static ConfigEntry<float> PlaceCost; public static ConfigEntry<float> RemoveCost; public static ConfigEntry<float> RepairCost; public static ConfigEntry<float> BuildRange; public static void Bind(ConfigFile cfg) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) Slot = cfg.Bind<SlotMode>("1 - General", "Slot mode", SlotMode.Utility, "Where a station pack must sit to work.\nUtility: the vanilla utility slot (shared with the Megingjord belt and Wishbone). One pack at a time, and your cape slot stays free for survival capes.\nShoulder: the vanilla cape slot - you give up your cape instead of your belt.\nAnyInventory: just carry it anywhere. No opportunity cost; effectively easy mode."); Verbose = cfg.Bind<bool>("1 - General", "Verbose logging", false, "Log phantom-station construction and every grant. Noisy; for debugging only."); ShowChargeMessages = cfg.Bind<bool>("1 - General", "Show charge messages", true, "Show a top-left message with the pack's remaining charge as it drains."); ShowBackMesh = cfg.Bind<bool>("3 - Appearance", "Show station on back", true, "Mount a shrunk copy of the emulated station on your back, so each pack looks distinct.\nTurn off to keep the plain cape look."); HideCape = cfg.Bind<bool>("3 - Appearance", "Hide the cape", true, "Hide the cape's own cloth so only the backpack shows. Off keeps the cape draping behind\nthe pack. Only matters when 'Show station on back' is on."); MaxDurability = cfg.Bind<float>("2 - Balance", "Max charge", 100f, new ConfigDescription("Charge of a quality-1 pack. One point is spent per piece placed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10000f), Array.Empty<object>())); DurabilityPerLevel = cfg.Bind<float>("2 - Balance", "Charge per upgrade level", 50f, new ConfigDescription("Extra charge for each quality level above 1.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f), Array.Empty<object>())); PlaceCost = cfg.Bind<float>("2 - Balance", "Charge per placement", 1f, new ConfigDescription("Charge spent when the pack is what allowed a piece to be placed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); RemoveCost = cfg.Bind<float>("2 - Balance", "Charge per deconstruct", 0.5f, new ConfigDescription("Charge spent when the pack is what allowed a piece to be removed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); RepairCost = cfg.Bind<float>("2 - Balance", "Charge per repair", 0.5f, new ConfigDescription("Charge spent when the pack is what allowed a piece to be repaired.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); BuildRange = cfg.Bind<float>("2 - Balance", "Build range", 20f, new ConfigDescription("Radius the pack projects around you. Vanilla workbench is 20.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 64f), Array.Empty<object>())); DevTools = cfg.Bind<bool>("9 - Dev", "Enable dev tools", false, "Enables the in-game dev tooling: the 'stationpacks' console commands (give, meshes, back, phantoms, invariant, ...) and the back-mesh tuning panel. Off for normal play."); TuneKey = cfg.Bind<KeyboardShortcut>("9 - Dev", "Tuning panel key", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Opens the live slider panel for positioning the pack on your back. Only works when 'Enable dev tools' is on."); } } } namespace StationPacks.Compat { public static class AdventureBackpacksCompat { private const string Guid = "vapok.mods.adventurebackpacks"; public static bool Installed => Chainloader.PluginInfos.ContainsKey("vapok.mods.adventurebackpacks"); public static void ReportOnce() { if (Installed) { if (SPConfig.Slot.Value == SlotMode.Shoulder) { Plugin.Log.LogInfo((object)"AdventureBackpacks detected, and StationPacks 'Slot mode' is set to Shoulder - both want the cape slot, so you can wear one or the other. Switch Slot mode to Utility (the default) to wear a backpack and a station pack together."); } else { Plugin.Log.LogInfo((object)"AdventureBackpacks detected. Station packs use the utility slot, so the two coexist - backpack on your back, station pack on your belt."); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }