Decompiled source of CruiserSkinRevived v1.1.0

BepInEx/plugins/CruiserSkinRevived.dll

Decompiled 2 months ago
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.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalNetworkAPI;
using LethalNetworkAPI.Utils;
using TerminalApi;
using TerminalApi.Classes;
using TerminalApi.Events;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CruiserSkinRevived")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f2f73231a9be60d9edab16f2377085ae6fbe4a52")]
[assembly: AssemblyProduct("CruiserSkinRevived")]
[assembly: AssemblyTitle("CruiserSkinRevived")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CruiserSkinRevived.Main;

[BepInPlugin("Fitrusielle.CruiserSkinRevived", "CruiserSkinRevived", "1.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class CSR : BaseUnityPlugin
{
	public enum SkinSelectionType
	{
		Terminal,
		Random
	}

	public static Dictionary<string, Skin> skins = new Dictionary<string, Skin>();

	public static Material cruiserMaterial = null;

	public static Material cruiserDestroyedMaterial = null;

	public static ManualLogSource Log;

	private static LNetworkMessage<List<object>> configMessage = LNetworkMessage<List<object>>.Connect("CSR.Config", (Action<List<object>, ulong>)OnServerConfigMessageRecieved, (Action<List<object>>)OnClientConfigMessageRecieved, (Action<List<object>, ulong>)null);

	public static ConfigEntry<SkinSelectionType> skinSelectionType;

	public static ConfigEntry<bool> randomWithoutRepeat;

	public static ConfigEntry<bool> useOriginalSkin;

	public static ConfigEntry<bool> onlyHostCanChangeSkin;

	private void Awake()
	{
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		cruiserMaterial = null;
		cruiserDestroyedMaterial = null;
		skinSelectionType = ((BaseUnityPlugin)this).Config.Bind<SkinSelectionType>("General", "SkinSelectionType", SkinSelectionType.Random, "If 'Random' - mod will select skin randomly.\nIf 'Terminal' - the player will have to set skin manually with command in terminal.");
		randomWithoutRepeat = ((BaseUnityPlugin)this).Config.Bind<bool>("Random", "NoRepeats", true, "If true, skins are chosen randomly without repeating twice.");
		useOriginalSkin = ((BaseUnityPlugin)this).Config.Bind<bool>("Random", "UseOriginalSkin", false, "If true, mod will use original skin in random like all other custom skins.");
		onlyHostCanChangeSkin = ((BaseUnityPlugin)this).Config.Bind<bool>("Terminal", "OnlyHostCanChangeSkin", false, "If true, only host will can change skin with terminal.");
		LoadSkins(Paths.PluginPath);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Skins count: " + skins.Count));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded skins: " + string.Join(", ", skins.Keys)));
		if (skins.Count == 0)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Not applying patch because skins count is 0.");
		}
		else
		{
			new Harmony("Fitrusielle.CruiserSkinRevived").PatchAll(typeof(Patch));
		}
		Events.TerminalStarted += new TerminalEventHandler(initTerminalCommands);
		LNetworkUtils.OnNetworkStart += OnNetworkStart;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"CSR successfully Loaded.");
	}

	private void OnNetworkStart(bool isHost)
	{
		if (!isHost)
		{
			Log.LogInfo((object)"(Client) Requesting config from host.");
			configMessage.SendServer(new List<object>());
		}
	}

	private static void OnServerConfigMessageRecieved(List<object> list, ulong client)
	{
		List<object> list2 = new List<object> { skinSelectionType.Value, randomWithoutRepeat.Value, useOriginalSkin.Value, onlyHostCanChangeSkin.Value };
		Log.LogInfo((object)("(Server) Client requesting config. Sending: " + string.Join(", ", list2)));
		configMessage.SendClient(list2, client);
	}

	private static void OnClientConfigMessageRecieved(List<object> list)
	{
		skinSelectionType.Value = (SkinSelectionType)list[0];
		randomWithoutRepeat.Value = (bool)list[1];
		useOriginalSkin.Value = (bool)list[2];
		onlyHostCanChangeSkin.Value = (bool)list[3];
		Log.LogInfo((object)("(Client) Config is succesfully synchronized. Now client config is: " + string.Join(", ", skinSelectionType.Value, randomWithoutRepeat.Value, useOriginalSkin.Value, onlyHostCanChangeSkin.Value)));
	}

	private void LoadSkins(string path)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Expected O, but got Unknown
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Expected O, but got Unknown
		string[] directories = Directory.GetDirectories(path);
		foreach (string path2 in directories)
		{
			LoadSkins(path2);
		}
		directories = Directory.GetFiles(path);
		foreach (string text in directories)
		{
			Skin skin = new Skin();
			if (text.EndsWith("cruiser.png") || text.EndsWith("cruiser_example.png"))
			{
				Texture2D val = new Texture2D(2, 2);
				ImageConversion.LoadImage(val, File.ReadAllBytes(text));
				skin.defaultSkin = val;
				Texture2D val2 = new Texture2D(2, 2);
				ImageConversion.LoadImage(val2, File.ReadAllBytes(text.EndsWith("cruiser_example.png") ? text.Replace("example", "destroyed_example") : text.Replace(".png", "_destroyed.png")));
				skin.destroyedSkin = val2;
				skin.name = (text.EndsWith("cruiser_example.png") ? "default" : text.Replace(path + "\\", "").Replace("_cruiser.png", "").ToLower());
			}
			if ((Object)(object)skin.defaultSkin != (Object)null && (Object)(object)skin.destroyedSkin != (Object)null)
			{
				skins.Add(skin.name, skin);
			}
		}
	}

	private void initTerminalCommands(object sender, EventArgs e)
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Expected O, but got Unknown
		TerminalKeyword val = TerminalApi.CreateTerminalKeyword("skin", true, (TerminalNode)null);
		foreach (KeyValuePair<string, Skin> skin in skins)
		{
			TerminalNode val2 = TerminalApi.CreateTerminalNode("", true, "");
			TerminalKeyword val3 = TerminalApi.CreateTerminalKeyword(skin.Key, false, (TerminalNode)null);
			val = TerminalExtenstionMethods.AddCompatibleNoun(val, val3, val2);
			TerminalApi.AddTerminalKeyword(val3, new CommandInfo
			{
				TriggerNode = val2,
				DisplayTextSupplier = delegate
				{
					if ((Object)(object)cruiserMaterial == (Object)null)
					{
						return "Cannot set skin now.\n\n";
					}
					if (LNetworkUtils.IsHostOrServer)
					{
						Patch.skinLocal = skin.Key;
						Patch.skinMessage.SendClients(Patch.skinLocal);
					}
					else
					{
						if (onlyHostCanChangeSkin.Value)
						{
							return "Only host can use this command.";
						}
						Patch.skinMessage.SendServer(skin.Key);
					}
					return "Skin is set to " + skin.Key + ".\n\n";
				},
				Category = "Skins",
				Description = "Set skin to " + skin.Key
			});
		}
		TerminalApi.AddTerminalKeyword(val);
		TerminalApi.AddTerminalKeyword(TerminalApi.CreateTerminalKeyword("skins", "All available skins: " + string.Join(", ", skins.Keys) + ".\n\nTo set skin use 'skin {skin name}'.\n\n", true, ""));
	}
}
internal class Patch
{
	public static string skinLocal = "default";

