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 skins = new Dictionary(); public static Material cruiserMaterial = null; public static Material cruiserDestroyedMaterial = null; public static ManualLogSource Log; private static LNetworkMessage> configMessage = LNetworkMessage>.Connect("CSR.Config", (Action, ulong>)OnServerConfigMessageRecieved, (Action>)OnClientConfigMessageRecieved, (Action, ulong>)null); public static ConfigEntry skinSelectionType; public static ConfigEntry randomWithoutRepeat; public static ConfigEntry useOriginalSkin; public static ConfigEntry 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("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("Random", "NoRepeats", true, "If true, skins are chosen randomly without repeating twice."); useOriginalSkin = ((BaseUnityPlugin)this).Config.Bind("Random", "UseOriginalSkin", false, "If true, mod will use original skin in random like all other custom skins."); onlyHostCanChangeSkin = ((BaseUnityPlugin)this).Config.Bind("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()); } } private static void OnServerConfigMessageRecieved(List list, ulong client) { List list2 = new List { 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 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 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 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((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(); 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((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (GameObject val in array) { if (((Object)val).name.Contains("MainBodyDestroyed") && ((Object)((Renderer)val.GetComponent()).sharedMaterial).name.StartsWith("TruckTextureDestroyed")) { CSR.cruiserDestroyedMaterial = ((Renderer)val.GetComponent()).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 skin in CSR.skins) { if (skin.Key != "default") { return result = skin.Key; } } } return result; } static Patch() { Action action = OnSkinRecievedClient; skinMessage = LNetworkMessage.Connect("CSR.skinMessage", (Action)OnSkinRecievedServer, action, (Action)null); random = new Random(); } } public class Skin { public string name; public Texture2D defaultSkin; public Texture2D destroyedSkin; }