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 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+bf80c8ca3708c9d5e6b58206d3a09d728788d2dd")]
[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;
if (_message == null || !_message.StartsWith("/"))
{
return true;
}
string[] array = _message.Split(' ');
string text = array[0].ToLower();
string[] array2 = ((array.Length > 1) ? array[1..] : new string[0]);
string text2 = text;
string text3 = text2;
if (text3 == "/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;
if (!message.StartsWith("."))
{
return true;
}
Player component = ((Component)__instance).GetComponent<Player>();
if ((Object)(object)component == (Object)null)
{
return true;
}
string[] array = message.Split(' ');
string text = 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 (text)
{
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<HC_PeerListEntry> 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<GameObject> placedProps = new Stack<GameObject>();
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_00b3: 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<GameObject>(prefab, val, rotation);
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.2")]
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<NetworkIdentity>();
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<string, GameObject> propPrefabs = new Dictionary<string, GameObject>();
public static Dictionary<Player, PlayerPropManager> propManagers = new Dictionary<Player, PlayerPropManager>();
public static PropMod Instance { get; private set; }
public static List<AssetBundle> PropBundles { get; private set; }
public ConfigEntry<bool> deletePropsOnDisconnect { get; private set; }
public ConfigEntry<int> 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<AssetBundle>();
deletePropsOnDisconnect = ((BaseUnityPlugin)this).Config.Bind<bool>("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<int>("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.2");
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<GameObject>();
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<AudioMixer>("_sound/_mixer/_mixerMain");
if ((Object)(object)val == (Object)null)
{
Logger.LogWarning((object)"Couldn't load main mixer from resources!");
return;
}
AudioSource[] componentsInChildren = prefab.GetComponentsInChildren<AudioSource>();
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);
}
}
}