	public static LNetworkMessage<string> skinMessage;

	private static Random random;

	[HarmonyPatch(typeof(StartOfRound), "StartGame")]
	[HarmonyPrefix]
	private static void StartGame(StartOfRound __instance)
	{
		if ((Object)(object)CSR.cruiserMaterial == (Object)null || (Object)(object)CSR.cruiserDestroyedMaterial == (Object)null)
		{
			VehicleController[] array = Object.FindObjectsByType<VehicleController>((FindObjectsSortMode)0);
			foreach (VehicleController val in array)
			{
				if (val.vehicleID == 0)
				{
					LoadCruiserMaterials(val);
				}
			}
			if ((Object)(object)CSR.cruiserMaterial == (Object)null || (Object)(object)CSR.cruiserDestroyedMaterial == (Object)null)
			{
				return;
			}
		}
		if (CSR.skinSelectionType.Value != CSR.SkinSelectionType.Terminal && LNetworkUtils.IsHostOrServer)
		{
			skinLocal = getRandomSkin();
			CSR.Log.LogInfo((object)("(Server) skinLocal is " + skinLocal + ". Sending it to clients."));
			skinMessage.SendClients(skinLocal);
		}
	}

	[HarmonyPatch(typeof(VehicleController), "Start")]
	[HarmonyPostfix]
	private static void Start(VehicleController __instance)
	{
		if (__instance.vehicleID == 0)
		{
			LoadCruiserMaterials(__instance);
			if (LNetworkUtils.IsHostOrServer)
			{
				CSR.Log.LogInfo((object)"(Server) VehicleController started. Sending skinLocal to clients.");
				skinMessage.SendClients(skinLocal);
			}
			else
			{
				CSR.Log.LogInfo((object)"(Client) VehicleController started. Sending ping to server.");
				skinMessage.SendServer("p");
			}
		}
	}

