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 PhotoScrap v1.1.0
BepInEx\plugins\Wang2-PhotoScrap\PhotoScrap.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LethalLib.Modules; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace Wang2.PhotoScrap; public sealed class PhotoFrameItem : PhysicsProp { public GameObject Backing; public GameObject PhotoSurface; public GameObject TopBorder; public GameObject BottomBorder; public GameObject LeftBorder; public GameObject RightBorder; public BoxCollider FrameCollider; public ScanNodeProperties ScanNode; internal int LoadedPhotoToken; private ulong _lastPhotoId = ulong.MaxValue; private Texture2D _lastTexture; private Material _runtimePhotoMaterial; public override void Start() { ((GrabbableObject)this).Start(); RefreshPhoto(); } public override void OnNetworkSpawn() { ((NetworkBehaviour)this).OnNetworkSpawn(); RefreshPhoto(); } public override int GetItemDataToSave() { if (PhotoNetwork.TryGetFramePhotoId(((NetworkBehaviour)this).NetworkObjectId, out var photoId) && PhotoLibrary.TryGetToken(photoId, out var token)) { return token; } return LoadedPhotoToken; } public override void LoadItemSaveData(int saveData) { ((GrabbableObject)this).LoadItemSaveData(saveData); LoadedPhotoToken = saveData; if (((NetworkBehaviour)this).IsServer && ((NetworkBehaviour)this).IsSpawned) { PhotoAssignment.AssignSavedFrame(this); } } public override void OnNetworkDespawn() { PhotoNetwork.ForgetFrame(((NetworkBehaviour)this).NetworkObjectId); ((NetworkBehaviour)this).OnNetworkDespawn(); } internal void RefreshPhoto() { if (!PhotoNetwork.TryGetFramePhotoId(((NetworkBehaviour)this).NetworkObjectId, out var photoId)) { photoId = 0uL; } Texture2D val = PhotoNetwork.GetTexture(photoId); if ((Object)(object)val == (Object)null) { val = PhotoScrapPlugin.PlaceholderTexture; } if (_lastPhotoId == photoId && (Object)(object)_lastTexture == (Object)(object)val) { UpdateScanValue(); return; } _lastPhotoId = photoId; _lastTexture = val; ApplyPhoto(val, photoId); UpdateScanValue(); } internal void UpdateScanValue() { if ((Object)(object)ScanNode != (Object)null) { ScanNode.scrapValue = ((GrabbableObject)this).scrapValue; } } private void ApplyPhoto(Texture2D texture, ulong photoId) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown if (!((Object)(object)texture == (Object)null) && !((Object)(object)PhotoSurface == (Object)null)) { float num = Mathf.Clamp((float)((Texture)texture).width / (float)((Texture)texture).height, 0.45f, 2.15f); float num2; float num3; if (num >= 1f) { num2 = 0.72f; num3 = 0.72f / num; } else { num3 = 0.72f; num2 = 0.72f * num; } SetTransform(Backing.transform, new Vector3(0f, 0f, 0f), new Vector3(num2 + 0.12f, num3 + 0.12f, 0.04f)); SetTransform(PhotoSurface.transform, new Vector3(0f, 0f, 0.031f), new Vector3(num2, num3, 0.012f)); SetTransform(TopBorder.transform, new Vector3(0f, num3 * 0.5f + 0.03f, 0.045f), new Vector3(num2 + 0.12f, 0.06f, 0.075f)); SetTransform(BottomBorder.transform, new Vector3(0f, (0f - num3) * 0.5f - 0.03f, 0.045f), new Vector3(num2 + 0.12f, 0.06f, 0.075f)); SetTransform(LeftBorder.transform, new Vector3((0f - num2) * 0.5f - 0.03f, 0f, 0.045f), new Vector3(0.06f, num3, 0.075f)); SetTransform(RightBorder.transform, new Vector3(num2 * 0.5f + 0.03f, 0f, 0.045f), new Vector3(0.06f, num3, 0.075f)); if ((Object)(object)FrameCollider != (Object)null) { FrameCollider.center = new Vector3(0f, 0f, 0.025f); FrameCollider.size = new Vector3(num2 + 0.12f, num3 + 0.12f, 0.1f); } if ((Object)(object)_runtimePhotoMaterial != (Object)null) { Object.Destroy((Object)(object)_runtimePhotoMaterial); } _runtimePhotoMaterial = new Material(PhotoScrapPlugin.PhotoMaterialTemplate); ((Object)_runtimePhotoMaterial).name = "PhotoScrap_RuntimePhoto_" + photoId.ToString("X16"); PhotoScrapPlugin.SetMaterialTexture(_runtimePhotoMaterial, (Texture)(object)texture); ((Renderer)PhotoSurface.GetComponent<MeshRenderer>()).sharedMaterial = _runtimePhotoMaterial; } } private static void SetTransform(Transform target, Vector3 position, Vector3 scale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) target.localPosition = position; target.localRotation = Quaternion.identity; target.localScale = scale; } public override void OnDestroy() { if ((Object)(object)_runtimePhotoMaterial != (Object)null) { Object.Destroy((Object)(object)_runtimePhotoMaterial); } ((GrabbableObject)this).OnDestroy(); } } internal static class PhotoAssignment { private static readonly List<PhotoRecord> Bag = new List<PhotoRecord>(); private static readonly Random Random = new Random(); private static ulong _lastPhotoId; internal static void ResetSession() { Bag.Clear(); _lastPhotoId = 0uL; } internal static void StartNewRound() { Bag.Clear(); _lastPhotoId = 0uL; } internal static void AssignSavedFrame(PhotoFrameItem frame) { if (!((Object)(object)frame == (Object)null) && ((NetworkBehaviour)frame).IsSpawned && !PhotoNetwork.TryGetFramePhotoId(((NetworkBehaviour)frame).NetworkObjectId, out var _)) { if (frame.LoadedPhotoToken != 0 && PhotoLibrary.TryGetByToken(frame.LoadedPhotoToken, out var record)) { PhotoNetwork.AssignFrame(((NetworkBehaviour)frame).NetworkObjectId, record.Id); } else { AssignNewFrame(frame); } } } internal static void AssignNewFrame(PhotoFrameItem frame) { if (!((Object)(object)frame == (Object)null) && ((NetworkBehaviour)frame).IsSpawned && !PhotoNetwork.TryGetFramePhotoId(((NetworkBehaviour)frame).NetworkObjectId, out var _)) { ulong photoId2 = DrawPhoto()?.Id ?? 0; PhotoNetwork.AssignFrame(((NetworkBehaviour)frame).NetworkObjectId, photoId2); } } private static PhotoRecord DrawPhoto() { IList<PhotoRecord> records = PhotoLibrary.Records; if (records == null || records.Count == 0) { return null; } if (Bag.Count == 0) { for (int i = 0; i < records.Count; i++) { Bag.Add(records[i]); } for (int num = Bag.Count - 1; num > 0; num--) { int index = Random.Next(num + 1); PhotoRecord value = Bag[num]; Bag[num] = Bag[index]; Bag[index] = value; } if (Bag.Count > 1 && Bag[0].Id == _lastPhotoId) { PhotoRecord value2 = Bag[0]; Bag[0] = Bag[1]; Bag[1] = value2; } } PhotoRecord photoRecord = Bag[0]; Bag.RemoveAt(0); _lastPhotoId = photoRecord.Id; return photoRecord; } } [HarmonyPatch(typeof(RoundManager), "SyncScrapValuesClientRpc")] internal static class SyncScrapValuesPatch { private sealed class FrameReference { public ulong NetworkId; public PhotoFrameItem Frame; } private static void Prefix(NetworkObjectReference[] spawnedScrap) { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || spawnedScrap == null) { return; } List<FrameReference> list = new List<FrameReference>(); NetworkObject val = default(NetworkObject); for (int i = 0; i < spawnedScrap.Length; i++) { if (((NetworkObjectReference)(ref spawnedScrap[i])).TryGet(ref val, NetworkManager.Singleton) && !((Object)(object)val == (Object)null)) { PhotoFrameItem component = ((Component)val).GetComponent<PhotoFrameItem>(); if (!((Object)(object)component == (Object)null)) { FrameReference frameReference = new FrameReference(); frameReference.NetworkId = val.NetworkObjectId; frameReference.Frame = component; list.Add(frameReference); } } } list.Sort((FrameReference left, FrameReference right) => left.NetworkId.CompareTo(right.NetworkId)); for (int num = 0; num < list.Count; num++) { PhotoAssignment.AssignNewFrame(list[num].Frame); } } } [HarmonyPatch(typeof(RoundManager), "LoadNewLevel")] internal static class NewRoundPatch { private static void Prefix() { if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer) { PhotoAssignment.StartNewRound(); } } } [HarmonyPatch(typeof(GrabbableObject), "SetScrapValue")] internal static class SetScrapValuePatch { private static void Postfix(GrabbableObject __instance) { PhotoFrameItem photoFrameItem = __instance as PhotoFrameItem; if ((Object)(object)photoFrameItem != (Object)null) { photoFrameItem.UpdateScanValue(); } } } internal sealed class PhotoRecord { internal ulong Id; internal int Token; internal byte[] JpegBytes; internal int Width; internal int Height; internal string SourceName; } internal static class PhotoLibrary { internal const int MaxNetworkPhotoBytes = 524288; private static readonly List<PhotoRecord> PhotoRecords = new List<PhotoRecord>(); private static readonly Dictionary<ulong, PhotoRecord> ById = new Dictionary<ulong, PhotoRecord>(); private static readonly Dictionary<int, PhotoRecord> ByToken = new Dictionary<int, PhotoRecord>(); private static string _folder; private static int _maximumDimension; private static int _jpegQuality; private static int _maximumPhotos; private static long _maximumInputBytes; private static bool _loaded; internal static IList<PhotoRecord> Records => PhotoRecords.AsReadOnly(); internal static void Configure(string folder, int maximumDimension, int jpegQuality, int maximumPhotos, int maximumInputMegabytes) { _folder = Environment.ExpandEnvironmentVariables(folder ?? string.Empty).Trim(); _maximumDimension = maximumDimension; _jpegQuality = jpegQuality; _maximumPhotos = maximumPhotos; _maximumInputBytes = (long)maximumInputMegabytes * 1024L * 1024; } internal static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; PhotoRecords.Clear(); ById.Clear(); ByToken.Clear(); try { if (string.IsNullOrWhiteSpace(_folder)) { string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); _folder = Path.Combine(folderPath, "PhotoScrap"); } _folder = Path.GetFullPath(_folder); Directory.CreateDirectory(_folder); string[] extensions = new string[3] { ".jpg", ".jpeg", ".png" }; string[] array = (from path in Directory.GetFiles(_folder, "*", SearchOption.TopDirectoryOnly) where extensions.Contains(Path.GetExtension(path).ToLowerInvariant()) select path).OrderBy<string, string>((string path) => Path.GetFileName(path), StringComparer.OrdinalIgnoreCase).Take(_maximumPhotos).ToArray(); for (int num = 0; num < array.Length; num++) { TryLoadFile(array[num]); } if (PhotoRecords.Count == 0) { PhotoScrapPlugin.Log.LogWarning((object)("No usable host photos were found. Frames will use the placeholder. Folder: " + _folder)); return; } PhotoScrapPlugin.Log.LogInfo((object)("Prepared " + PhotoRecords.Count + " host photos from: " + _folder)); } catch (Exception ex) { PhotoScrapPlugin.Log.LogError((object)("Unable to load the host photo folder: " + ex)); } } private static void TryLoadFile(string path) { try { FileInfo fileInfo = new FileInfo(path); if (!fileInfo.Exists || fileInfo.Length <= 0 || fileInfo.Length > _maximumInputBytes) { PhotoScrapPlugin.Log.LogWarning((object)("Skipped an empty or oversized photo: " + fileInfo.Name)); return; } byte[] array = File.ReadAllBytes(path); byte[] rawHash = ComputeHash(array); string cachePath = GetCachePath(rawHash); byte[] array2 = null; int width = 0; int height = 0; if (File.Exists(cachePath)) { byte[] array3 = File.ReadAllBytes(cachePath); if (array3.Length > 0 && array3.Length <= 524288 && TryReadJpegDimensions(array3, out width, out height)) { array2 = array3; } } if (array2 == null) { array2 = CompressPhoto(array, out width, out height); if (array2 == null || array2.Length == 0 || array2.Length > 524288) { PhotoScrapPlugin.Log.LogWarning((object)("Skipped a photo that could not be compressed safely: " + fileInfo.Name)); return; } try { Directory.CreateDirectory(Path.GetDirectoryName(cachePath)); File.WriteAllBytes(cachePath, array2); } catch (Exception ex) { PhotoScrapPlugin.Log.LogWarning((object)("Photo cache write failed: " + ex.Message)); } } ulong num = ComputeId(array2); if (ById.ContainsKey(num)) { return; } int num2 = (int)(num & 0x7FFFFFFF); if (num2 == 0) { num2 = 1; } while (ByToken.ContainsKey(num2)) { num2 = (num2 * 397 + 17) & 0x7FFFFFFF; if (num2 == 0) { num2 = 1; } } PhotoRecord photoRecord = new PhotoRecord(); photoRecord.Id = num; photoRecord.Token = num2; photoRecord.JpegBytes = array2; photoRecord.Width = width; photoRecord.Height = height; photoRecord.SourceName = fileInfo.Name; PhotoRecords.Add(photoRecord); ById.Add(num, photoRecord); ByToken.Add(num2, photoRecord); } catch (Exception ex2) { PhotoScrapPlugin.Log.LogWarning((object)("Skipped photo " + Path.GetFileName(path) + ": " + ex2.Message)); } } private static string GetCachePath(byte[] rawHash) { string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "PhotoScrap", "Cache"); string path2 = ToHex(rawHash) + "_" + _maximumDimension + "_" + _jpegQuality + ".jpg"; return Path.Combine(path, path2); } private static byte[] CompressPhoto(byte[] sourceBytes, out int outputWidth, out int outputHeight) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown outputWidth = 0; outputHeight = 0; Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ((Object)val).name = "PhotoScrap_Source"; if (!ImageConversion.LoadImage(val, sourceBytes, false)) { Object.DestroyImmediate((Object)(object)val); return null; } int orientation = ReadExifOrientation(sourceBytes); int num = _maximumDimension; int num2 = _jpegQuality; byte[] array = null; try { for (int i = 0; i < 6; i++) { FitDimensions(((Texture)val).width, ((Texture)val).height, num, out var targetWidth, out var targetHeight); Texture2D val2 = Resize(val, targetWidth, targetHeight); Texture2D val3 = ApplyOrientation(val2, orientation); try { array = ImageConversion.EncodeToJPG(val3, num2); outputWidth = ((Texture)val3).width; outputHeight = ((Texture)val3).height; } finally { if ((Object)(object)val3 != (Object)(object)val2) { Object.DestroyImmediate((Object)(object)val3); } if ((Object)(object)val2 != (Object)(object)val) { Object.DestroyImmediate((Object)(object)val2); } } if (array == null || array.Length > 524288) { num = Math.Max(256, num * 3 / 4); num2 = Math.Max(55, num2 - 5); continue; } break; } } finally { Object.DestroyImmediate((Object)(object)val); } return array; } private static void FitDimensions(int width, int height, int maximum, out int targetWidth, out int targetHeight) { int num = Math.Max(width, height); if (num <= maximum) { targetWidth = width; targetHeight = height; } else { float num2 = (float)maximum / (float)num; targetWidth = Math.Max(1, Mathf.RoundToInt((float)width * num2)); targetHeight = Math.Max(1, Mathf.RoundToInt((float)height * num2)); } } private static Texture2D Resize(Texture2D source, int width, int height) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (((Texture)source).width == width && ((Texture)source).height == height) { return source; } RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); RenderTexture active = RenderTexture.active; try { Graphics.Blit((Texture)(object)source, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(width, height, (TextureFormat)3, false); ((Object)val).name = "PhotoScrap_Resized"; val.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0, false); val.Apply(false, false); return val; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } private static Texture2D ApplyOrientation(Texture2D source, int orientation) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if (orientation <= 1 || orientation > 8) { return source; } int width = ((Texture)source).width; int height = ((Texture)source).height; bool flag = orientation >= 5; int num = (flag ? height : width); int num2 = (flag ? width : height); Color32[] pixels = source.GetPixels32(); Color32[] array = (Color32[])(object)new Color32[num * num2]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int num3 = j; int num4 = i; switch (orientation) { case 2: num3 = width - 1 - j; break; case 3: num3 = width - 1 - j; num4 = height - 1 - i; break; case 4: num4 = height - 1 - i; break; case 5: num3 = height - 1 - i; num4 = width - 1 - j; break; case 6: num3 = i; num4 = width - 1 - j; break; case 7: num3 = i; num4 = j; break; case 8: num3 = height - 1 - i; num4 = j; break; } ref Color32 reference = ref array[num4 * num + num3]; reference = pixels[i * width + j]; } } Texture2D val = new Texture2D(num, num2, (TextureFormat)3, false); ((Object)val).name = "PhotoScrap_Oriented"; val.SetPixels32(array); val.Apply(false, false); return val; } private static int ReadExifOrientation(byte[] bytes) { try { if (bytes == null || bytes.Length < 14 || bytes[0] != byte.MaxValue || bytes[1] != 216) { return 1; } int num; for (int i = 2; i + 4 < bytes.Length && bytes[i] == byte.MaxValue; i += 2 + num) { byte b = bytes[i + 1]; num = (bytes[i + 2] << 8) | bytes[i + 3]; if (num < 2 || i + 2 + num > bytes.Length) { break; } int num2 = i + 4; if (b != 225 || num < 16 || bytes[num2] != 69 || bytes[num2 + 1] != 120 || bytes[num2 + 2] != 105 || bytes[num2 + 3] != 102) { continue; } int num3 = num2 + 6; bool flag = bytes[num3] == 73 && bytes[num3 + 1] == 73; bool flag2 = bytes[num3] == 77 && bytes[num3 + 1] == 77; if (!flag && !flag2) { return 1; } uint num4 = ReadUInt32(bytes, num3 + 4, flag); int num5 = checked(num3 + (int)num4); ushort num6 = ReadUInt16(bytes, num5, flag); for (int j = 0; j < num6; j++) { int num7 = num5 + 2 + j * 12; if (num7 + 12 > bytes.Length) { break; } if (ReadUInt16(bytes, num7, flag) == 274) { int num8 = ReadUInt16(bytes, num7 + 8, flag); return (num8 < 1 || num8 > 8) ? 1 : num8; } } } } catch { } return 1; } private static ushort ReadUInt16(byte[] bytes, int offset, bool little) { if (offset < 0 || offset + 2 > bytes.Length) { throw new EndOfStreamException(); } if (!little) { return (ushort)((bytes[offset] << 8) | bytes[offset + 1]); } return (ushort)(bytes[offset] | (bytes[offset + 1] << 8)); } private static uint ReadUInt32(byte[] bytes, int offset, bool little) { if (offset < 0 || offset + 4 > bytes.Length) { throw new EndOfStreamException(); } if (little) { return (uint)(bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)); } return (uint)((bytes[offset] << 24) | (bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3]); } internal static ulong ComputeId(byte[] bytes) { byte[] value = ComputeHash(bytes); ulong num = BitConverter.ToUInt64(value, 0); if (num != 0) { return num; } return 6287392622479692611uL; } private static byte[] ComputeHash(byte[] bytes) { using SHA256 sHA = SHA256.Create(); return sHA.ComputeHash(bytes); } private static string ToHex(byte[] bytes) { StringBuilder stringBuilder = new StringBuilder(bytes.Length * 2); for (int i = 0; i < bytes.Length; i++) { stringBuilder.Append(bytes[i].ToString("x2")); } return stringBuilder.ToString(); } internal static bool TryGetRecord(ulong id, out PhotoRecord record) { return ById.TryGetValue(id, out record); } internal static bool TryGetByToken(int token, out PhotoRecord record) { return ByToken.TryGetValue(token, out record); } internal static bool TryGetToken(ulong id, out int token) { if (ById.TryGetValue(id, out var value)) { token = value.Token; return true; } token = 0; return false; } internal static bool TryReadJpegDimensions(byte[] bytes, out int width, out int height) { width = 0; height = 0; try { if (bytes == null || bytes.Length < 4 || bytes[0] != byte.MaxValue || bytes[1] != 216) { return false; } int num; for (int i = 2; i + 8 < bytes.Length; i += 2 + num) { if (bytes[i] != byte.MaxValue) { return false; } byte b = bytes[i + 1]; num = (bytes[i + 2] << 8) | bytes[i + 3]; if (num < 2 || i + 2 + num > bytes.Length) { return false; } if (b >= 192 && b <= 207 && b != 196 && b != 200 && b != 204) { height = (bytes[i + 5] << 8) | bytes[i + 6]; width = (bytes[i + 7] << 8) | bytes[i + 8]; return width > 0 && height > 0 && width <= 4096 && height <= 4096; } } } catch { } return false; } internal static void Shutdown() { PhotoRecords.Clear(); ById.Clear(); ByToken.Clear(); _loaded = false; } } internal static class PhotoNetwork { private sealed class ReceiveState { internal byte[] Buffer; internal int NextOffset; } private const int ProtocolVersion = 2; private const int ChunkSize = 12288; private const string HelloMessage = "W2PS_110_HELLO"; private const string AcknowledgeMessage = "W2PS_110_ACK"; private const string BeginMessage = "W2PS_110_BEGIN"; private const string ChunkMessage = "W2PS_110_CHUNK"; private const string AssignmentMessage = "W2PS_110_ASSIGN"; private static readonly Dictionary<ulong, ulong> FramePhotos = new Dictionary<ulong, ulong>(); private static readonly Dictionary<ulong, byte[]> RemotePhotos = new Dictionary<ulong, byte[]>(); private static readonly Dictionary<ulong, Texture2D> Textures = new Dictionary<ulong, Texture2D>(); private static readonly Dictionary<ulong, ReceiveState> Receiving = new Dictionary<ulong, ReceiveState>(); private static readonly HashSet<ulong> ReadyClients = new HashSet<ulong>(); private static readonly Dictionary<ulong, HashSet<ulong>> SentPhotos = new Dictionary<ulong, HashSet<ulong>>(); private static NetworkManager _manager; private static bool _serverAcknowledged; private static float _nextHelloTime; internal static void Tick() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening) { if ((Object)(object)_manager != (Object)null) { Detach(); } return; } if ((Object)(object)_manager != (Object)(object)singleton) { Attach(singleton); } if ((Object)(object)_manager != (Object)null && _manager.IsClient && !_manager.IsServer && _manager.IsConnectedClient && !_serverAcknowledged && Time.realtimeSinceStartup >= _nextHelloTime) { SendHello(); _nextHelloTime = Time.realtimeSinceStartup + 3f; } } private static void Attach(NetworkManager manager) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown Detach(); _manager = manager; ClearSessionState(); CustomMessagingManager customMessagingManager = manager.CustomMessagingManager; customMessagingManager.RegisterNamedMessageHandler("W2PS_110_HELLO", new HandleNamedMessageDelegate(HandleHello)); customMessagingManager.RegisterNamedMessageHandler("W2PS_110_ACK", new HandleNamedMessageDelegate(HandleAcknowledge)); customMessagingManager.RegisterNamedMessageHandler("W2PS_110_BEGIN", new HandleNamedMessageDelegate(HandleBegin)); customMessagingManager.RegisterNamedMessageHandler("W2PS_110_CHUNK", new HandleNamedMessageDelegate(HandleChunk)); customMessagingManager.RegisterNamedMessageHandler("W2PS_110_ASSIGN", new HandleNamedMessageDelegate(HandleAssignment)); manager.OnClientConnectedCallback += HandleClientConnected; manager.OnClientDisconnectCallback += HandleClientDisconnected; if (manager.IsServer) { PhotoLibrary.EnsureLoaded(); } if (manager.IsClient && !manager.IsServer && manager.IsConnectedClient) { SendHello(); } } private static void Detach() { if ((Object)(object)_manager != (Object)null) { try { CustomMessagingManager customMessagingManager = _manager.CustomMessagingManager; if (customMessagingManager != null) { customMessagingManager.UnregisterNamedMessageHandler("W2PS_110_HELLO"); customMessagingManager.UnregisterNamedMessageHandler("W2PS_110_ACK"); customMessagingManager.UnregisterNamedMessageHandler("W2PS_110_BEGIN"); customMessagingManager.UnregisterNamedMessageHandler("W2PS_110_CHUNK"); customMessagingManager.UnregisterNamedMessageHandler("W2PS_110_ASSIGN"); } _manager.OnClientConnectedCallback -= HandleClientConnected; _manager.OnClientDisconnectCallback -= HandleClientDisconnected; } catch { } } _manager = null; ClearSessionState(); } private static void ClearSessionState() { FramePhotos.Clear(); RemotePhotos.Clear(); Receiving.Clear(); ReadyClients.Clear(); SentPhotos.Clear(); foreach (Texture2D value in Textures.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } Textures.Clear(); PhotoAssignment.ResetSession(); _serverAcknowledged = false; _nextHelloTime = 0f; } internal static void Shutdown() { Detach(); } private static void HandleClientConnected(ulong clientId) { if (!((Object)(object)_manager == (Object)null)) { if (_manager.IsServer && clientId != _manager.LocalClientId) { SentPhotos[clientId] = new HashSet<ulong>(); } if (_manager.IsClient && !_manager.IsServer && clientId == _manager.LocalClientId) { SendHello(); } } } private static void HandleClientDisconnected(ulong clientId) { ReadyClients.Remove(clientId); SentPhotos.Remove(clientId); if ((Object)(object)_manager != (Object)null && clientId == _manager.LocalClientId) { _serverAcknowledged = false; } } private static void SendHello() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_manager == (Object)null || !_manager.IsClient || _manager.IsServer || !_manager.IsConnectedClient) { return; } FastBufferWriter writer = new FastBufferWriter(4, (Allocator)2, 4); try { WriteInt32(ref writer, 2); _manager.CustomMessagingManager.SendNamedMessage("W2PS_110_HELLO", 0uL, writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void HandleHello(ulong senderClientId, FastBufferReader reader) { if ((Object)(object)_manager == (Object)null || !_manager.IsServer || ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position < 4) { return; } int num = ReadInt32(ref reader); if (num != 2) { PhotoScrapPlugin.Log.LogWarning((object)("Client " + senderClientId + " uses an incompatible PhotoScrap protocol.")); return; } ReadyClients.Add(senderClientId); if (!SentPhotos.ContainsKey(senderClientId)) { SentPhotos[senderClientId] = new HashSet<ulong>(); } SendAcknowledge(senderClientId); SendAllState(senderClientId); } private static void SendAcknowledge(ulong clientId) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter writer = new FastBufferWriter(4, (Allocator)2, 4); try { WriteInt32(ref writer, 2); _manager.CustomMessagingManager.SendNamedMessage("W2PS_110_ACK", clientId, writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void HandleAcknowledge(ulong senderClientId, FastBufferReader reader) { if (!((Object)(object)_manager == (Object)null) && _manager.IsClient && !_manager.IsServer && senderClientId == 0 && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position >= 4) { int num = ReadInt32(ref reader); if (num == 2) { _serverAcknowledged = true; } } } internal static void AssignFrame(ulong networkObjectId, ulong photoId) { FramePhotos[networkObjectId] = photoId; RefreshFrame(networkObjectId); if (!((Object)(object)_manager == (Object)null) && _manager.IsServer) { ulong[] array = ReadyClients.ToArray(); for (int i = 0; i < array.Length; i++) { SendStateForFrame(array[i], networkObjectId, photoId); } } } private static void SendAllState(ulong clientId) { KeyValuePair<ulong, ulong>[] array = FramePhotos.ToArray(); for (int i = 0; i < array.Length; i++) { SendStateForFrame(clientId, array[i].Key, array[i].Value); } } private static void SendStateForFrame(ulong clientId, ulong networkObjectId, ulong photoId) { if (ReadyClients.Contains(clientId) && !((Object)(object)_manager == (Object)null) && _manager.IsServer) { if (photoId != 0) { SendPhotoIfNeeded(clientId, photoId); } SendAssignment(clientId, networkObjectId, photoId); } } private static void SendPhotoIfNeeded(ulong clientId, ulong photoId) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) if (!SentPhotos.TryGetValue(clientId, out var value)) { value = new HashSet<ulong>(); SentPhotos[clientId] = value; } if (value.Contains(photoId) || !PhotoLibrary.TryGetRecord(photoId, out var record) || record.JpegBytes == null) { return; } byte[] jpegBytes = record.JpegBytes; if (jpegBytes.Length <= 0 || jpegBytes.Length > 524288) { return; } FastBufferWriter writer = new FastBufferWriter(12, (Allocator)2, 12); try { WriteUInt64(ref writer, photoId); WriteInt32(ref writer, jpegBytes.Length); _manager.CustomMessagingManager.SendNamedMessage("W2PS_110_BEGIN", clientId, writer, (NetworkDelivery)4); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } int num; for (int i = 0; i < jpegBytes.Length; i += num) { num = Math.Min(12288, jpegBytes.Length - i); int num2 = 16 + num; FastBufferWriter writer2 = new FastBufferWriter(num2, (Allocator)2, num2); try { WriteUInt64(ref writer2, photoId); WriteInt32(ref writer2, i); WriteInt32(ref writer2, num); for (int j = 0; j < num; j++) { ((FastBufferWriter)(ref writer2)).WriteByteSafe(jpegBytes[i + j]); } _manager.CustomMessagingManager.SendNamedMessage("W2PS_110_CHUNK", clientId, writer2, (NetworkDelivery)4); } finally { ((FastBufferWriter)(ref writer2)).Dispose(); } } value.Add(photoId); } private static void SendAssignment(ulong clientId, ulong networkObjectId, ulong photoId) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter writer = new FastBufferWriter(16, (Allocator)2, 16); try { WriteUInt64(ref writer, networkObjectId); WriteUInt64(ref writer, photoId); _manager.CustomMessagingManager.SendNamedMessage("W2PS_110_ASSIGN", clientId, writer, (NetworkDelivery)4); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void HandleBegin(ulong senderClientId, FastBufferReader reader) { if (IsValidServerMessage(senderClientId) && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position >= 12) { ulong num = ReadUInt64(ref reader); int num2 = ReadInt32(ref reader); if (num != 0 && num2 > 0 && num2 <= 524288) { ReceiveState receiveState = new ReceiveState(); receiveState.Buffer = new byte[num2]; receiveState.NextOffset = 0; Receiving[num] = receiveState; } } } private static void HandleChunk(ulong senderClientId, FastBufferReader reader) { if (!IsValidServerMessage(senderClientId) || ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position < 16) { return; } ulong num = ReadUInt64(ref reader); int num2 = ReadInt32(ref reader); int num3 = ReadInt32(ref reader); if (!Receiving.TryGetValue(num, out var value) || num3 <= 0 || num3 > 12288 || num2 != value.NextOffset || num2 < 0 || num2 + num3 > value.Buffer.Length || ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position < num3) { Receiving.Remove(num); return; } byte[] array = new byte[num3]; for (int i = 0; i < num3; i++) { ((FastBufferReader)(ref reader)).ReadByteSafe(ref array[i]); } Buffer.BlockCopy(array, 0, value.Buffer, num2, num3); value.NextOffset += num3; if (value.NextOffset == value.Buffer.Length) { Receiving.Remove(num); if (PhotoLibrary.ComputeId(value.Buffer) != num) { PhotoScrapPlugin.Log.LogWarning((object)"Rejected a photo with an invalid network hash."); return; } if (!PhotoLibrary.TryReadJpegDimensions(value.Buffer, out var _, out var _)) { PhotoScrapPlugin.Log.LogWarning((object)"Rejected invalid JPEG data from the host."); return; } RemotePhotos[num] = value.Buffer; RefreshFramesUsingPhoto(num); } } private static void HandleAssignment(ulong senderClientId, FastBufferReader reader) { if (IsValidServerMessage(senderClientId) && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position >= 16) { ulong num = ReadUInt64(ref reader); ulong value = ReadUInt64(ref reader); FramePhotos[num] = value; RefreshFrame(num); } } private static bool IsValidServerMessage(ulong senderClientId) { if ((Object)(object)_manager != (Object)null && _manager.IsClient && !_manager.IsServer) { return senderClientId == 0; } return false; } internal static bool TryGetFramePhotoId(ulong networkObjectId, out ulong photoId) { return FramePhotos.TryGetValue(networkObjectId, out photoId); } internal static Texture2D GetTexture(ulong photoId) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown if (photoId == 0) { return PhotoScrapPlugin.PlaceholderTexture; } if (Textures.TryGetValue(photoId, out var value) && (Object)(object)value != (Object)null) { return value; } byte[] value2 = null; if (PhotoLibrary.TryGetRecord(photoId, out var record)) { value2 = record.JpegBytes; } else { RemotePhotos.TryGetValue(photoId, out value2); } if (value2 == null) { return PhotoScrapPlugin.PlaceholderTexture; } Texture2D val = new Texture2D(2, 2, (TextureFormat)3, false); ((Object)val).name = "PhotoScrap_NetworkPhoto_" + photoId.ToString("X16"); if (!ImageConversion.LoadImage(val, value2, true)) { Object.Destroy((Object)(object)val); return PhotoScrapPlugin.PlaceholderTexture; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; Textures[photoId] = val; return val; } private static void RefreshFrame(ulong networkObjectId) { PhotoFrameItem[] array = Object.FindObjectsOfType<PhotoFrameItem>(); for (int i = 0; i < array.Length; i++) { if (((NetworkBehaviour)array[i]).IsSpawned && ((NetworkBehaviour)array[i]).NetworkObjectId == networkObjectId) { array[i].RefreshPhoto(); } } } private static void RefreshFramesUsingPhoto(ulong photoId) { ulong[] array = (from pair in FramePhotos where pair.Value == photoId select pair.Key).ToArray(); for (int num = 0; num < array.Length; num++) { RefreshFrame(array[num]); } } internal static void ForgetFrame(ulong networkObjectId) { FramePhotos.Remove(networkObjectId); } private static void WriteInt32(ref FastBufferWriter writer, int value) { ((FastBufferWriter)(ref writer)).WriteByteSafe((byte)value); ((FastBufferWriter)(ref writer)).WriteByteSafe((byte)(value >> 8)); ((FastBufferWriter)(ref writer)).WriteByteSafe((byte)(value >> 16)); ((FastBufferWriter)(ref writer)).WriteByteSafe((byte)(value >> 24)); } private static int ReadInt32(ref FastBufferReader reader) { byte b = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b); byte b2 = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b2); byte b3 = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b3); byte b4 = default(byte); ((FastBufferReader)(ref reader)).ReadByteSafe(ref b4); return b | (b2 << 8) | (b3 << 16) | (b4 << 24); } private static void WriteUInt64(ref FastBufferWriter writer, ulong value) { for (int i = 0; i < 64; i += 8) { ((FastBufferWriter)(ref writer)).WriteByteSafe((byte)(value >> i)); } } private static ulong ReadUInt64(ref FastBufferReader reader) { ulong num = 0uL; byte b = default(byte); for (int i = 0; i < 64; i += 8) { ((FastBufferReader)(ref reader)).ReadByteSafe(ref b); num |= (ulong)b << i; } return num; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("wang2.photoscrap", "PhotoScrap", "1.1.0")] public sealed class PhotoScrapPlugin : BaseUnityPlugin { public const string PluginGuid = "wang2.photoscrap"; public const string PluginName = "PhotoScrap"; public const string PluginVersion = "1.1.0"; public const int MinimumValue = 80; public const int MaximumValue = 140; internal static PhotoScrapPlugin Instance; internal static ManualLogSource Log; internal static Material PhotoMaterialTemplate; internal static Material FrameMaterial; internal static Material BackMaterial; internal static Texture2D PlaceholderTexture; private ConfigEntry<int> _spawnWeight; private void Awake() { //IL_013b: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; string text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "PhotoScrap"); _spawnWeight = ((BaseUnityPlugin)this).Config.Bind<int>("Spawn", "Rarity", 65, "Relative spawn weight on all moons. 65 aims for a fairly common one or two frames per round."); ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("Photos", "Folder", text, "Folder read only when this player is the host. Restart the game after changing photos."); ConfigEntry<int> val2 = ((BaseUnityPlugin)this).Config.Bind<int>("Photos", "MaximumDimension", 1024, "Maximum width or height after compression (256-2048)."); ConfigEntry<int> val3 = ((BaseUnityPlugin)this).Config.Bind<int>("Photos", "JpegQuality", 82, "JPEG compression quality (55-95)."); ConfigEntry<int> val4 = ((BaseUnityPlugin)this).Config.Bind<int>("Photos", "MaximumPhotos", 64, "Maximum number of files read from the host photo folder (1-128)."); ConfigEntry<int> val5 = ((BaseUnityPlugin)this).Config.Bind<int>("Photos", "MaximumInputMegabytes", 20, "Maximum size of one source image in MiB (1-100)."); PhotoLibrary.Configure(val.Value, Mathf.Clamp(val2.Value, 256, 2048), Mathf.Clamp(val3.Value, 55, 95), Mathf.Clamp(val4.Value, 1, 128), Mathf.Clamp(val5.Value, 1, 100)); try { CreateMaterials(); RegisterPhotoScrap(); new Harmony("wang2.photoscrap").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("PhotoScrap 1.1.0 loaded. Host photos will be read from: " + val.Value)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("PhotoScrap failed to initialize: " + ex)); } } private void Update() { PhotoNetwork.Tick(); } private void OnDestroy() { PhotoNetwork.Shutdown(); PhotoLibrary.Shutdown(); } private static Shader FindShader(params string[] names) { for (int i = 0; i < names.Length; i++) { Shader val = Shader.Find(names[i]); if ((Object)(object)val != (Object)null) { return val; } } throw new InvalidOperationException("No compatible material shader was found."); } private void CreateMaterials() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) Shader val = FindShader("HDRP/Lit", "Standard"); Shader val2 = FindShader("HDRP/Unlit", "Unlit/Texture", "Standard"); FrameMaterial = new Material(val); ((Object)FrameMaterial).name = "PhotoScrap_AgedIron"; SetMaterialColor(FrameMaterial, new Color(0.16f, 0.105f, 0.075f, 1f)); SetMaterialFloat(FrameMaterial, "_Metallic", 0.62f); SetMaterialFloat(FrameMaterial, "_Smoothness", 0.22f); BackMaterial = new Material(val); ((Object)BackMaterial).name = "PhotoScrap_OldBacking"; SetMaterialColor(BackMaterial, new Color(0.055f, 0.045f, 0.04f, 1f)); SetMaterialFloat(BackMaterial, "_Metallic", 0.12f); SetMaterialFloat(BackMaterial, "_Smoothness", 0.08f); PlaceholderTexture = CreatePlaceholderTexture(); PhotoMaterialTemplate = new Material(val2); ((Object)PhotoMaterialTemplate).name = "PhotoScrap_PhotoTemplate"; SetMaterialColor(PhotoMaterialTemplate, Color.white); SetMaterialTexture(PhotoMaterialTemplate, (Texture)(object)PlaceholderTexture); } private static Texture2D CreatePlaceholderTexture() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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) Texture2D val = new Texture2D(64, 64, (TextureFormat)3, false); ((Object)val).name = "PhotoScrap_Placeholder"; Color32[] array = (Color32[])(object)new Color32[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { bool flag = j < 5 || i < 5 || j >= 59 || i >= 59; bool flag2 = Math.Abs(j - i) < 3 || Math.Abs(63 - j - i) < 3; ref Color32 reference = ref array[i * 64 + j]; reference = (flag ? new Color32((byte)82, (byte)55, (byte)40, byte.MaxValue) : (flag2 ? new Color32((byte)102, (byte)92, (byte)76, byte.MaxValue) : new Color32((byte)42, (byte)39, (byte)35, byte.MaxValue))); } } val.SetPixels32(array); val.Apply(false, true); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return val; } private static void SetMaterialColor(Material material, Color color) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", color); } if (material.HasProperty("_UnlitColor")) { material.SetColor("_UnlitColor", color); } } private static void SetMaterialFloat(Material material, string property, float value) { if (material.HasProperty(property)) { material.SetFloat(property, value); } } internal static void SetMaterialTexture(Material material, Texture texture) { material.mainTexture = texture; if (material.HasProperty("_BaseColorMap")) { material.SetTexture("_BaseColorMap", texture); } if (material.HasProperty("_UnlitColorMap")) { material.SetTexture("_UnlitColorMap", texture); } } private void RegisterPhotoScrap() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Expected O, but got Unknown Item val = ScriptableObject.CreateInstance<Item>(); ((Object)val).name = "PhotoScrapItem"; val.itemName = "旧日合影"; val.itemId = 9251201; val.isScrap = true; val.minValue = 80; val.maxValue = 140; val.weight = 1.08f; val.twoHanded = false; val.twoHandedAnimation = false; val.canBeGrabbedBeforeGameStart = true; val.itemSpawnsOnGround = true; val.isConductiveMetal = true; val.requiresBattery = false; val.grabAnimationTime = 0.4f; val.saveItemVariable = true; val.allowDroppingAheadOfPlayer = true; val.positionOffset = new Vector3(0.08f, 0.02f, 0.18f); val.rotationOffset = new Vector3(0f, 90f, 95f); val.restingRotation = new Vector3(0f, 0f, 90f); val.verticalOffset = 0.06f; val.toolTips = new string[0]; Item val2 = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item candidate) => (Object)(object)candidate != (Object)null && (Object)(object)candidate.grabSFX != (Object)null && (Object)(object)candidate.dropSFX != (Object)null)); if ((Object)(object)val2 != (Object)null) { val.grabSFX = val2.grabSFX; val.dropSFX = val2.dropSFX; val.pocketSFX = val2.pocketSFX; val.throwSFX = val2.throwSFX; val.clinkAudios = val2.clinkAudios; } GameObject val3 = NetworkPrefabs.CreateNetworkPrefab("Wang2_PhotoScrap_Prefab"); val3.layer = 6; Rigidbody val4 = val3.AddComponent<Rigidbody>(); val4.mass = 1.15f; val4.drag = 0.08f; val4.angularDrag = 0.08f; BoxCollider val5 = val3.AddComponent<BoxCollider>(); val5.size = new Vector3(0.84f, 0.58f, 0.09f); PhotoFrameItem photoFrameItem = val3.AddComponent<PhotoFrameItem>(); ((GrabbableObject)photoFrameItem).itemProperties = val; ((GrabbableObject)photoFrameItem).grabbable = true; ((GrabbableObject)photoFrameItem).grabbableToEnemies = true; ((GrabbableObject)photoFrameItem).propBody = val4; ((GrabbableObject)photoFrameItem).propColliders = (Collider[])(object)new Collider[1] { (Collider)val5 }; photoFrameItem.FrameCollider = val5; Transform transform = new GameObject("PhotoFrameVisuals").transform; transform.SetParent(val3.transform, false); photoFrameItem.Backing = CreateBox("Backing", transform, BackMaterial); photoFrameItem.PhotoSurface = CreateBox("Photo", transform, PhotoMaterialTemplate); photoFrameItem.TopBorder = CreateBox("TopBorder", transform, FrameMaterial); photoFrameItem.BottomBorder = CreateBox("BottomBorder", transform, FrameMaterial); photoFrameItem.LeftBorder = CreateBox("LeftBorder", transform, FrameMaterial); photoFrameItem.RightBorder = CreateBox("RightBorder", transform, FrameMaterial); ((GrabbableObject)photoFrameItem).mainObjectRenderer = photoFrameItem.Backing.GetComponent<MeshRenderer>(); GameObject val6 = new GameObject("ScanNode"); val6.layer = 22; val6.transform.SetParent(val3.transform, false); ScanNodeProperties val7 = val6.AddComponent<ScanNodeProperties>(); val7.headerText = "旧日合影"; val7.subText = "价值:"; val7.nodeType = 2; val7.minRange = 1; val7.maxRange = 13; val7.requiresLineOfSight = true; photoFrameItem.ScanNode = val7; val.spawnPrefab = val3; NetworkPrefabs.RegisterNetworkPrefab(val3); Items.RegisterScrap(val, Mathf.Clamp(_spawnWeight.Value, 0, 999), (LevelTypes)(-1)); } private static GameObject CreateBox(string name, Transform parent, Material material) { GameObject val = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)val).name = name; val.layer = 6; val.transform.SetParent(parent, false); Collider component = val.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } ((Renderer)val.GetComponent<MeshRenderer>()).sharedMaterial = material; return val; } }