using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
[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("GraffitiMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GraffitiMod")]
[assembly: AssemblyTitle("GraffitiMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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;
}
}
}
namespace SprayMod
{
[BepInPlugin("IvitoDev.SprayMod", "Spray Mod", "1.1.0")]
public class SprayMod : BaseUnityPlugin, IOnEventCallback, IInRoomCallbacks
{
[CompilerGenerated]
private sealed class <LoadSelectedSprayCoroutine>d__35 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public SprayMod <>4__this;
private string <path>5__1;
private byte[] <data>5__2;
private Exception <ex>5__3;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadSelectedSprayCoroutine>d__35(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<path>5__1 = null;
<data>5__2 = null;
<ex>5__3 = null;
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
try
{
<path>5__1 = Path.Combine(<>4__this.imagesFolderPath, <>4__this.selectedImageName);
if (!File.Exists(<path>5__1))
{
Logger.LogWarning((object)("Spray image not found: " + <>4__this.selectedImageName));
return false;
}
<data>5__2 = File.ReadAllBytes(<path>5__1);
<>4__this.sprayTexture = <>4__this.LoadAndResizeImage(<data>5__2);
if ((Object)(object)<>4__this.sprayTexture != (Object)null)
{
Logger.LogInfo((object)("Spray image loaded: " + <>4__this.selectedImageName));
}
else
{
Logger.LogError((object)"Spray image is invalid and could not be loaded.");
}
<path>5__1 = null;
<data>5__2 = null;
}
catch (Exception ex)
{
<ex>5__3 = ex;
Logger.LogError((object)("Failed to load spray texture: " + <ex>5__3.Message));
}
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private Texture2D sprayTexture = null;
private string selectedImageName = string.Empty;
private ConfigEntry<string> sprayImageEntry = null;
private ConfigEntry<bool> openFolderFlag = null;
private ConfigEntry<bool> refreshFlag = null;
private string imagesFolderPath = null;
private string[] availableImages = Array.Empty<string>();
private float cooldownTime = 10f;
private float lastSprayTime = -999f;
private bool registeredCallbacks = false;
internal static SprayMod Instance { get; private set; }
internal static ManualLogSource Logger => Instance._logger;
private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;
private void Awake()
{
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Expected O, but got Unknown
Instance = this;
((Component)this).gameObject.transform.parent = null;
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
imagesFolderPath = Path.Combine(directoryName, "Images");
Logger.LogInfo((object)("Spray Mod initialized at: " + directoryName));
if (!Directory.Exists(imagesFolderPath))
{
Logger.LogWarning((object)("Spray folder not found: " + imagesFolderPath));
}
UpdateImageList();
InitConfigEntries();
Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
val.PatchAll();
}
private void Update()
{
if (!registeredCallbacks && PhotonNetwork.InRoom)
{
PhotonNetwork.AddCallbackTarget((object)this);
registeredCallbacks = true;
Logger.LogInfo((object)"[SprayMod] Registered Photon callbacks.");
}
if (Input.GetKeyDown((KeyCode)121) && (Object)(object)sprayTexture != (Object)null)
{
TryPlaceSpray();
}
if (openFolderFlag.Value)
{
OpenImagesFolder();
openFolderFlag.Value = false;
}
if (refreshFlag.Value)
{
RefreshImagesManually();
refreshFlag.Value = false;
}
}
private void OnDestroy()
{
if (registeredCallbacks)
{
PhotonNetwork.RemoveCallbackTarget((object)this);
}
}
public void OnJoinedRoom()
{
Logger.LogInfo((object)"[SprayMod] Joined Photon room. Ready to receive events.");
}
public void OnLeftRoom()
{
Logger.LogInfo((object)"[SprayMod] Left Photon room. Stopping event reception.");
}
public void OnPlayerEnteredRoom(Player newPlayer)
{
}
public void OnPlayerLeftRoom(Player otherPlayer)
{
}
public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
{
}
public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
{
}
public void OnMasterClientSwitched(Player newMasterClient)
{
}
public void OnEvent(EventData photonEvent)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: 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_009a: Unknown result type (might be due to invalid IL or missing references)
if (photonEvent.Code != 42)
{
return;
}
object[] array = (object[])photonEvent.CustomData;
byte[] buffer = (byte[])array[0];
Vector3 position = (Vector3)array[1];
Quaternion rotation = (Quaternion)array[2];
try
{
using MemoryStream stream = new MemoryStream(buffer);
using GZipStream gZipStream = new GZipStream(stream, CompressionMode.Decompress);
using MemoryStream memoryStream = new MemoryStream();
gZipStream.CopyTo(memoryStream);
byte[] data = memoryStream.ToArray();
Texture2D val = LoadAndResizeImage(data);
if ((Object)(object)val == (Object)null)
{
Logger.LogError((object)"[SprayMod] Received image is invalid.");
return;
}
PlaceSpray(position, rotation, val);
Logger.LogInfo((object)"Spray received and placed.");
}
catch (Exception ex)
{
Logger.LogError((object)("Error decompressing or processing spray: " + ex.Message));
}
}
private void Start()
{
selectedImageName = sprayImageEntry.Value;
((MonoBehaviour)this).StartCoroutine(LoadSelectedSprayCoroutine());
}
private void InitConfigEntries()
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Expected O, but got Unknown
string text = availableImages.FirstOrDefault() ?? "";
sprayImageEntry = ((BaseUnityPlugin)this).Config.Bind<string>("Spray", "Image", text, new ConfigDescription("Select the spray image (PNG or JPG).", (AcceptableValueBase)(object)new AcceptableValueList<string>(availableImages), Array.Empty<object>()));
sprayImageEntry.SettingChanged += delegate
{
selectedImageName = sprayImageEntry.Value;
((MonoBehaviour)this).StartCoroutine(LoadSelectedSprayCoroutine());
};
openFolderFlag = ((BaseUnityPlugin)this).Config.Bind<bool>("Spray", "Open Spray Folder", false, "Turn ON to open the spray folder. It will turn OFF automatically.");
refreshFlag = ((BaseUnityPlugin)this).Config.Bind<bool>("Spray", "Refresh Spray List", false, "Turn ON to refresh image list. Then close and reopen this menu to update the dropdown.");
}
private void OpenImagesFolder()
{
Logger.LogInfo((object)"Opening spray image folder...");
try
{
Application.OpenURL(imagesFolderPath);
}
catch (Exception ex)
{
Logger.LogError((object)("Could not open folder: " + ex.Message));
}
}
private void RefreshImagesManually()
{
Logger.LogInfo((object)"Refreshing spray image list...");
UpdateImageList();
UpdateSprayConfigEntry();
}
private void UpdateImageList()
{
try
{
availableImages = (from f in Directory.GetFiles(imagesFolderPath)
where f.EndsWith(".png") || f.EndsWith(".jpg")
select f).Select(Path.GetFileName).ToArray();
Logger.LogInfo((object)$"Found {availableImages.Length} spray image(s).");
}
catch (Exception ex)
{
Logger.LogError((object)("Error reading spray folder: " + ex.Message));
}
}
private void UpdateSprayConfigEntry()
{
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
string text = sprayImageEntry.Value;
string text2 = availableImages.FirstOrDefault() ?? "";
if (!availableImages.Contains(text))
{
text = text2;
}
ConfigDefinition definition = ((ConfigEntryBase)sprayImageEntry).Definition;
((BaseUnityPlugin)this).Config.Remove(definition);
sprayImageEntry = ((BaseUnityPlugin)this).Config.Bind<string>(definition.Section, definition.Key, text, new ConfigDescription("Select the spray image (PNG or JPG).", (AcceptableValueBase)(object)new AcceptableValueList<string>(availableImages), Array.Empty<object>()));
sprayImageEntry.SettingChanged += delegate
{
selectedImageName = sprayImageEntry.Value;
((MonoBehaviour)this).StartCoroutine(LoadSelectedSprayCoroutine());
};
}
[IteratorStateMachine(typeof(<LoadSelectedSprayCoroutine>d__35))]
private IEnumerator LoadSelectedSprayCoroutine()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadSelectedSprayCoroutine>d__35(0)
{
<>4__this = this
};
}
private Texture2D LoadAndResizeImage(byte[] data)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
try
{
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
if (!ImageConversion.LoadImage(val, data, false))
{
return null;
}
if (((Texture)val).width == 0 || ((Texture)val).height == 0 || val.GetPixels().All((Color c) => c.a == 0f))
{
return null;
}
return ResizeIfTooLarge(val);
}
catch (Exception ex)
{
Logger.LogError((object)("Image decoding failed: " + ex.Message));
return null;
}
}
private Texture2D ResizeIfTooLarge(Texture2D original)
{
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
if (((Texture)original).width <= 1024 && ((Texture)original).height <= 1024)
{
return original;
}
float num = Math.Min(1024f / (float)((Texture)original).width, 1024f / (float)((Texture)original).height);
int num2 = Mathf.RoundToInt((float)((Texture)original).width * num);
int num3 = Mathf.RoundToInt((float)((Texture)original).height * num);
try
{
RenderTexture temporary = RenderTexture.GetTemporary(num2, num3);
Graphics.Blit((Texture)(object)original, temporary);
RenderTexture.active = temporary;
Texture2D val = new Texture2D(num2, num3, (TextureFormat)4, false);
val.ReadPixels(new Rect(0f, 0f, (float)num2, (float)num3), 0, 0);
val.Apply();
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(temporary);
return val;
}
catch (Exception ex)
{
Logger.LogError((object)("Image resizing failed: " + ex.Message));
return null;
}
}
private void TryPlaceSpray()
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Expected O, but got Unknown
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: 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_01db: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Expected O, but got Unknown
if (Time.time - lastSprayTime < cooldownTime)
{
Logger.LogWarning((object)"Spray is on cooldown.");
return;
}
Camera main = Camera.main;
if ((Object)(object)main == (Object)null)
{
return;
}
Ray val = main.ViewportPointToRay(new Vector3(0.5f, 0.5f));
RaycastHit val2 = default(RaycastHit);
if (Physics.Raycast(val, ref val2, 3f))
{
if ((Object)(object)sprayTexture == (Object)null || ((Texture)sprayTexture).width == 0 || ((Texture)sprayTexture).height == 0)
{
Logger.LogWarning((object)"Spray texture is invalid or null, skipping placement.");
return;
}
PlaceSpray(((RaycastHit)(ref val2)).point, Quaternion.LookRotation(-((RaycastHit)(ref val2)).normal, Vector3.up), sprayTexture);
if (PhotonNetwork.InRoom)
{
try
{
Texture2D val3 = new Texture2D(((Texture)sprayTexture).width, ((Texture)sprayTexture).height, (TextureFormat)4, false);
val3.SetPixels(sprayTexture.GetPixels());
val3.Apply();
byte[] array = ImageConversion.EncodeToPNG(val3);
if (array == null || array.Length == 0 || !ValidatePngData(array))
{
Logger.LogWarning((object)"Failed to encode or validate spray image.");
return;
}
byte[] array2 = CompressImage(array);
if (array2.Length > 250000)
{
Logger.LogWarning((object)"Spray image too large to send after compression.");
return;
}
object[] array3 = new object[3]
{
array2,
((RaycastHit)(ref val2)).point,
Quaternion.LookRotation(-((RaycastHit)(ref val2)).normal, Vector3.up)
};
PhotonNetwork.RaiseEvent((byte)42, (object)array3, new RaiseEventOptions
{
Receivers = (ReceiverGroup)0
}, SendOptions.SendReliable);
}
catch (Exception ex)
{
Logger.LogError((object)("Error sending spray image: " + ex.Message));
}
}
lastSprayTime = Time.time;
}
else
{
Logger.LogWarning((object)"No valid surface found to place spray.");
}
}
private bool ValidatePngData(byte[] data)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Expected O, but got Unknown
try
{
Texture2D val = new Texture2D(2, 2);
return ImageConversion.LoadImage(val, data, true);
}
catch (Exception ex)
{
Logger.LogError((object)("Image validation failed: " + ex.Message));
return false;
}
}
private void PlaceSpray(Vector3 position, Quaternion rotation, Texture2D texture)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: 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_00a2: Expected O, but got Unknown
GameObject val = GameObject.CreatePrimitive((PrimitiveType)5);
((Object)val).name = "SprayMod_Instance";
val.transform.position = position + rotation * Vector3.forward * 0.01f;
val.transform.rotation = rotation;
val.transform.localScale = new Vector3(1.2f, 1.2f, 1f);
val.transform.parent = null;
((Object)val).hideFlags = (HideFlags)61;
Object.Destroy((Object)(object)val.GetComponent<Collider>());
Material material = new Material(Shader.Find("Sprites/Default"))
{
mainTexture = (Texture)(object)texture
};
val.GetComponent<Renderer>().material = material;
Object.Destroy((Object)(object)val, 30f);
}
private byte[] CompressImage(byte[] data)
{
using MemoryStream memoryStream = new MemoryStream();
using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Compress))
{
gZipStream.Write(data, 0, data.Length);
}
return memoryStream.ToArray();
}
}
}