using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Mirror; using UnityEngine; using UnityEngine.Audio; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PropMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+20350fc6c775a62be73e8593c6b767bdc709e90d")] [assembly: AssemblyProduct("PropMod")] [assembly: AssemblyTitle("PropMod")] [assembly: AssemblyVersion("1.0.0.0")] public class CommandHandler { [HarmonyPatch(typeof(ChatBehaviour), "Send_ChatMessage")] public class ChatBehaviour_Send_ChatMessage { public static bool Prefix(ChatBehaviour __instance, ref string _message) { PropMod instance = PropMod.Instance; string text = Regex.Replace(_message, "<.*?>", string.Empty); if (text == null || !text.StartsWith("/")) { return true; } string[] array = _message.Split(' '); string text2 = array[0].ToLower(); string[] array2 = ((array.Length > 1) ? array[1..] : new string[0]); string text3 = text2; string text4 = text3; if (text4 == "/list_props") { PropMod.ListPropsInChat(); return false; } return true; } } [HarmonyPatch(typeof(ChatBehaviour), "Rpc_RecieveChatMessage")] public static class ChatBehaviour_Rpc_RecieveChatMessage { public static bool Prefix(ref ChatBehaviour __instance, ref string message) { if (!NetworkServer.active) { return true; } PropMod instance = PropMod.Instance; string text = Regex.Replace(message, "<.*?>", string.Empty); if (!text.StartsWith(".")) { return true; } Player component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } string[] array = text.Split(' '); string text2 = array[0].ToLower(); string[] array2 = ((array.Length > 1) ? array[1..] : new string[0]); PropMod.propManagers.TryGetValue(component, out var value); if (value == null) { PropMod.Logger.LogError((object)("Player " + component._nickname + " doesn't have an associated prop manager!")); return true; } switch (text2) { case ".place": if (array2.Length != 0) { string prefabName = array2[0].ToLower(); value.TryPlaceAction(prefabName); return false; } return true; case ".undo": value.UndoProp(); return false; case ".clear": value.ClearProps(); return false; case ".clearall": value.ClearAllProps(); return false; default: return true; } } } [HarmonyPatch(typeof(AtlyssNetworkManager), "OnServerDisconnect")] public static class AtlyssNetworkManager_OnServerDisconnect { public static void Prefix(ref NetworkConnectionToClient _conn) { List list = HostConsole._current?._peerListEntries; int connectionId = ((NetworkConnection)_conn).connectionId; Player val = null; if (list == null) { return; } for (int i = 0; i < list.Count; i++) { if (((ListDataEntry)list[i])._dataID == connectionId) { val = list[i]._peerPlayer; break; } } if ((Object)(object)val == (Object)null) { return; } PropMod instance = PropMod.Instance; if (PropMod.propManagers.TryGetValue(val, out var value)) { PlayerPropManager value2; if (instance.deletePropsOnDisconnect.Value) { value.ClearProps(); } else if (PropMod.propManagers.TryGetValue(Player._mainPlayer, out value2)) { value2.ClaimPropOwnership(value); } else { PropMod.Logger.LogWarning((object)"Couldn't transfer props to host! Falling back to removing orphaned props."); value.ClearProps(); } PropMod.propManagers.Remove(val); } } } } public class PlayerPropManager { public Player owner; public Stack placedProps = new Stack(); public PlayerPropManager(Player player) { owner = player; } public void TryPlaceAction(string prefabName) { PropMod instance = PropMod.Instance; if (PropMod.propPrefabs.TryGetValue(prefabName, out var value)) { if (owner._isHostPlayer || placedProps.Count < instance.maxPropNum.Value) { PlaceProp(value); } } else { PropMod.Logger.LogWarning((object)("Couldn't find prop named " + prefabName)); } } public void PlaceProp(GameObject prefab) { //IL_0049: 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) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_0098: 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_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_00c0: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active) { PropMod.Logger.LogInfo((object)("Placing " + ((Object)prefab).name + " from player " + owner._nickname)); Vector3 val = ((Component)owner).transform.position + ((Component)owner).transform.forward * 5f + ((Component)owner).transform.up * -1f; Quaternion rotation = ((Component)owner).transform.rotation; GameObject val2 = Object.Instantiate(prefab, val, rotation); ((Object)val2).name = ((Object)prefab).name; SceneManager.MoveGameObjectToScene(val2, owner._playerMapInstance._loadedScene); val2.SetActive(true); NetworkServer.Spawn(val2, (NetworkConnection)null); placedProps.Push(val2); } } public void UndoProp() { if (NetworkServer.active && placedProps.TryPop(out var result)) { NetworkServer.Destroy(result); } } public void ClearProps() { while (placedProps.Count > 0) { UndoProp(); } } public void ClearAllProps() { if (!owner._isHostPlayer) { return; } foreach (PlayerPropManager value in PropMod.propManagers.Values) { value.ClearProps(); } } public void ClaimPropOwnership(PlayerPropManager otherManager) { if (otherManager != null && otherManager != this) { GameObject result; while (otherManager.placedProps.TryPop(out result)) { placedProps.Push(result); } } } } [BepInPlugin("firenoobsta.propplacer", "Prop Placer", "1.0.3")] public class PropMod : BaseUnityPlugin { [HarmonyPatch(typeof(MainMenuManager), "Start")] public class RegisterProps { [HarmonyPostfix] private static void Postfix(MainMenuManager __instance) { Logger.LogInfo((object)"Registering props ..."); foreach (GameObject value in propPrefabs.Values) { NetworkIdentity component = value.GetComponent(); if ((Object)(object)component == (Object)null) { Logger.LogError((object)("Couldn't register prop " + ((Object)value).name + " because it has no Network Identity component")); continue; } if (component.assetId != 0) { NetworkClient.RegisterPrefab(value); continue; } MD5 mD = MD5.Create(); byte[] b = mD.ComputeHash(Encoding.UTF8.GetBytes(((Object)value).name)); Guid guid = new Guid(b); uint num = NetworkIdentity.AssetGuidToUint(guid); try { NetworkClient.RegisterPrefab(value, num); } catch (Exception ex) { Logger.LogError((object)("Error trying to register " + ((Object)value).name + "!")); Logger.LogError((object)ex.Message); } } } } [HarmonyPatch(typeof(Player), "Awake")] public static class CreatePropManager { public static void Postfix(Player __instance) { if (NetworkServer.active) { propManagers.Add(__instance, new PlayerPropManager(__instance)); } } } internal static ManualLogSource Logger; public static string AssetFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); public static string PluginFolderPath = Paths.PluginPath; public static Dictionary propPrefabs = new Dictionary(); public static Dictionary propManagers = new Dictionary(); public static PropMod Instance { get; private set; } public static List PropBundles { get; private set; } public ConfigEntry deletePropsOnDisconnect { get; private set; } public ConfigEntry maxPropNum { get; private set; } private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Harmony val = new Harmony("firenoobsta.propplacer"); val.PatchAll(); Instance = this; PropBundles = new List(); deletePropsOnDisconnect = ((BaseUnityPlugin)this).Config.Bind("General", "DeleteOnDisconnect", true, "Choose whether to delete all props a specific player placed when they leave the server. If set to false, abandoned props will transfer ownership to host."); maxPropNum = ((BaseUnityPlugin)this).Config.Bind("General", "MaxPropNum", 5, "Maximum number of props clients in your server can place (per player). Hosts can place unlimited amounts. Setting to 0 means only the host can place props."); } private void Start() { Logger.LogInfo((object)"Prop Placer Loaded!"); Logger.LogInfo((object)"Version 1.0.3"); if (Directory.Exists(PluginFolderPath)) { CheckDirectory(PluginFolderPath); } Logger.LogInfo((object)"List of loaded Props: "); foreach (string key in propPrefabs.Keys) { Logger.LogInfo((object)(key ?? "")); } } public static void CheckDirectory(string dirPath) { string[] files = Directory.GetFiles(dirPath); string[] array = files; foreach (string filePath in array) { CheckFile(filePath); } string[] directories = Directory.GetDirectories(dirPath); string[] array2 = directories; foreach (string dirPath2 in array2) { CheckDirectory(dirPath2); } } public static void CheckFile(string filePath) { if (!filePath.EndsWith(".propbundle")) { return; } Logger.LogInfo((object)("Loading prop asset bundle: " + Path.GetFileName(filePath))); AssetBundle val = AssetBundle.LoadFromFile(filePath); if ((Object)(object)val == (Object)null) { Logger.LogError((object)("Failed to load asset bundle: " + Path.GetFileName(filePath))); return; } GameObject[] array = val.LoadAllAssets(); foreach (GameObject val2 in array) { FixPrefabAudioSources(val2); if (!propPrefabs.TryAdd(((Object)val2).name.ToLower(), val2)) { Logger.LogError((object)("Failed to add " + ((Object)val2).name + " to list of props")); } } PropBundles.Add(val); Logger.LogInfo((object)"Successfully loaded bundle!"); } public static void FixPrefabAudioSources(GameObject prefab) { AudioMixer val = Resources.Load("_sound/_mixer/_mixerMain"); if ((Object)(object)val == (Object)null) { Logger.LogWarning((object)"Couldn't load main mixer from resources!"); return; } AudioSource[] componentsInChildren = prefab.GetComponentsInChildren(); foreach (AudioSource val2 in componentsInChildren) { if ((Object)(object)val2.outputAudioMixerGroup != (Object)null) { val2.outputAudioMixerGroup = val.FindMatchingGroups(((Object)val2.outputAudioMixerGroup).name)[0]; } } } public static void ListPropsInChat() { ChatBehaviour chatBehaviour = Player._mainPlayer._chatBehaviour; if ((Object)(object)chatBehaviour == (Object)null) { Logger.LogError((object)"Couldn't get main player's chat behavior component"); return; } chatBehaviour.New_ChatMessage("Available props:"); foreach (string key in propPrefabs.Keys) { chatBehaviour.New_ChatMessage(key); } } }