using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using ReservedItemSlotCore;
using ReservedItemSlotCore.Config;
using ReservedItemSlotCore.Data;
using ReservedWalkieSlot.Config;
using ReservedWalkieSlot.Patches;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ReservedWalkieSlot")]
[assembly: AssemblyDescription("Mod made by flipf17")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReservedWalkieSlot")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c15c320f-d8fc-4f1c-be3c-f2d2ffc41edd")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ReservedWalkieSlot
{
[BepInPlugin("FlipMods.ReservedWalkieSlot", "ReservedWalkieSlot", "2.0.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
public static Plugin instance;
private static ManualLogSource logger;
private Harmony _harmony;
public static ReservedItemSlotData walkieSlotData;
public static ReservedItemData walkieData;
public static List<ReservedItemData> additionalItemData = new List<ReservedItemData>();
private void Awake()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
instance = this;
CreateCustomLogger();
ConfigSettings.BindConfigSettings();
CreateReservedItemSlots();
CreateAdditionalReservedItemSlots();
_harmony = new Harmony("ReservedWalkieSlot");
PatchAll();
Log("ReservedWalkieSlot loaded");
}
private void CreateReservedItemSlots()
{
//IL_003e: 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_0061: Expected O, but got Unknown
walkieSlotData = ReservedItemSlotData.CreateReservedItemSlotData("walkie_talkie", ConfigSettings.overrideItemSlotPriority.Value, ConfigSettings.overridePurchasePrice.Value);
walkieData = walkieSlotData.AddItemToReservedItemSlot(new ReservedItemData("무전기", (PlayerBone)4, new Vector3(0.15f, -0.05f, 0.25f), new Vector3(0f, -90f, 100f)));
}
private void CreateAdditionalReservedItemSlots()
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: 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_004d: 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_0056: Expected O, but got Unknown
string[] array = ConfigSettings.ParseAdditionalItems();
string[] array2 = array;
foreach (string text in array2)
{
if (!walkieSlotData.ContainsItem(text))
{
LogWarning("Adding additional item to reserved item slot. Item: " + text);
ReservedItemData val = new ReservedItemData(text, (PlayerBone)0, default(Vector3), default(Vector3));
additionalItemData.Add(val);
walkieSlotData.AddItemToReservedItemSlot(val);
}
}
}
private void PatchAll()
{
IEnumerable<Type> enumerable;
try
{
enumerable = Assembly.GetExecutingAssembly().GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
enumerable = ex.Types.Where((Type t) => t != null);
}
foreach (Type item in enumerable)
{
_harmony.PatchAll(item);
}
}
private void CreateCustomLogger()
{
try
{
logger = Logger.CreateLogSource($"{((BaseUnityPlugin)this).Info.Metadata.Name}-{((BaseUnityPlugin)this).Info.Metadata.Version}");
}
catch
{
logger = ((BaseUnityPlugin)this).Logger;
}
}
public static void Log(string message)
{
logger.LogInfo((object)message);
}
public static void LogError(string message)
{
logger.LogError((object)message);
}
public static void LogWarning(string message)
{
logger.LogWarning((object)message);
}
public static bool IsModLoaded(string guid)
{
return Chainloader.PluginInfos.ContainsKey(guid);
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "FlipMods.ReservedWalkieSlot";
public const string PLUGIN_NAME = "ReservedWalkieSlot";
public const string PLUGIN_VERSION = "2.0.2";
}
}
namespace ReservedWalkieSlot.Patches
{
[HarmonyPatch(typeof(ShipBuildModeManager), "PlayerMeetsConditionsToBuild")]
public class PlayerMeetsConditionsToBuildPatcher
{
private static bool activatingWalkie;
private static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;
public static void Prefix(ShipBuildModeManager __instance)
{
if (!((Object)(object)localPlayerController == (Object)null))
{
activatingWalkie = localPlayerController.activatingItem;
WalkieTalkie mainWalkie = WalkiePatcher.GetMainWalkie(localPlayerController);
if (!((Object)(object)mainWalkie == (Object)null) && !((Object)(object)((GrabbableObject)mainWalkie).playerHeldBy == (Object)null) && !((Object)(object)((GrabbableObject)mainWalkie).playerHeldBy != (Object)(object)localPlayerController) && localPlayerController.activatingItem && mainWalkie.speakingIntoWalkieTalkie)
{
localPlayerController.activatingItem = false;
}
}
}
public static void Postfix(ShipBuildModeManager __instance)
{
if (!((Object)(object)localPlayerController == (Object)null))
{
localPlayerController.activatingItem = activatingWalkie;
}
}
}
[HarmonyPatch]
public static class WalkiePatcher
{
public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;
public static WalkieTalkie GetMainWalkie(PlayerControllerB playerController)
{
return GetCurrentlySelectedWalkie(playerController) ?? GetReservedWalkie(playerController);
}
public static WalkieTalkie GetReservedWalkie(PlayerControllerB playerController)
{
ReservedItemSlotData val = default(ReservedItemSlotData);
ReservedPlayerData value;
return (WalkieTalkie)((SessionManager.TryGetUnlockedItemSlotData(Plugin.walkieSlotData.slotName, ref val) && ReservedPlayerData.allPlayerData.TryGetValue(playerController, out value)) ? /*isinst with value type is only supported in some contexts*/: null);
}
public static WalkieTalkie GetCurrentlySelectedWalkie(PlayerControllerB playerController)
{
return (WalkieTalkie)((playerController.currentItemSlot >= 0 && playerController.currentItemSlot < playerController.ItemSlots.Length) ? /*isinst with value type is only supported in some contexts*/: null);
}
}
}
namespace ReservedWalkieSlot.Input
{
internal class IngameKeybinds : LcInputActions
{
internal static IngameKeybinds Instance = new IngameKeybinds();
[InputAction("<Keyboard>/x", Name = "[ReservedItemSlots]\nActivate walkie")]
public InputAction ActivateWalkieHotkey { get; set; }
internal static InputActionAsset GetAsset()
{
return ((LcInputActions)Instance).Asset;
}
}
internal class InputUtilsCompat
{
internal static InputActionAsset Asset => IngameKeybinds.GetAsset();
internal static bool Enabled => Plugin.IsModLoaded("com.rune580.LethalCompanyInputUtils");
public static InputAction ActivateWalkieHotkey => IngameKeybinds.Instance.ActivateWalkieHotkey;
}
[HarmonyPatch]
internal static class Keybinds
{
public static InputActionAsset Asset;
public static InputActionMap ActionMap;
private static InputAction ActivateWalkieAction;
public static PlayerControllerB localPlayerController => StartOfRound.Instance?.localPlayerController;
[HarmonyPatch(typeof(PreInitSceneScript), "Awake")]
[HarmonyPrefix]
public static void AddToKeybindMenu()
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Expected O, but got Unknown
//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)
Plugin.Log("Initializing hotkeys.");
if (InputUtilsCompat.Enabled)
{
Asset = InputUtilsCompat.Asset;
ActionMap = Asset.actionMaps[0];
ActivateWalkieAction = InputUtilsCompat.ActivateWalkieHotkey;
}
else
{
Asset = ScriptableObject.CreateInstance<InputActionAsset>();
ActionMap = new InputActionMap("ReservedItemSlots");
InputActionSetupExtensions.AddActionMap(Asset, ActionMap);
ActivateWalkieAction = InputActionSetupExtensions.AddAction(ActionMap, "ReservedItemSlots.ActivateWalkie", (InputActionType)0, "<keyboard>/x", (string)null, (string)null, (string)null, (string)null);
}
}
[HarmonyPatch(typeof(StartOfRound), "OnEnable")]
[HarmonyPostfix]
public static void OnEnable()
{
Asset.Enable();
ActivateWalkieAction.performed += OnPressWalkieButtonPerformed;
ActivateWalkieAction.canceled += OnReleaseWalkieButtonPerformed;
}
[HarmonyPatch(typeof(StartOfRound), "OnDisable")]
[HarmonyPostfix]
public static void OnDisable()
{
Asset.Disable();
ActivateWalkieAction.performed -= OnPressWalkieButtonPerformed;
ActivateWalkieAction.canceled -= OnReleaseWalkieButtonPerformed;
}
private static void OnPressWalkieButtonPerformed(CallbackContext context)
{
if ((Object)(object)localPlayerController == (Object)null || !localPlayerController.isPlayerControlled || (((NetworkBehaviour)localPlayerController).IsServer && !localPlayerController.isHostPlayerObject))
{
return;
}
WalkieTalkie mainWalkie = WalkiePatcher.GetMainWalkie(localPlayerController);
if (((CallbackContext)(ref context)).performed && !((Object)(object)mainWalkie == (Object)null) && ((GrabbableObject)mainWalkie).isBeingUsed && !ShipBuildModeManager.Instance.InBuildMode)
{
float num = (float)Traverse.Create((object)localPlayerController).Field("timeSinceSwitchingSlots").GetValue();
if (!(num < 0.075f))
{
Plugin.Log("Speaking into walkie");
((GrabbableObject)mainWalkie).UseItemOnClient(true);
Traverse.Create((object)localPlayerController).Field("timeSinceSwitchingSlots").SetValue((object)0);
}
}
}
private static void OnReleaseWalkieButtonPerformed(CallbackContext context)
{
if (!((Object)(object)localPlayerController == (Object)null) && localPlayerController.isPlayerControlled && (!((NetworkBehaviour)localPlayerController).IsServer || localPlayerController.isHostPlayerObject))
{
WalkieTalkie mainWalkie = WalkiePatcher.GetMainWalkie(localPlayerController);
if (((CallbackContext)(ref context)).canceled && !((Object)(object)mainWalkie == (Object)null))
{
Plugin.Log("Not talking into walkie");
((GrabbableObject)mainWalkie).UseItemOnClient(false);
}
}
}
}
}
namespace ReservedWalkieSlot.Config
{
public static class ConfigSettings
{
public static ConfigEntry<int> overrideItemSlotPriority;
public static ConfigEntry<int> overridePurchasePrice;
public static ConfigEntry<string> additionalItemsInSlot;
public static Dictionary<string, ConfigEntryBase> currentConfigEntries = new Dictionary<string, ConfigEntryBase>();
public static void BindConfigSettings()
{
Plugin.Log("BindingConfigs");
overrideItemSlotPriority = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "WalkieSlotPriorityOverride", 150, "[Host only] Manually set the priority for this item slot. Higher priority slots will come first in the reserved item slots, which will appear below the other slots. Negative priority items will appear on the left side of the screen, this is disabled in the core mod's config."));
overridePurchasePrice = AddConfigEntry<int>(((BaseUnityPlugin)Plugin.instance).Config.Bind<int>("Server-side", "WalkieSlotPriceOverride", 150, "[Host only] Manually set the price for this item in the store. Setting 0 will force this item to be unlocked immediately after the game starts."));
additionalItemsInSlot = AddConfigEntry<string>(((BaseUnityPlugin)Plugin.instance).Config.Bind<string>("Server-side", "AdditionalItemsInSlot", "", "[Host only] Syntax: \"Item1,Item name2\" (without quotes). When adding items, use the item's name as it appears in game. Include spaces if there are spaces in the item name. Adding items that do not exist, or that are from a mod which is not enabled will not cause any problems.\nNOTE: IF YOU ARE USING A TRANSLATION MOD, YOU MAY NEED TO ADD THE TRANSLATED NAME OF ANY ITEM YOU WANT IN THIS SLOT."));
additionalItemsInSlot.Value = additionalItemsInSlot.Value.Replace(", ", ",");
TryRemoveOldConfigSettings();
}
public static ConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
{
currentConfigEntries.Add(((ConfigEntryBase)configEntry).Definition.Key, (ConfigEntryBase)(object)configEntry);
return configEntry;
}
public static string[] ParseAdditionalItems()
{
return ConfigSettings.ParseItemNames(additionalItemsInSlot.Value);
}
public static void TryRemoveOldConfigSettings()
{
HashSet<string> hashSet = new HashSet<string>();
HashSet<string> hashSet2 = new HashSet<string>();
foreach (ConfigEntryBase value in currentConfigEntries.Values)
{
hashSet.Add(value.Definition.Section);
hashSet2.Add(value.Definition.Key);
}
try
{
ConfigFile config = ((BaseUnityPlugin)Plugin.instance).Config;
string configFilePath = config.ConfigFilePath;
if (!File.Exists(configFilePath))
{
return;
}
string text = File.ReadAllText(configFilePath);
string[] array = File.ReadAllLines(configFilePath);
string text2 = "";
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i].Replace("\n", "");
if (array[i].Length <= 0)
{
continue;
}
if (array[i].StartsWith("["))
{
if (text2 != "" && !hashSet.Contains(text2))
{
text2 = "[" + text2 + "]";
int num = text.IndexOf(text2);
int num2 = text.IndexOf(array[i]);
text = text.Remove(num, num2 - num);
}
text2 = array[i].Replace("[", "").Replace("]", "").Trim();
}
else
{
if (!(text2 != ""))
{
continue;
}
if (i <= array.Length - 4 && array[i].StartsWith("##"))
{
int j;
for (j = 1; i + j < array.Length && array[i + j].Length > 3; j++)
{
}
if (hashSet.Contains(text2))
{
int num3 = array[i + j - 1].IndexOf("=");
string item = array[i + j - 1].Substring(0, num3 - 1);
if (!hashSet2.Contains(item))
{
int num4 = text.IndexOf(array[i]);
int num5 = text.IndexOf(array[i + j - 1]) + array[i + j - 1].Length;
text = text.Remove(num4, num5 - num4);
}
}
i += j - 1;
}
else if (array[i].Length > 3)
{
text = text.Replace(array[i], "");
}
}
}
if (!hashSet.Contains(text2))
{
text2 = "[" + text2 + "]";
int num6 = text.IndexOf(text2);
text = text.Remove(num6, text.Length - num6);
}
while (text.Contains("\n\n\n"))
{
text = text.Replace("\n\n\n", "\n\n");
}
File.WriteAllText(configFilePath, text);
config.Reload();
}
catch
{
}
}
}
}