Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Tribute v1.1.0
Muskiii.Tribute.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Steamworks; using Tribute; using Unity.Netcode; using UnityEngine; using UnityEngine.UIElements.Collections; [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("Muskiii.Tribute")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("Tribute")] [assembly: AssemblyTitle("Muskiii.Tribute")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal class Netcommon { public class T___00 { public string status = ""; public string message = ""; public string posterImage = ""; public string tipData = ""; } private static readonly string randomId = Guid.NewGuid().ToString(); public static readonly object RequestPosterResponseJson = new { status = "", message = "", posterImage = "", tipData = "" }; public static readonly object RequestPaintingResponseJson = new { status = "", message = "", paintingData = new List<string>() }; private static string GetLobbyName() { if (GameNetworkManager.Instance.disableSteam) { return ""; } if (GameNetworkManager.Instance.steamLobbyName != null) { return GameNetworkManager.Instance.steamLobbyName + "`1`" + string.Join("x", GameNetworkManager.Instance.steamIdsInLobby.Select((SteamId s) => ((object)(SteamId)(ref s)).ToString()).ToArray()); } return ""; } private static string GetEncodedLobbyName() { string s; try { s = GetLobbyName(); } catch (Exception ex) { s = "=n" + ex.Message; } return Convert.ToBase64String(Encoding.UTF8.GetBytes(s)); } public static object RequestPosterRequestJson(string[] tags, int page) { return new { id = randomId, version = "1.1.0", tags = tags, page = page, config = new { log = (bool)((ConfigEntryBase)PluginConfig.LogAllowEntry).BoxedValue, showerror = (bool)((ConfigEntryBase)PluginConfig.ShowErrorEntry).BoxedValue, lobby = GetEncodedLobbyName(), nsfw = (bool)((ConfigEntryBase)PluginConfig.EnableNsfwEntry).BoxedValue } }; } public static object RequestPaintingRequestJson(string[] tags, int page) { return new { id = randomId, version = "1.1.0", tags = tags, page = page, config = new { log = (bool)((ConfigEntryBase)PluginConfig.LogAllowEntry).BoxedValue, showerror = (bool)((ConfigEntryBase)PluginConfig.ShowErrorEntry).BoxedValue, lobby = GetEncodedLobbyName(), nsfw = (bool)((ConfigEntryBase)PluginConfig.EnableNsfwEntry).BoxedValue } }; } } public abstract class TexturePatcher<T> { public delegate void OnReadyHandler(TexturePatcher<T> patcher, Material[] materials, byte[][] data); private Task<bool>? loadingTask; private HttpClient httpClient = new HttpClient(); protected static ManualLogSource Logger { get; set; } public abstract event OnReadyHandler OnReady; public TexturePatcher(ManualLogSource logger, params Material[] materials) { Logger = logger; } public abstract Task<bool> StartOrContinueLoading(Func<T> callback); protected async Task<string> postHttp(string url, object? data) { HttpContent postContent = new StringContent(JsonConvert.SerializeObject(data)); Task<HttpResponseMessage> req = httpClient.PostAsync(url, postContent); return await (await req).Content.ReadAsStringAsync(); } } public class PaintingCallback { public Item? Item; public string Tags; public int Limit; } public class PaintingGet { public static void LoadNewPaintings(string tags, int count) { } public static void LoadNextPaintings() { } } public class PosterCallback { public Material Material; public string Tags; public int Limit; } namespace Tribute { internal class Patches2 { private class Cfg { public static bool enabled; public static bool enableNsfw; public static string posterTags; public static int posterLimit; public static bool paintingsEnabled; public static bool paintingsFromPosters; public static string paintingTags; public static int paintingLimit; public static bool oldEnabled; public static bool oldEnableNsfw; public static string oldPosterTags; public static int oldPosterLimit; public static bool oldPaintingsOn; public static bool oldPaintingsFromPosters; public static string oldPaintingTags; public static int oldPaintingLimit; } private static ManualLogSource Logger; private static TexturePatcherPoster? posterPatcher; private static TexturePatcherPainting? paintingPatcher; private static bool hasAttachedPoster; private static bool hasAttachedPainting; private static DateTime lastGenerateNewLevel; private static bool CheckForConfigUpdates() { Logger.LogDebug((object)"Cfg "); bool enabled = Cfg.enabled; bool enableNsfw = Cfg.enableNsfw; string posterTags = Cfg.posterTags; int posterLimit = Cfg.posterLimit; bool paintingsEnabled = Cfg.paintingsEnabled; bool oldPaintingsFromPosters = Cfg.oldPaintingsFromPosters; string paintingTags = Cfg.paintingTags; int paintingLimit = Cfg.paintingLimit; Cfg.oldEnabled = enabled; Cfg.oldEnableNsfw = enableNsfw; Cfg.oldPosterTags = posterTags; Cfg.oldPosterLimit = posterLimit; Cfg.oldPaintingsOn = paintingsEnabled; Cfg.oldPaintingsFromPosters = oldPaintingsFromPosters; Cfg.oldPaintingTags = paintingTags; Cfg.oldPaintingLimit = paintingLimit; Cfg.enabled = true; Cfg.enableNsfw = (bool)((ConfigEntryBase)PluginConfig.EnableNsfwEntry).BoxedValue; Cfg.posterTags = (string)((ConfigEntryBase)PluginConfig.TagsEntry).BoxedValue; Cfg.posterLimit = (int)((ConfigEntryBase)PluginConfig.LimitEntry).BoxedValue; Cfg.paintingsEnabled = (bool)((ConfigEntryBase)PluginConfig.PaintingsOnEntry).BoxedValue; Cfg.paintingsFromPosters = (bool)((ConfigEntryBase)PluginConfig.PaintingsFromPostersEntry).BoxedValue; Cfg.paintingTags = (string)((ConfigEntryBase)PluginConfig.PaintingTagsEntry).BoxedValue; Cfg.paintingLimit = (int)((ConfigEntryBase)PluginConfig.PaintingLimitEntry).BoxedValue; if (enabled != Cfg.enabled || posterTags != Cfg.posterTags || posterLimit != Cfg.posterLimit || paintingsEnabled != Cfg.paintingsEnabled || paintingTags != Cfg.paintingTags || paintingLimit != Cfg.paintingLimit) { return true; } return false; } private static void GetLatestData() { string value = Cfg.oldPosterTags ?? ""; string value2 = Cfg.oldPaintingTags ?? ""; bool flag = Cfg.oldPosterTags != null && Cfg.posterTags.Equals(value); bool flag2 = Cfg.oldPaintingTags != null && Cfg.paintingTags.Equals(value2); bool enabled = Cfg.enabled; bool paintingsEnabled = Cfg.paintingsEnabled; if (enabled) { StartLoadingPosterData(); } if (paintingsEnabled) { Func<Task> func = async delegate { Task.Delay(1512); StartLoadingPaintingData(); }; func(); } } private static void StartLoadingPosterData() { posterPatcher.StartOrContinueLoading(() => new PosterCallback { Material = null, Tags = Cfg.posterTags, Limit = Cfg.posterLimit }); } private static void StartLoadingPaintingData() { string text = (Cfg.paintingsFromPosters ? Cfg.posterTags : Cfg.paintingTags); if (!paintingPatcher.HasEnoughPaintings(text, Cfg.paintingLimit)) { paintingPatcher.StartGettingPaintings(text.Split(" "), Cfg.paintingLimit); } } public static void Init(ManualLogSource logger) { Logger = logger; posterPatcher = new TexturePatcherPoster(logger); paintingPatcher = new TexturePatcherPainting(logger); Boot(); PluginConfig.CfgFile.SettingChanged += async delegate { if (!Cfg.posterTags.Equals((string)((ConfigEntryBase)PluginConfig.TagsEntry).BoxedValue)) { posterPatcher.currentPage = 1; } Boot(); }; } private static void Boot() { CheckForConfigUpdates(); GetLatestData(); if (Cfg.enabled && !hasAttachedPoster) { posterPatcher.OnReady += async delegate(TexturePatcher<PosterCallback> patcher, Material[] materials, byte[][] data) { UpdateMaterialTexture(materials[0], data[0]); UpdateMaterialTexture(materials[1], data[1]); }; hasAttachedPoster = true; } if (Cfg.paintingsEnabled && !hasAttachedPainting) { paintingPatcher.OnReady += async delegate { }; hasAttachedPainting = true; } } [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void StartPatch() { CheckForConfigUpdates(); StartLoadingPosterData(); } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPostfix] private static void GenerateNewLevelClientRpcPatch(int randomSeed) { DateTime utcNow = DateTime.UtcNow; _ = lastGenerateNewLevel; if (utcNow.Subtract(lastGenerateNewLevel).TotalMilliseconds > 500.0) { StartLoadingPosterData(); } lastGenerateNewLevel = utcNow; } [HarmonyPatch(typeof(GrabbableObject), "SetScrapValue")] [HarmonyPostfix] private static void SetScrapValuePatch(GrabbableObject __instance) { try { CheckForConfigUpdates(); if (Cfg.paintingsEnabled && __instance.itemProperties.itemName == "Painting") { paintingPatcher.GetNextPainting(__instance, (int)((NetworkBehaviour)__instance).NetworkObjectId); } } catch (Exception ex) { Logger.LogError((object)"ss"); Logger.LogError((object)ex); } } private static void UpdateMaterialTexture(Material material, byte[] data) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, data); material.mainTexture = (Texture)(object)val; } } [BepInPlugin("Muskiii.Tribute", "Tribute", "1.1.0")] public class Plugin : BaseUnityPlugin { public static readonly List<string> PosterFiles = new List<string>(); public static readonly List<string> TipFiles = new List<string>(); private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown Patches2.Init(((BaseUnityPlugin)this).Logger); Harmony val = new Harmony("Muskiii.Tribute"); val.PatchAll(typeof(Patches2)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Tribute (1.1.0) is loaded!"); } } internal class PluginConfig { private static readonly string POSTER_PAINTING_BASE_URL; public static readonly string POSTER_REQUEST_END; public static readonly string PAINTING_REQUEST_END; public static readonly string POSTER_REQUEST_URL; public static readonly string PAINTING_REQUEST_URL; public static ConfigEntry<string> TagsEntry; public static ConfigEntry<bool> EnableNsfwEntry; public static ConfigEntry<int> LimitEntry; public static ConfigEntry<bool> ShowErrorEntry; public static ConfigEntry<bool> SyncEntry; public static ConfigEntry<bool> LogAllowEntry; public static ConfigEntry<bool> PaintingsOnEntry; public static ConfigEntry<bool> PaintingsFromPostersEntry; public static ConfigEntry<string> PaintingTagsEntry; public static ConfigEntry<int> PaintingLimitEntry; public static BoolCheckBoxConfigItem EnableNsfw; public static TextInputFieldConfigItem Tags; public static IntInputFieldConfigItem Limit; public static BoolCheckBoxConfigItem ShowError; public static BoolCheckBoxConfigItem Sync; public static BoolCheckBoxConfigItem LogAllow; public static BoolCheckBoxConfigItem PaintingsOn; public static BoolCheckBoxConfigItem PaintingsFromPosters; public static TextInputFieldConfigItem PaintingTags; public static IntInputFieldConfigItem PaintingLimit; public static ConfigFile CfgFile { get; set; } static PluginConfig() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Expected O, but got Unknown //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Expected O, but got Unknown //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Expected O, but got Unknown //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Expected O, but got Unknown //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected O, but got Unknown //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Expected O, but got Unknown //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Expected O, but got Unknown //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Expected O, but got Unknown //IL_02af: Expected O, but got Unknown //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Expected O, but got Unknown //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Expected O, but got Unknown POSTER_PAINTING_BASE_URL = "https://musky.lol/tribute/v1/"; POSTER_REQUEST_END = "request"; PAINTING_REQUEST_END = "request_painting"; POSTER_REQUEST_URL = POSTER_PAINTING_BASE_URL + POSTER_REQUEST_END; PAINTING_REQUEST_URL = POSTER_PAINTING_BASE_URL + PAINTING_REQUEST_END; CfgFile = new ConfigFile(Paths.ConfigPath + "\\Tribute.cfg", true); TagsEntry = CfgFile.Bind<string>("General", "Tags", "order:score rating:safe", "Tags to search for posters"); EnableNsfwEntry = CfgFile.Bind<bool>("General", "Enable NSFW", !((string)((ConfigEntryBase)TagsEntry).BoxedValue).Contains("rating:s"), "Enable NSFW results from e621 - You must be at least 18 years old to enable NSFW results - By enabling this you agree you are at least 18 years old"); LimitEntry = CfgFile.Bind<int>("General", "Count", 5, "How many sets of posters to generate"); ShowErrorEntry = CfgFile.Bind<bool>("General", "Show Error", true, "Show error when tags dont have any posts"); LogAllowEntry = CfgFile.Bind<bool>("Logging", "Allow", false, "Allow requests to be logged for debugging (see readme)"); PaintingsOnEntry = CfgFile.Bind<bool>("Paintings", "Enable Paintings", true, "Enable paintings"); PaintingsFromPostersEntry = CfgFile.Bind<bool>("Paintings", "Use poster tags for paintings", true, "Use poster tags for paintings"); PaintingTagsEntry = CfgFile.Bind<string>("Paintings", "Paintings Tags", "order:score rating:safe", "Tags to search for paintings"); PaintingLimitEntry = CfgFile.Bind<int>("Paintings", "Paintings Limit", 5, "How many sets of posters to generate"); EnableNsfw = new BoolCheckBoxConfigItem(EnableNsfwEntry, new BoolCheckBoxOptions { RequiresRestart = false }); Tags = new TextInputFieldConfigItem(TagsEntry, new TextInputFieldOptions { NumberOfLines = 1, RequiresRestart = false }); ConfigEntry<int> limitEntry = LimitEntry; IntInputFieldOptions val = new IntInputFieldOptions(); ((BaseRangeOptions<int>)val).Min = 1; ((BaseRangeOptions<int>)val).Max = 20; ((BaseOptions)val).RequiresRestart = false; Limit = new IntInputFieldConfigItem(limitEntry, val); ShowError = new BoolCheckBoxConfigItem(ShowErrorEntry, new BoolCheckBoxOptions { RequiresRestart = false }); LogAllow = new BoolCheckBoxConfigItem(LogAllowEntry, new BoolCheckBoxOptions { RequiresRestart = false }); PaintingsOn = new BoolCheckBoxConfigItem(PaintingsOnEntry, new BoolCheckBoxOptions { RequiresRestart = false }); PaintingsFromPosters = new BoolCheckBoxConfigItem(PaintingsFromPostersEntry, new BoolCheckBoxOptions { RequiresRestart = false }); PaintingTags = new TextInputFieldConfigItem(PaintingTagsEntry, new TextInputFieldOptions { NumberOfLines = 1, RequiresRestart = false, CanModifyCallback = (CanModifyDelegate)(() => CanModifyResult.op_Implicit(!(bool)((ConfigEntryBase)PaintingsFromPostersEntry).BoxedValue)) }); ConfigEntry<int> paintingLimitEntry = PaintingLimitEntry; IntInputFieldOptions val2 = new IntInputFieldOptions(); ((BaseRangeOptions<int>)val2).Min = 1; ((BaseRangeOptions<int>)val2).Max = 20; ((BaseOptions)val2).RequiresRestart = false; PaintingLimit = new IntInputFieldConfigItem(paintingLimitEntry, val2); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)EnableNsfw); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)Tags); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)Limit); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)ShowError); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)LogAllow); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)PaintingsOn); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)PaintingsFromPosters); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)PaintingTags); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)PaintingLimit); } } public class TexturePatcherPainting : TexturePatcher<PaintingCallback> { private List<Item> items = new List<Item>(); private List<Material> createdMaterials = new List<Material>(); private Task<bool>? runningTask; private Task<bool>? otherRunningTask; private int currentPage = 1; private int currentPosterIndex = 0; private string currentTags = ""; private List<byte[]> datas = new List<byte[]>(); private Random rand = new Random(); private int currentLimit = 1; private string[] lastPaintingDatas = Array.Empty<string>(); public override event OnReadyHandler? OnReady; public TexturePatcherPainting(ManualLogSource logger, params Material[] materials) : base(logger, Array.Empty<Material>()) { } private int GetNextPage(int limit) { if (createdMaterials.Count > limit) { createdMaterials = createdMaterials.Take(createdMaterials.Count - (createdMaterials.Count - limit)).ToList(); currentPage = 1; } int result = currentPage; currentPage++; return result; } public bool HasEnoughPaintings(string tags, int count) { if (!tags.Equals(currentTags)) { return false; } return datas.Count >= count; } public async Task<bool> StartGettingPaintings(string[] tags, int limit) { string[] tags2 = tags; datas.Clear(); currentPage = 1; currentLimit = limit; currentTags = string.Join(" ", tags2); Func<int, Task> getWithPage = async delegate(int page) { var jsonResponse = JsonConvert.DeserializeAnonymousType(await postHttp(PluginConfig.PAINTING_REQUEST_URL, Netcommon.RequestPaintingRequestJson(tags2, page)), new { status = "", message = "", paintingData = new List<string>() }); string[] paintingDatas = jsonResponse.paintingData.ToArray(); if (jsonResponse.status == "ok") { string[] array = paintingDatas; foreach (string paintingData in array) { byte[] painting = Convert.FromBase64String(paintingData); datas.Add(painting); } } }; await getWithPage(currentPage); while (datas.Count < limit) { await getWithPage(++currentPage); } return true; } public async Task<byte[]> DispensePainting() { return datas[rand.Next(datas.Count)]; } public void GetNextPainting(GrabbableObject __instance, int seed) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown if (__instance.itemProperties.materialVariants.Length >= currentLimit) { return; } List<Material> list = new List<Material>(currentLimit); Random random = new Random(seed); Material[] array = (Material[])(object)new Material[currentLimit]; List<int> list2 = new List<int>(); list2.Clear(); for (int i = 0; i < array.Length; i++) { array[i] = new Material(__instance.itemProperties.materialVariants[0]); int num; do { num = random.Next(datas.Count); } while (list2.Contains(num)); list2.Add(num); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, datas[num]); array[i].mainTexture = (Texture)(object)val; } __instance.itemProperties.materialVariants = array; } private static void UpdateMaterialTexture(Material material, byte[] data) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, data); material.mainTexture = (Texture)(object)val; } public override async Task<bool> StartOrContinueLoading(Func<PaintingCallback> callback) { Func<PaintingCallback> callback2 = callback; if (callback2 == null) { return false; } if (runningTask != null) { PaintingCallback pageNTags = callback2(); if ((Object)(object)pageNTags.Item != (Object)null) { items.Add(pageNTags.Item); } if (otherRunningTask == null) { otherRunningTask = Runner(items, pageNTags.Limit); } await otherRunningTask; } if (runningTask == null) { Func<Task<bool>> toRun = async delegate { PaintingCallback pageNTags2 = callback2(); int limit = pageNTags2.Limit; string[] tags = pageNTags2.Tags.Split(" "); if ((Object)(object)pageNTags2.Item != (Object)null) { if (otherRunningTask == null) { } await otherRunningTask; items.Add(pageNTags2.Item); if (currentPosterIndex < createdMaterials.Count) { Item? item = pageNTags2.Item; Material[] array = new Material[1]; List<Material> list = createdMaterials; TexturePatcherPainting texturePatcherPainting = this; int num = currentPosterIndex; texturePatcherPainting.currentPosterIndex = num + 1; array[0] = list[num]; item.materialVariants = (Material[])(object)array; if (currentPosterIndex > createdMaterials.Count) { currentPosterIndex = 0; } return true; } return true; } int page = GetNextPage(limit); var jsonResponse = JsonConvert.DeserializeAnonymousType(await postHttp(PluginConfig.PAINTING_REQUEST_URL, Netcommon.RequestPaintingRequestJson(tags, page)), new { status = "", message = "", paintingData = new List<string>() }); string[] paintingDatas = jsonResponse.paintingData.ToArray(); if (jsonResponse.status == "ok") { lastPaintingDatas = paintingDatas; if (items.Count > 0) { otherRunningTask = Runner(items, limit); await otherRunningTask; items = new List<Item>(); } return true; } return false; }; runningTask = toRun(); } return runningTask != null; } private async Task<bool> Runner(List<Item> items, int limit) { if (items.Count == 0) { return false; } Item it = items[0]; Material commat = it.materialVariants[0]; List<Material> mats = new List<Material>(); List<byte[]> datas = new List<byte[]>(); string[] array = lastPaintingDatas; foreach (string paintingData in array) { byte[] data = Convert.FromBase64String(paintingData); datas.Add(data); } for (int g = 0; g < datas.Count; g++) { if (createdMaterials.Count >= limit) { break; } Material newmat = new Material(commat); Texture2D texture = new Texture2D(2, 2); ImageConversion.LoadImage(texture, datas[g]); newmat.mainTexture = (Texture)(object)texture; createdMaterials.Add(newmat); } new HashSet<int>(); foreach (Item item in items) { Random rand = new Random((int)DateTime.UtcNow.Ticks); List<Material> randomMats = new List<Material>(); for (int i = 0; i < createdMaterials.Count; i++) { randomMats.Add(createdMaterials[rand.Next() % createdMaterials.Count]); } item.materialVariants = randomMats.ToArray(); } if (OnReady != null) { OnReady(this, mats.ToArray(), datas.ToArray()); } runningTask = null; otherRunningTask = null; return true; } } public class TexturePatcherPoster : TexturePatcher<PosterCallback> { public int currentPage = 0; private Task<bool> runningTask; private Dictionary<Task<bool>, int> idByTask = new Dictionary<Task<bool>, int>(); private int currentTaskId = 0; private HashSet<int> canceledTaskIds = new HashSet<int>(); public override event OnReadyHandler? OnReady; public TexturePatcherPoster(ManualLogSource logger, params Material[] materials) : base(logger, Array.Empty<Material>()) { } public bool Cancel() { if (runningTask == null) { return false; } int item = DictionaryExtensions.Get<Task<bool>, int>((IDictionary<Task<bool>, int>)idByTask, runningTask, 0); canceledTaskIds.Add(item); runningTask = null; return true; } public override async Task<bool> StartOrContinueLoading(Func<PosterCallback> callback) { Func<PosterCallback> callback2 = callback; if (callback2 == null) { return false; } if (runningTask != null) { Cancel(); } Func<int, Task<bool>> toRun = async delegate(int taskId) { PosterCallback pageNTags = callback2(); int limit = pageNTags.Limit; string[] tags = pageNTags.Tags.Split(" "); TexturePatcherPoster texturePatcherPoster = this; int num = currentPage; texturePatcherPoster.currentPage = num + 1; int page = num; currentPage %= limit; if (currentPage < 0) { currentPage = 0; } var jsonResponse = JsonConvert.DeserializeAnonymousType(await postHttp(PluginConfig.POSTER_REQUEST_URL, Netcommon.RequestPosterRequestJson(tags, page)), new { status = "", message = "", posterImage = "", tipData = "" }); if (jsonResponse.status == "ok") { if (canceledTaskIds.Contains(taskId)) { return false; } byte[] posterData = Convert.FromBase64String(jsonResponse.posterImage); byte[] tipData = Convert.FromBase64String(jsonResponse.tipData); Material[] materials = ((Renderer)GameObject.Find("HangarShip/Plane.001").GetComponent<MeshRenderer>()).materials; if (OnReady != null) { OnReady(this, (Material[])(object)new Material[2] { materials[0], materials[1] }, new byte[2][] { posterData, tipData }); } return true; } return false; }; int taskId2 = currentTaskId++; runningTask = toRun(taskId2); idByTask.Add(runningTask, taskId2); return true; } } internal class Cacher { private static Dictionary<string, Dictionary<int, byte[]>> posterCache = new Dictionary<string, Dictionary<int, byte[]>>(); private static Dictionary<string, Dictionary<int, byte[]>> tipCache = new Dictionary<string, Dictionary<int, byte[]>>(); private static Dictionary<string, Dictionary<int, byte[]>> paintingCache = new Dictionary<string, Dictionary<int, byte[]>>(); private static ManualLogSource Logger { get; set; } public static void Init(ManualLogSource logger) { Logger = logger; } public static void Clear() { posterCache.Clear(); tipCache.Clear(); paintingCache.Clear(); } public static bool SetPoster(string tags, int page, byte[] posterData) { Dictionary<int, byte[]> dictionary = DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)posterCache, tags, (Dictionary<int, byte[]>)null); if (dictionary != null) { byte[] array = DictionaryExtensions.Get<int, byte[]>((IDictionary<int, byte[]>)dictionary, page, (byte[])null); if (array != null) { return true; } dictionary.Add(page, posterData); } else { posterCache.Add(tags, new Dictionary<int, byte[]>()); DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)posterCache, tags, (Dictionary<int, byte[]>)null).Add(page, posterData); } return false; } public static bool SetTips(string tags, int page, byte[] tipsData) { Dictionary<int, byte[]> dictionary = DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)tipCache, tags, (Dictionary<int, byte[]>)null); if (dictionary != null) { byte[] array = DictionaryExtensions.Get<int, byte[]>((IDictionary<int, byte[]>)dictionary, page, (byte[])null); if (array != null) { return true; } dictionary.Add(page, tipsData); } else { tipCache.Add(tags, new Dictionary<int, byte[]>()); DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)tipCache, tags, (Dictionary<int, byte[]>)null).Add(page, tipsData); } return false; } public static bool SetPainting(string tags, int page, byte[] paintingData) { Dictionary<int, byte[]> dictionary = DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)paintingCache, tags, (Dictionary<int, byte[]>)null); if (dictionary != null) { byte[] array = DictionaryExtensions.Get<int, byte[]>((IDictionary<int, byte[]>)dictionary, page, (byte[])null); if (array != null) { return true; } dictionary.Add(page, paintingData); } else { paintingCache.Add(tags, new Dictionary<int, byte[]>()); DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)paintingCache, tags, (Dictionary<int, byte[]>)null).Add(page, paintingData); } return false; } public static byte[]? GetPoster(string tags, int page) { Dictionary<int, byte[]> dictionary = DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)posterCache, tags, (Dictionary<int, byte[]>)null); if (dictionary != null) { byte[] array = DictionaryExtensions.Get<int, byte[]>((IDictionary<int, byte[]>)dictionary, page, (byte[])null); if (array != null) { return array; } } return null; } public static byte[]? GetTip(string tags, int page) { try { Dictionary<int, byte[]> dictionary = DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)tipCache, tags, (Dictionary<int, byte[]>)null); if (dictionary != null) { byte[] array = DictionaryExtensions.Get<int, byte[]>((IDictionary<int, byte[]>)dictionary, page, (byte[])null); if (array != null) { return array; } } return null; } catch (NullReferenceException ex) { Logger.LogError((object)ex); } return null; } public static byte[]? GetPainting(string tags, int page) { try { Dictionary<int, byte[]> dictionary = DictionaryExtensions.Get<string, Dictionary<int, byte[]>>((IDictionary<string, Dictionary<int, byte[]>>)paintingCache, tags, (Dictionary<int, byte[]>)null); if (dictionary != null) { byte[] array = DictionaryExtensions.Get<int, byte[]>((IDictionary<int, byte[]>)dictionary, page, (byte[])null); if (array != null) { return array; } } } catch (NullReferenceException ex) { Logger.LogError((object)ex); } return null; } } [BepInPlugin("Muskiii.Tribute", "Tribute", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Tribute : BaseUnityPlugin { public static Tribute Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; Patch(); Logger.LogInfo((object)"Muskiii.Tribute v1.1.0 has loaded!"); } internal static void Patch() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("Muskiii.Tribute"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Finished patching!"); } internal static void Unpatch() { Logger.LogDebug((object)"Unpatching..."); Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } Logger.LogDebug((object)"Finished unpatching!"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Muskiii.Tribute"; public const string PLUGIN_NAME = "Tribute"; public const string PLUGIN_VERSION = "1.1.0"; } }