	private static void LoadCruiserMaterials(VehicleController vc)
	{
		if ((Object)(object)CSR.cruiserMaterial != (Object)null && (Object)(object)CSR.cruiserMaterial != (Object)null)
		{
			return;
		}
		MeshRenderer componentInChildren = ((Component)vc).GetComponentInChildren<MeshRenderer>();
		if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Renderer)componentInChildren).sharedMaterial != (Object)null && ((Object)((Renderer)componentInChildren).sharedMaterial).name.StartsWith("TruckTexture"))
		{
			CSR.cruiserMaterial = ((Renderer)componentInChildren).sharedMaterial;
			CSR.Log.LogInfo((object)"(Client) Default cruiser material is loaded.");
		}
		GameObject[] array = Object.FindObjectsByType<GameObject>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		foreach (GameObject val in array)
		{
			if (((Object)val).name.Contains("MainBodyDestroyed") && ((Object)((Renderer)val.GetComponent<MeshRenderer>()).sharedMaterial).name.StartsWith("TruckTextureDestroyed"))
			{
				CSR.cruiserDestroyedMaterial = ((Renderer)val.GetComponent<MeshRenderer>()).sharedMaterial;
				CSR.Log.LogInfo((object)"(Client) Destroyed cruiser material is loaded.");
			}
		}
		if ((Object)(object)CSR.cruiserMaterial == (Object)null || (Object)(object)CSR.cruiserDestroyedMaterial == (Object)null)
		{
			CSR.Log.LogWarning((object)"(Client) For some reason one of cruiser materials failed to load. Skins will not work.");
		}
	}

	private static void OnSkinRecievedServer(string skin, ulong player)
	{
		if (skin == "p")
		{
			CSR.Log.LogInfo((object)("(Server) Recieved ping from client. Sending host skin back: " + skinLocal));
			skinMessage.SendClient(skinLocal, player);
		}
		else
		{
			skinLocal = skin;
			skinMessage.SendClients(skinLocal, LNetworkUtils.AllConnectedClients);
		}
	}

	private static void OnSkinRecievedClient(string skin)
	{
		CSR.Log.LogInfo((object)("(Client) Recieved skin: " + skin));
		skinLocal = skin;
		SetSkin(skinLocal);
	}

	private static void SetSkin(string name)
	{
		if ((Object)(object)CSR.cruiserMaterial == (Object)null || (Object)(object)CSR.cruiserDestroyedMaterial == (Object)null)
		{
			CSR.Log.LogError((object)"(Client) Cannot set cruiser skin. Cruiser material is not loaded.");
			return;
		}
		CSR.cruiserMaterial.mainTexture = (Texture)(object)CSR.skins[name].defaultSkin;
		CSR.cruiserDestroyedMaterial.mainTexture = (Texture)(object)CSR.skins[name].destroyedSkin;
		CSR.Log.LogInfo((object)("(Client) Cruiser skin set to " + name));
	}

	private static string getRandomSkin()
	{
		if (CSR.skins.Count >= 3)
		{
			if (!CSR.randomWithoutRepeat.Value)
			{
				return CSR.skins.ElementAt(random.Next(0, CSR.skins.Count)).Key;
			}
			return getRandomSkinNoRepeatRecursive();
		}
		return getFirstSkin();
	}

	private static string getRandomSkinNoRepeatRecursive()
	{
		string key = CSR.skins.ElementAt(random.Next(0, CSR.skins.Count)).Key;
		if (key == skinLocal || (!CSR.useOriginalSkin.Value && key == "default"))
		{
			return getRandomSkinNoRepeatRecursive();
		}
		return key;
	}

	private static string getFirstSkin()
	{
		string result = "default";
		if (!CSR.useOriginalSkin.Value)
		{
			foreach (KeyValuePair<string, Skin> skin in CSR.skins)
			{
				if (skin.Key != "default")
				{
					return result = skin.Key;
				}
			}
		}
		return result;
	}

	static Patch()
	{
		Action<string> action = OnSkinRecievedClient;
		skinMessage = LNetworkMessage<string>.Connect("CSR.skinMessage", (Action<string, ulong>)OnSkinRecievedServer, action, (Action<string, ulong>)null);
		random = new Random();
	}
}
public class Skin
{
	public string name;

	public Texture2D defaultSkin;

	public Texture2D destroyedSkin;
}