Decompiled source of BetterSprayPaint v2.0.9
BepInEx/plugins/BetterSprayPaint.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BetterSprayPaint; using BetterSprayPaint.NetcodePatcher; using BetterSprayPaint.Ngo; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: AssemblyCompany("BetterSprayPaint")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.9.0")] [assembly: AssemblyInformationalVersion("2.0.9+67b14332f2c2ee64549a66c724edce78e6201b2c")] [assembly: AssemblyProduct("BetterSprayPaint")] [assembly: AssemblyTitle("BetterSprayPaint")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.9.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] internal class <Module> { static <Module>() { NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<float>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<float>(); NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>(); NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<Color>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<Color>(); NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedINetworkSerializable<NetworkObjectReference>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<NetworkObjectReference>(); } } 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 QuietLogSource : ILogSource, IDisposable { private ManualLogSource innerLog; private static readonly TimeSpan baseRecentLogTimeout = TimeSpan.FromMilliseconds(5000.0); private Dictionary<string, (DateTime, int)> recentLogs = new Dictionary<string, (DateTime, int)>(); private int logsSuppressed; private int lastReportedLogsSuppressed; private bool suppressLogs = true; private const int minimumBeforeSuppressal = 5; public string SourceName { get; } public event EventHandler<LogEventArgs> LogEvent { add { innerLog.LogEvent += value; } remove { innerLog.LogEvent -= value; } } public QuietLogSource(string sourceName) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown innerLog = new ManualLogSource(sourceName); SourceName = sourceName; } public void Dispose() { innerLog.Dispose(); } private object AddStackTrace(object data) { if (data is string arg) { StackTrace arg2 = new StackTrace(3, fNeedFileInfo: true); return $"{arg}\n{arg2}"; } return data; } public void Log(LogLevel level, object data, bool addStackTrace = false) { //IL_014e: Unknown result type (might be due to invalid IL or missing references) if (recentLogs.Count > 30) { KeyValuePair<string, (DateTime, int)>[] array = recentLogs.Where<KeyValuePair<string, (DateTime, int)>>((KeyValuePair<string, (DateTime, int)> kvp) => DateTime.UtcNow - kvp.Value.Item1 > baseRecentLogTimeout).ToArray(); foreach (KeyValuePair<string, (DateTime, int)> keyValuePair in array) { recentLogs.Remove(keyValuePair.Key); } } if (data is string key) { if (recentLogs.TryGetValue(key, out var value)) { TimeSpan timeSpan = ((value.Item2 < 100) ? baseRecentLogTimeout : (baseRecentLogTimeout * 2.0)); if (DateTime.UtcNow - value.Item1 > timeSpan) { recentLogs[key] = (DateTime.UtcNow, (value.Item2 > 5) ? 5 : 0); } else { recentLogs[key] = (value.Item1, value.Item2 + 1); if (value.Item2 >= 5) { logsSuppressed++; if (suppressLogs) { return; } } } } else { recentLogs.Add(key, (DateTime.UtcNow, 0)); } } innerLog.Log(level, addStackTrace ? AddStackTrace(data) : data); if (suppressLogs && logsSuppressed > lastReportedLogsSuppressed) { innerLog.LogInfo((object)$"{logsSuppressed - lastReportedLogsSuppressed} duplicate logs suppressed"); lastReportedLogsSuppressed = logsSuppressed; } } public void LogInfo(object data) { Log((LogLevel)16, data); } public void LogError(object data, bool addStackTrace = true) { Log((LogLevel)2, data, addStackTrace); } public void LogWarning(object data, bool addStackTrace = true) { Log((LogLevel)4, data, addStackTrace); } public void LogLoud(string data) { for (int i = 0; i < 25; i++) { Log((LogLevel)16, $"{data} ({i})"); } } } internal interface INetVar : IDisposable { void Synchronize(); static INetVar[] GetAllNetVars(object self) { object self2 = self; return (from field in self2.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where typeof(INetVar).IsAssignableFrom(field.FieldType) select (INetVar)field.GetValue(self2)).ToArray(); } } internal class NetVar<T> : INetVar, IDisposable where T : IEquatable<T> { public readonly NetworkVariable<T> networkVariable; private bool deferPending = true; private T deferredValue; private T _localValue; private readonly bool isGlued; private readonly Action<T>? setGlued; private readonly Func<T>? getGlued; private readonly Func<T, T>? validate; private readonly Func<bool> inControl; private readonly Action<T> SetOnServer; private readonly OnValueChangedDelegate<T>? onChange; private T localValue { get { return _localValue; } set { if (isGlued) { setGlued(value); } _localValue = value; } } public T Value { get { Synchronize(); return localValue; } set { if (inControl()) { deferPending = false; if (validate != null) { value = validate(value); } if (!EqualityComparer<T>.Default.Equals(localValue, value)) { T prevValue = localValue; localValue = value; SetOnServer(value); OnChange(prevValue, value); } } } } public NetVar(out NetworkVariable<T> networkVariable, Action<T> SetOnServer, Func<bool> inControl, T initialValue = default(T), OnValueChangedDelegate<T>? onChange = null, Action<T>? setGlued = null, Func<T>? getGlued = null, Func<T, T>? validate = null) { isGlued = setGlued != null && getGlued != null; this.setGlued = setGlued; this.getGlued = getGlued; this.validate = validate; this.onChange = onChange; this.SetOnServer = SetOnServer; this.inControl = inControl; this.networkVariable = new NetworkVariable<T>(initialValue, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); networkVariable = this.networkVariable; _localValue = initialValue; localValue = initialValue; deferredValue = initialValue; NetworkVariable<T> obj = networkVariable; obj.OnValueChanged = (OnValueChangedDelegate<T>)(object)Delegate.Combine((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)(OnValueChangedDelegate<T>)delegate(T prevValue, T currentValue) { if (!EqualityComparer<T>.Default.Equals(localValue, currentValue)) { Synchronize(); OnChange(prevValue, currentValue); } }); } public void ServerSet(T value) { if (validate != null) { value = validate(value); } networkVariable.Value = value; } public void SetDeferred(T value) { deferredValue = value; } private void OnChange(T prevValue, T currentValue) { if (onChange != null) { onChange.Invoke(prevValue, currentValue); } } public void UpdateDeferred() { if (inControl() && deferPending) { Value = deferredValue; } deferPending = false; } public void Synchronize() { if (!inControl()) { localValue = networkVariable.Value; deferPending = false; } else if (isGlued) { Value = getGlued(); } else { Value = localValue; } } public void Dispose() { ((NetworkVariableBase)networkVariable).Dispose(); } } public class SprayPaintItemExt : MonoBehaviour { public SprayPaintItem instance; public SprayPaintItemNetExt net; public DecalProjector previewDecal; private List<Action> cleanupActions = new List<Action>(); private float previewFadeFactor = 1f; private Vector3 previewOriginalScale = Vector3.oneVector; public bool ItemActive() { if (net.HeldByLocalPlayer && net.InActiveSlot) { return Patches.CanUseItem(((GrabbableObject)instance).playerHeldBy); } return false; } public void Awake() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown instance = ((Component)this).GetComponent<SprayPaintItem>(); net = instance.NetExt(); GameObject val = Object.Instantiate<GameObject>(instance.sprayPaintPrefab); previewDecal = val.GetComponent<DecalProjector>(); Object.DontDestroyOnLoad((Object)(object)val); previewDecal.material = new Material(net.baseDecalMaterial); ((Behaviour)previewDecal).enabled = true; ((Object)val).name = "PreviewDecal"; val.SetActive(true); ActionSubscriptionBuilder actionSubscriptionBuilder = new ActionSubscriptionBuilder(cleanupActions, () => ItemActive()); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintEraseModifier, delegate { if (SessionData.AllowErasing) { net.IsErasing = true; } }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintErase, delegate { if (SessionData.AllowErasing) { net.IsErasing = true; } ((GrabbableObject)instance).UseItemOnClient(true); }, delegate { ((GrabbableObject)instance).UseItemOnClient(false); }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintNextColor, delegate { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (SessionData.AllowColorChange) { int num2 = net.ColorPalette.FindIndex((Color color) => color == net.CurrentColor); num2 = net.posmod(++num2, net.ColorPalette.Count); ((MonoBehaviour)this).StartCoroutine(net.ChangeColorCoroutine(net.ColorPalette[num2])); } }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintPreviousColor, delegate { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (SessionData.AllowColorChange) { int num = net.ColorPalette.FindIndex((Color color) => color == net.CurrentColor); num = net.posmod(--num, net.ColorPalette.Count); ((MonoBehaviour)this).StartCoroutine(net.ChangeColorCoroutine(net.ColorPalette[num])); } }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintColor1, delegate { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (SessionData.AllowColorChange) { int index4 = net.posmod(0, net.ColorPalette.Count); ((MonoBehaviour)this).StartCoroutine(net.ChangeColorCoroutine(net.ColorPalette[index4])); } }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintColor2, delegate { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (SessionData.AllowColorChange) { int index3 = net.posmod(1, net.ColorPalette.Count); ((MonoBehaviour)this).StartCoroutine(net.ChangeColorCoroutine(net.ColorPalette[index3])); } }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintColor3, delegate { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (SessionData.AllowColorChange) { int index2 = net.posmod(2, net.ColorPalette.Count); ((MonoBehaviour)this).StartCoroutine(net.ChangeColorCoroutine(net.ColorPalette[index2])); } }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintColor4, delegate { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (SessionData.AllowColorChange) { int index = net.posmod(3, net.ColorPalette.Count); ((MonoBehaviour)this).StartCoroutine(net.ChangeColorCoroutine(net.ColorPalette[index])); } }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintIncreaseSize, (object _, CallbackContext _) => ((MonoBehaviour)this).StartCoroutine(net.ChangeSizeCoroutine()), delegate(object _, CallbackContext _, Coroutine? coroutine) { ((MonoBehaviour)this).StopCoroutine(coroutine); }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintDecreaseSize, (object _, CallbackContext _) => ((MonoBehaviour)this).StartCoroutine(net.ChangeSizeCoroutine()), delegate(object _, CallbackContext _, Coroutine? coroutine) { ((MonoBehaviour)this).StopCoroutine(coroutine); }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintSize01, delegate { net.PaintSize = 0.1f; }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintSize1, delegate { net.PaintSize = 1f; }); actionSubscriptionBuilder.Subscribe(Plugin.inputActions.SprayPaintSize2, delegate { net.PaintSize = 2f; }); } public void Update() { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_017b: 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_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)previewDecal == (Object)null || (Object)(object)((Component)previewDecal).gameObject == (Object)null || (Object)(object)previewDecal.material == (Object)null) { return; } bool flag = false; if (ItemActive()) { Vector3 position = ((Component)((GrabbableObject)instance).playerHeldBy.gameplayCamera).transform.position; Vector3 forward = ((Component)((GrabbableObject)instance).playerHeldBy.gameplayCamera).transform.forward; if (Patches.RaycastCustom(new Ray(position, forward), out var sprayHit, SessionData.Range, net.sprayPaintMask, (QueryTriggerInteraction)2, instance)) { Patches.PositionSprayPaint(instance, ((Component)previewDecal).gameObject, sprayHit, setColor: false); previewOriginalScale = ((Component)previewDecal).transform.localScale; flag = true; } } Color currentColor = net.CurrentColor; float num = (Mathf.Sin(Time.timeSinceLevelLoad * 6f) + 1f) * 0.2f + 0.2f; previewFadeFactor = Utils.Lexp(previewFadeFactor, flag ? 1f : 0f, 15f * Time.deltaTime); previewDecal.material.color = new Color(Mathf.Lerp(currentColor.r, Math.Min(currentColor.r + 0.35f, 1f), num), Mathf.Lerp(currentColor.g, Math.Min(currentColor.g + 0.35f, 1f), num), Mathf.Lerp(currentColor.b, Math.Min(currentColor.b + 0.35f, 1f), num), Mathf.Clamp(Plugin.SprayPreviewOpacity, 0f, 1f) * previewFadeFactor); ((Component)previewDecal).transform.localScale = previewOriginalScale * previewFadeFactor; } public void OnDestroy() { foreach (Action cleanupAction in cleanupActions) { cleanupAction(); } Object.Destroy((Object)(object)previewDecal); } } namespace BetterSprayPaint { [HarmonyPatch] internal class Patches { public static HashSet<string> CompanyCruiserColliderBlacklist = new HashSet<string> { "Meshes/DoorLeftContainer/Door/DoorTrigger", "CollisionTriggers/Cube", "PushTrigger", "Triggers/ItemDropRegion", "Triggers/BackPhysicsRegion", "Triggers/LeftShelfPlacementCollider/bounds", "Triggers/RightShelfPlacementCollider/bounds", "VehicleBounds", "InsideTruckNavBounds" }; private static MethodInfo physicsRaycast = typeof(Physics).GetMethod("Raycast", new Type[5] { typeof(Ray), typeof(RaycastHit).MakeByRefType(), typeof(float), typeof(int), typeof(QueryTriggerInteraction) }); private static MethodInfo raycastCustom = typeof(Patches).GetMethod("RaycastCustom"); [HarmonyPrefix] [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] public static void EndOfGame() { foreach (GameObject sprayPaintDecal in SprayPaintItem.sprayPaintDecals) { if ((Object)(object)sprayPaintDecal != (Object)null && !sprayPaintDecal.activeInHierarchy) { Object.Destroy((Object)(object)sprayPaintDecal); } } } [HarmonyPrefix] [HarmonyPatch(typeof(SprayPaintItem), "LateUpdate")] public static void LateUpdate(SprayPaintItem __instance, ref float ___sprayCanTank, ref float ___sprayCanShakeMeter, ref AudioSource ___sprayAudio, bool ___isSpraying) { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) if (__instance.isWeedKillerSprayBottle) { return; } __instance.Ext(); SprayPaintItemNetExt sprayPaintItemNetExt = __instance.NetExt(); if ((Object)(object)sprayPaintItemNetExt == (Object)null) { return; } if (SessionData.InfiniteTank) { ___sprayCanTank = 1f; } __instance.maxSprayPaintDecals = Plugin.MaxSprayPaintDecals; __instance.sprayIntervalSpeed = 0.01f * sprayPaintItemNetExt.PaintSize; if (SessionData.ShakingNotNeeded) { ___sprayCanShakeMeter = 1f; } ___sprayAudio.volume = Plugin.Volume; if (sprayPaintItemNetExt.HeldByLocalPlayer && sprayPaintItemNetExt.ShakeMeter.Value != ___sprayCanShakeMeter) { sprayPaintItemNetExt.UpdateShakeMeterServerRpc(___sprayCanShakeMeter); } else { ___sprayCanShakeMeter = sprayPaintItemNetExt.ShakeMeter.Value; } NetworkObjectReference value; if (sprayPaintItemNetExt.HeldByLocalPlayer) { value = sprayPaintItemNetExt.PlayerHeldBy.Value; if (((NetworkObjectReference)(ref value)).NetworkObjectId != ((NetworkBehaviour)((GrabbableObject)__instance).playerHeldBy).NetworkObjectId) { sprayPaintItemNetExt.SetPlayerHeldByServerRpc(new NetworkObjectReference(((NetworkBehaviour)((GrabbableObject)__instance).playerHeldBy).NetworkObject)); goto IL_00f8; } } value = sprayPaintItemNetExt.PlayerHeldBy.Value; NetworkObject val = default(NetworkObject); if (((NetworkObjectReference)(ref value)).TryGet(ref val, (NetworkManager)null)) { ((GrabbableObject)__instance).playerHeldBy = ((Component)val).GetComponent<PlayerControllerB>(); } goto IL_00f8; IL_00f8: if (sprayPaintItemNetExt.HeldByLocalPlayer) { sprayPaintItemNetExt.IsErasing = Plugin.inputActions.SprayPaintEraseModifier.IsPressed() || Plugin.inputActions.SprayPaintErase.IsPressed(); } if (___isSpraying && (___sprayCanTank <= 0f || ___sprayCanShakeMeter <= 0f)) { sprayPaintItemNetExt.UpdateParticles(); __instance.StopSpraying(); PlayCanEmptyEffect(__instance, ___sprayCanTank <= 0f); } if (!((Object)(object)((GrabbableObject)__instance).playerHeldBy != (Object)null) || !Plugin.ShorterShakeAnimation) { return; } Animator playerBodyAnimator = ((GrabbableObject)__instance).playerHeldBy.playerBodyAnimator; AnimatorClipInfo[] currentAnimatorClipInfo = playerBodyAnimator.GetCurrentAnimatorClipInfo(2); for (int i = 0; i < currentAnimatorClipInfo.Length; i++) { AnimatorClipInfo val2 = currentAnimatorClipInfo[i]; if (((Object)((AnimatorClipInfo)(ref val2)).clip).name == "ShakeItem") { AnimatorStateInfo currentAnimatorStateInfo = playerBodyAnimator.GetCurrentAnimatorStateInfo(2); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime > 0.1f) { playerBodyAnimator.Play("HoldOneHandedItem"); } } } } public static void EraseSprayPaintAtPoint(SprayPaintItem __instance, Vector3 pos) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject sprayPaintDecal in SprayPaintItem.sprayPaintDecals) { if ((Object)(object)sprayPaintDecal != (Object)null && Vector3.Distance(sprayPaintDecal.transform.position, pos) < Mathf.Max(0.15f, 0.5f * __instance.NetExt().PaintSize)) { sprayPaintDecal.SetActive(false); } } } public static bool EraseSprayPaintLocal(SprayPaintItem __instance, Vector3 sprayPos, Vector3 sprayRot, out RaycastHit sprayHit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (RaycastCustom(new Ray(sprayPos, sprayRot), out sprayHit, SessionData.Range, __instance.NetExt().sprayPaintMask, (QueryTriggerInteraction)2, __instance)) { EraseSprayPaintAtPoint(__instance, ((RaycastHit)(ref sprayHit)).point); return true; } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(SprayPaintItem), "TrySpraying")] public static bool TrySpraying(SprayPaintItem __instance, ref bool __result, ref RaycastHit ___sprayHit, ref float ___sprayCanShakeMeter) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (__instance.isWeedKillerSprayBottle) { return true; } SprayPaintItemNetExt sprayPaintItemNetExt = __instance.NetExt(); Vector3 position = ((Component)GameNetworkManager.Instance.localPlayerController.gameplayCamera).transform.position; Vector3 forward = ((Component)GameNetworkManager.Instance.localPlayerController.gameplayCamera).transform.forward; sprayPaintItemNetExt.UpdateParticles(); if (SessionData.AllowErasing && sprayPaintItemNetExt.IsErasing) { if (EraseSprayPaintLocal(__instance, position, forward, out var sprayHit)) { __result = true; sprayPaintItemNetExt.EraseServerRpc(((RaycastHit)(ref sprayHit)).point); } return false; } if (AddSprayPaintLocal(__instance, position, forward)) { __result = true; sprayPaintItemNetExt.SprayServerRpc(position, forward); } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(SprayPaintItem), "ItemActivate")] public static void ItemActivate(SprayPaintItem __instance) { if (!__instance.isWeedKillerSprayBottle) { __instance.NetExt().UpdateParticles(); } } public static bool RaycastCustom(Ray ray, out RaycastHit sprayHit, float _distance, int layerMask, QueryTriggerInteraction queryTriggerInteraction, SprayPaintItem __instance) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_016f: 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) PlayerControllerB playerHeldBy = ((GrabbableObject)__instance).playerHeldBy; GameObject val = null; if ((Object)(object)playerHeldBy != (Object)null && (Object)(object)((Component)playerHeldBy).gameObject != (Object)null) { val = ((Component)playerHeldBy).gameObject; } else { Plugin.log.LogWarning("Player GameObject is null"); } bool result = false; RaycastHit val2 = default(RaycastHit); float num = SessionData.Range + 1f; int num2 = 1073742336; RaycastHit[] array = Physics.RaycastAll(ray, SessionData.Range, layerMask | num2, queryTriggerInteraction); for (int i = 0; i < array.Length; i++) { RaycastHit val3 = array[i]; int num3 = 1 << ((Component)((RaycastHit)(ref val3)).collider).gameObject.layer; if ((Object)(object)val != (Object)null && ((RaycastHit)(ref val3)).transform.IsChildOf(val.transform)) { continue; } if ((num3 & layerMask) == 0) { if ((num3 & num2) == 0) { continue; } Transform val4 = ((Component)((RaycastHit)(ref val3)).collider).gameObject.transform.GetAncestors().FirstOrDefault((Func<Transform, bool>)((Transform go) => ((Object)go).name.StartsWith("CompanyCruiser"))); if ((Object)(object)val4 == (Object)null) { continue; } string path = ((Component)((RaycastHit)(ref val3)).collider).gameObject.transform.GetPath(val4); if (CompanyCruiserColliderBlacklist.Contains(path)) { continue; } } if ((!((RaycastHit)(ref val3)).collider.isTrigger || !((Object)((RaycastHit)(ref val3)).collider).name.Contains("Trigger")) && ((RaycastHit)(ref val3)).distance < num) { num = ((RaycastHit)(ref val3)).distance; val2 = val3; result = true; } } sprayHit = val2; if (!SessionData.ClientsCanPaintShip) { bool flag = (Object)(object)((GrabbableObject)__instance).playerHeldBy != (Object)null && ((GrabbableObject)__instance).playerHeldBy.isHostPlayerObject; if ((((Object)(object)((RaycastHit)(ref sprayHit)).collider != (Object)null && ((Component)((RaycastHit)(ref sprayHit)).collider).transform.IsChildOf(StartOfRound.Instance.elevatorTransform)) || (Object)(object)RoundManager.Instance.mapPropsContainer == (Object)null) && !flag) { result = false; } } return result; } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(SprayPaintItem), "AddSprayPaintLocal")] public static bool original_AddSprayPaintLocal(object instance, Vector3 sprayPos, Vector3 sprayRot) { throw new NotImplementedException("stub"); } [HarmonyTranspiler] [HarmonyPatch(typeof(SprayPaintItem), "AddSprayPaintLocal")] private static IEnumerable<CodeInstruction> transpiler_AddSprayPaintLocal(IEnumerable<CodeInstruction> instructions) { bool foundMinNextDecalDistance = false; bool foundRaycastCall = false; bool addedWeedKillerSkip = false; foreach (CodeInstruction instruction in instructions) { if (!addedWeedKillerSkip) { addedWeedKillerSkip = true; foreach (CodeInstruction item in _transpiler_AddWeedKillerSkip(instruction, typeof(Patches).GetMethod("original_AddSprayPaintLocal"))) { yield return item; } } else if (!foundMinNextDecalDistance && instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 0.175f) { foundMinNextDecalDistance = true; yield return new CodeInstruction(OpCodes.Ldc_R4, (object)0.001f); } else if (!foundRaycastCall && instruction.opcode == OpCodes.Call && instruction.operand == physicsRaycast) { foundRaycastCall = true; yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)raycastCustom); } else { yield return instruction; } } } public static float TankCapacity() { if (SessionData.InfiniteTank) { return 25f; } return SessionData.TankCapacity; } private static IEnumerable<CodeInstruction> _transpiler_AddWeedKillerSkip(CodeInstruction instruction, MethodInfo original) { Label label = default(Label); yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Ldfld, (object)typeof(SprayPaintItem).GetField("isWeedKillerSprayBottle")); yield return new CodeInstruction(OpCodes.Brfalse_S, (object)label); yield return new CodeInstruction(OpCodes.Jmp, (object)original); yield return CodeInstructionExtensions.WithLabels(instruction, new Label[1] { label }); } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(SprayPaintItem), "LateUpdate")] public static void original_LateUpdate(object instance) { throw new NotImplementedException("stub"); } [HarmonyTranspiler] [HarmonyPatch(typeof(SprayPaintItem), "LateUpdate")] private static IEnumerable<CodeInstruction> transpiler_LateUpdate(IEnumerable<CodeInstruction> instructions) { bool foundTankCapacityDivisor = false; bool addedWeedKillerSkip = false; foreach (CodeInstruction instruction in instructions) { if (!addedWeedKillerSkip) { addedWeedKillerSkip = true; foreach (CodeInstruction item in _transpiler_AddWeedKillerSkip(instruction, typeof(Patches).GetMethod("original_LateUpdate"))) { yield return item; } } else if (!foundTankCapacityDivisor && instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 25f) { foundTankCapacityDivisor = true; yield return new CodeInstruction(OpCodes.Call, (object)typeof(Patches).GetMethod("TankCapacity")); } else { yield return instruction; } } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] public static void Player_Update_Postfix(PlayerControllerB __instance) { if (__instance.IsLocalPlayer()) { Plugin.UpdateSessionData(); } } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(PlayerControllerB), "CanUseItem")] public static bool CanUseItem(object instance) { throw new NotImplementedException("stub"); } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(SprayPaintItem), "AddSprayPaintLocal")] public static bool _AddSprayPaintLocal(object instance, Vector3 sprayPos, Vector3 sprayRot) { Transpiler(null); return false; static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { bool foundMinNextDecalDistance = false; bool foundRaycastCall = false; foreach (CodeInstruction instruction in instructions) { if (!foundMinNextDecalDistance && instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 0.175f) { foundMinNextDecalDistance = true; yield return new CodeInstruction(OpCodes.Ldc_R4, (object)0.001f); } else if (!foundRaycastCall && instruction.opcode == OpCodes.Call && instruction.operand == physicsRaycast) { foundRaycastCall = true; yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)raycastCustom); } else { yield return instruction; } } } } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(SprayPaintItem), "PlayCanEmptyEffect")] public static void PlayCanEmptyEffect(object instance, bool isEmpty) { throw new NotImplementedException("stub"); } public static void PositionSprayPaint(SprayPaintItem instance, GameObject gameObject, RaycastHit sprayHit, bool setColor = true) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) gameObject.transform.forward = -((RaycastHit)(ref sprayHit)).normal; gameObject.transform.position = ((RaycastHit)(ref sprayHit)).point; if (((Component)((RaycastHit)(ref sprayHit)).collider).gameObject.layer == 11 || ((Component)((RaycastHit)(ref sprayHit)).collider).gameObject.layer == 8 || ((Component)((RaycastHit)(ref sprayHit)).collider).gameObject.layer == 0) { if (((Component)((RaycastHit)(ref sprayHit)).collider).transform.IsChildOf(StartOfRound.Instance.elevatorTransform) || (Object)(object)RoundManager.Instance.mapPropsContainer == (Object)null) { gameObject.transform.SetParent(StartOfRound.Instance.elevatorTransform, true); } else { gameObject.transform.SetParent(RoundManager.Instance.mapPropsContainer.transform, true); } } DecalProjector component = gameObject.GetComponent<DecalProjector>(); ((Behaviour)component).enabled = true; SprayPaintItemNetExt sprayPaintItemNetExt = instance.NetExt(); component.drawDistance = Plugin.DrawDistance; if (setColor) { component.material = sprayPaintItemNetExt.DecalMaterialForColor(sprayPaintItemNetExt.CurrentColor); } component.scaleMode = (DecalScaleMode)1; gameObject.transform.localScale = new Vector3(1f, 1f, 1f); Vector3 lossyScale = gameObject.transform.lossyScale; gameObject.transform.localScale = new Vector3(1f / lossyScale.x * sprayPaintItemNetExt.PaintSize, 1f / lossyScale.y * sprayPaintItemNetExt.PaintSize, 1f); } public static bool AddSprayPaintLocal(SprayPaintItem instance, Vector3 sprayPos, Vector3 sprayRot) { //IL_0035: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (SprayPaintItem.sprayPaintDecalsIndex - SprayPaintItem.sprayPaintDecals.Count > 1) { SprayPaintItem.sprayPaintDecals.AddRange((IEnumerable<GameObject>)(object)new GameObject[SprayPaintItem.sprayPaintDecalsIndex - 2 - SprayPaintItem.sprayPaintDecals.Count]); } bool num = _AddSprayPaintLocal(instance, sprayPos, sprayRot); if (num && SprayPaintItem.sprayPaintDecals.Count > SprayPaintItem.sprayPaintDecalsIndex) { GameObject gameObject = SprayPaintItem.sprayPaintDecals[SprayPaintItem.sprayPaintDecalsIndex]; RaycastHit value = Traverse.Create((object)instance).Field<RaycastHit>("sprayHit").Value; PositionSprayPaint(instance, gameObject, value); } return num; } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(SprayPaintItem), "ItemInteractLeftRight")] public static void original_ItemInteractLeftRight(object instance, bool right) { throw new NotImplementedException("stub"); } public static float _shakeRestoreAmount() { return SessionData.ShakeEfficiency; } [HarmonyTranspiler] [HarmonyPatch(typeof(SprayPaintItem), "ItemInteractLeftRight")] private static IEnumerable<CodeInstruction> transpiler_ItemInteractLeftRight(IEnumerable<CodeInstruction> instructions) { bool foundShakeRestoreAmount = false; bool addedWeedKillerSkip = false; foreach (CodeInstruction instruction in instructions) { if (!addedWeedKillerSkip) { addedWeedKillerSkip = true; foreach (CodeInstruction item in _transpiler_AddWeedKillerSkip(instruction, typeof(Patches).GetMethod("original_ItemInteractLeftRight"))) { yield return item; } } else if (!foundShakeRestoreAmount && instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 0.15f) { foundShakeRestoreAmount = true; yield return new CodeInstruction(OpCodes.Call, (object)typeof(Patches).GetMethod("_shakeRestoreAmount")); } else { yield return instruction; } } } } [BepInPlugin("taffyko.BetterSprayPaint", "BetterSprayPaint", "2.0.9")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private delegate bool ParseConfigValue<T>(string input, out T output); public const string modGUID = "taffyko.BetterSprayPaint"; public const string modName = "BetterSprayPaint"; public const string modVersion = "2.0.9"; internal static Harmony harmony; internal static QuietLogSource log; internal static List<Action> cleanupActions; internal static List<Action> sceneChangeActions; internal static PluginInputActions inputActions; public static bool AllowErasing { get; private set; } public static bool AllowColorChange { get; private set; } public static bool InfiniteTank { get; private set; } public static float TankCapacity { get; private set; } public static float ShakeEfficiency { get; private set; } public static bool ShakingNotNeeded { get; private set; } public static float Volume { get; private set; } public static float MaxSize { get; private set; } public static float Range { get; private set; } public static bool ShorterShakeAnimation { get; private set; } public static int MaxSprayPaintDecals { get; private set; } public static float DrawDistance { get; private set; } public static float SprayPreviewOpacity { get; private set; } public static bool ClientsCanPaintShip { get; private set; } static Plugin() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown harmony = new Harmony("taffyko.BetterSprayPaint"); cleanupActions = new List<Action>(); sceneChangeActions = new List<Action>(); inputActions = new PluginInputActions(); log = new QuietLogSource("BetterSprayPaint"); Logger.Sources.Add((ILogSource)(object)log); } private void Awake() { log.LogInfo("Loading taffyko.BetterSprayPaint"); ConfigInit(); harmony.PatchAll(Assembly.GetExecutingAssembly()); } private void OnDestroy() { } public static void UpdateSessionData() { SessionData instance = SessionData.instance; if ((Object)(object)instance != (Object)null && ((NetworkBehaviour)instance).IsServer) { instance.allowErasing.Value = AllowErasing; instance.allowColorChange.Value = AllowColorChange; instance.infiniteTank.Value = InfiniteTank; instance.tankCapacity.Value = TankCapacity; instance.shakeEfficiency.Value = ShakeEfficiency; instance.shakingNotNeeded.Value = ShakingNotNeeded; instance.range.Value = Range; instance.maxSize.Value = MaxSize; instance.clientsCanPaintShip.Value = ClientsCanPaintShip; } } private void ConfigInit() { ((BaseUnityPlugin)this).Config.Bind<string>("README", "README", "", "All config values are text-based, as a workaround to make it possible for default values to change in future updates.\r\n\r\nSee https://github.com/taffyko/LCNiceChat/issues/3 for more information.\r\n\r\nIf you enter an invalid value, it will change back to \"default\" when the game starts."); ConfEntry("General", "AllowErasing", defaultValue: true, "When enabled, players can erase spray paint. (Note: With default controls, erasing is done by holding E and LMB at the same time)", bool.TryParse, hostControlled: true); ConfEntry("General", "AllowColorChange", defaultValue: true, "When enabled, players can control the color of their spray paint.", bool.TryParse, hostControlled: true); ConfEntry("General", "InfiniteTank", defaultValue: true, "When enabled, the spray can has infinite uses.", bool.TryParse, hostControlled: true); ConfEntry("General", "TankCapacity", 30f, "Amount of time (in seconds) that each can may spray for before running out (Has no effect when InfiniteTank is enabled.)", float.TryParse, 30f, hostControlled: true); ConfEntry("General", "ShakeEfficiency", 0.3f, "The percentage to restore on the \"shake meter\" each time the can is shaken.", float.TryParse, 0.15f, hostControlled: true); ConfEntry("General", "ShakingNotNeeded", defaultValue: false, "When enabled, the can never needs to be shaken.", bool.TryParse, hostControlled: true); ConfEntry("General", "MaxSize", 2f, "The maximum size of spray paint that players are allowed to create.", float.TryParse, hostControlled: true); ConfEntry("General", "Range", 7f, "The maximum distance that players can spray.", float.TryParse, 7f, hostControlled: true); ConfEntry("General", "ClientsCanPaintShip", defaultValue: true, "When disabled, only the host can paint on or within the ship.", bool.TryParse, hostControlled: true); ConfEntry("Client-side", "Volume", 0.1f, "Volume of spray paint sound effects.", float.TryParse, 1f); ConfEntry("Client-side", "ShorterShakeAnimation", defaultValue: true, "Whether to shorten the can-shaking animation.", bool.TryParse); ConfEntry("Client-side", "MaxSprayPaintDecals", 4000, "The maximum amount of spray paint decals that can exist at once. When the limit is reached, spray paint decals will start to disappear, starting with the oldest.", int.TryParse, 1000); ConfEntry("Client-side", "DrawDistance", 35f, "The maximum distance from which spray paint decals can be seen (Only applies to new spray paint drawn after the setting was changed, if changed mid-game).", float.TryParse, 20f); ConfEntry("Client-side", "SprayPreviewOpacity", 0.5f, "Opacity of the preview highlighting where spray paint will land when sprayed. Set to 0 to disable the preview altogether.", float.TryParse); } private static bool NoopParse(string input, out string output) { output = input; return true; } private void ConfEntry<T>(string category, string name, T defaultValue, string description, ParseConfigValue<T> tryParse, bool hostControlled = false) { ConfEntryInternal(category, name, defaultValue, description, tryParse, hostControlled); } private void ConfEntry<T>(string category, string name, T defaultValue, string description, ParseConfigValue<T> tryParse, T vanillaValue, bool hostControlled = false) { ConfEntryInternal(category, name, defaultValue, description, tryParse, hostControlled, ConfEntryToString(vanillaValue)); } private void ConfEntryInternal<T>(string category, string name, T defaultValue, string description, ParseConfigValue<T> tryParse, bool hostControlled = false, string? vanillaValueText = null) { ParseConfigValue<T> tryParse2 = tryParse; T defaultValue2 = defaultValue; PropertyInfo property = typeof(Plugin).GetProperty(name); string text = "[default: " + ConfEntryToString(defaultValue2) + "]\n" + description; text += (hostControlled ? "\n(This setting is overridden by the lobby host)" : "\n(This setting's effect applies to you only)"); if (vanillaValueText != null) { text = text + "\n(The original value of this setting in the base-game is " + vanillaValueText + ")"; } ConfigEntry<string> config = ((BaseUnityPlugin)this).Config.Bind<string>(category, name, "default", text); if (string.IsNullOrEmpty(config.Value)) { config.Value = "default"; } T output; bool flag = tryParse2(config.Value, out output) && config.Value != "default"; property.SetValue(null, flag ? output : defaultValue2); if (!flag) { config.Value = "default"; } EventHandler loadConfig = delegate { T output2; bool flag2 = tryParse2(config.Value, out output2) && config.Value != "default"; property.SetValue(null, flag2 ? output2 : defaultValue2); }; config.SettingChanged += loadConfig; cleanupActions.Add(delegate { config.SettingChanged -= loadConfig; property.SetValue(null, defaultValue2); }); } private string ConfEntryToString(object? value) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (value == null) { return "null"; } Type type = value.GetType(); if (type == typeof(float)) { return $"{(float)value:0.0#####}"; } if (type == typeof(Color)) { return "#" + ColorUtility.ToHtmlStringRGBA((Color)value); } return value.ToString(); } } public class PluginInputActions : LcInputActions { [InputAction("<Keyboard>/e", Name = "Spray Paint Erase Modifier", ActionId = "SprayPaintEraseModifier", GamepadPath = "<Gamepad>/dpad/up")] public InputAction? SprayPaintEraseModifier { get; set; } [InputAction("", Name = "Spray Paint Erase", ActionId = "SprayPaintErase")] public InputAction? SprayPaintErase { get; set; } [InputAction("<Keyboard>/t", Name = "Spray Paint Next Color", ActionId = "SprayPaintNextColor")] public InputAction? SprayPaintNextColor { get; set; } [InputAction("", Name = "Spray Paint Previous Color", ActionId = "SprayPaintPreviousColor")] public InputAction? SprayPaintPreviousColor { get; set; } [InputAction("", Name = "Spray Paint Color 1", ActionId = "SprayPaintColor1")] public InputAction? SprayPaintColor1 { get; set; } [InputAction("", Name = "Spray Paint Color 2", ActionId = "SprayPaintColor2")] public InputAction? SprayPaintColor2 { get; set; } [InputAction("", Name = "Spray Paint Color 3", ActionId = "SprayPaintColor3")] public InputAction? SprayPaintColor3 { get; set; } [InputAction("", Name = "Spray Paint Color 4", ActionId = "SprayPaintColor4")] public InputAction? SprayPaintColor4 { get; set; } [InputAction("<Keyboard>/equals", Name = "Spray Paint Increase Size", ActionId = "SprayPaintIncreaseSize")] public InputAction? SprayPaintIncreaseSize { get; set; } [InputAction("<Keyboard>/minus", Name = "Spray Paint Decrease Size", ActionId = "SprayPaintDecreaseSize")] public InputAction? SprayPaintDecreaseSize { get; set; } [InputAction("", Name = "Spray Paint Set Size 0.1", ActionId = "SprayPaintSize01")] public InputAction? SprayPaintSize01 { get; set; } [InputAction("", Name = "Spray Paint Set Size 1.0", ActionId = "SprayPaintSize1")] public InputAction? SprayPaintSize1 { get; set; } [InputAction("", Name = "Spray Paint Set Size 2.0", ActionId = "SprayPaintSize2")] public InputAction? SprayPaintSize2 { get; set; } } public class ActionSubscriptionBuilder { public List<Action> cleanupActions; public Func<bool> active; public ActionSubscriptionBuilder(List<Action> cleanupActions, Func<bool> active) { this.cleanupActions = cleanupActions; this.active = active; base..ctor(); } public void Subscribe(InputAction? action, EventHandler<CallbackContext> onStart, EventHandler<CallbackContext>? onStop = null) { EventHandler<CallbackContext> onStart2 = onStart; EventHandler<CallbackContext> onStop2 = onStop; Subscribe(action, delegate(object sender, CallbackContext e) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) onStart2(sender, e); return null; }, (onStop2 == null) ? null : ((Action<object, CallbackContext, object>)delegate(object sender, CallbackContext e, object? ret) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) onStop2(sender, e); })); } public void Subscribe<T>(InputAction? action, Func<object, CallbackContext, T> onStart, Action<object, CallbackContext, T?>? onStop = null) { Func<object, CallbackContext, T> onStart2 = onStart; Action<object, CallbackContext, T?> onStop2 = onStop; InputAction action2 = action; if (action2 == null) { Plugin.log.LogWarning("Subscribe called with null InputAction"); return; } EventInfo startedEvent = typeof(InputAction).GetEvent("started"); EventInfo canceledEvent = typeof(InputAction).GetEvent("canceled"); T ret = default(T); bool actionHeld = false; Action<CallbackContext> startHandler = delegate(CallbackContext e) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (active()) { actionHeld = true; ret = onStart2(this, e); } }; Action<CallbackContext> cancelHandler = delegate(CallbackContext e) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (actionHeld && onStop2 != null) { onStop2(this, e, ret); actionHeld = false; } }; startedEvent.AddEventHandler(action2, startHandler); cleanupActions.Add(delegate { startedEvent.RemoveEventHandler(action2, startHandler); }); canceledEvent.AddEventHandler(action2, cancelHandler); cleanupActions.Add(delegate { canceledEvent.RemoveEventHandler(action2, cancelHandler); }); } } public static class Utils { public static string GetPath(this Transform current, Transform? relativeTo = null) { if ((Object)(object)current == (Object)(object)relativeTo) { return ""; } if ((Object)(object)current.parent == (Object)null) { return "/" + ((Object)current).name; } string path = current.parent.GetPath(relativeTo); if (path == "") { return ((Object)current).name; } return path + "/" + ((Object)current).name; } public static IEnumerable<Transform> GetAncestors(this Transform self, bool includeSelf = true) { Transform current = self; if (!includeSelf) { current = self.parent; } while ((Object)(object)current != (Object)null) { yield return current; current = current.parent; } } public static bool IsLocalPlayer(this PlayerControllerB? player) { if ((Object)(object)player != (Object)null) { return (Object)(object)player == (Object)(object)StartOfRound.Instance?.localPlayerController; } return false; } public static SprayPaintItemNetExt NetExt(this SprayPaintItem instance) { SprayPaintItemNetExt component = ((Component)instance).GetComponent<SprayPaintItemNetExt>(); if ((Object)(object)component == (Object)null) { Plugin.log.LogError("SprayPaintItem.Ext() is null"); } return component; } public static SprayPaintItemExt Ext(this SprayPaintItem instance) { SprayPaintItemExt sprayPaintItemExt = ((Component)instance).GetComponent<SprayPaintItemExt>(); if ((Object)(object)sprayPaintItemExt == (Object)null) { sprayPaintItemExt = ((Component)instance).gameObject.AddComponent<SprayPaintItemExt>(); } return sprayPaintItemExt; } public static PlayerNetExt? NetExt(this PlayerControllerB? instance) { PlayerNetExt result = default(PlayerNetExt); if ((Object)(object)instance != (Object)null && ((Component)instance).TryGetComponent<PlayerNetExt>(ref result)) { return result; } return null; } public static void SyncWithNetworkObject(this NetworkBehaviour networkBehaviour, NetworkObject? networkObject) { networkObject = networkObject ?? networkBehaviour.NetworkObject; if (!networkObject.ChildNetworkBehaviours.Contains(networkBehaviour)) { networkObject.ChildNetworkBehaviours.Add(networkBehaviour); } networkBehaviour.UpdateNetworkProperties(); } public static float Lexp(float a, float b, float t) { return a + (b - a) * (1f - Mathf.Exp(0f - t)); } } public static class PluginInfo { public const string PLUGIN_GUID = "BetterSprayPaint"; public const string PLUGIN_NAME = "BetterSprayPaint"; public const string PLUGIN_VERSION = "2.0.9"; } } namespace BetterSprayPaint.Ngo { public class PlayerNetExt : NetworkBehaviour { internal NetworkVariable<float> paintSize; internal NetVar<float> PaintSize; private INetVar[] netVars = Array.Empty<INetVar>(); public PlayerControllerB instance => ((Component)this).GetComponent<PlayerControllerB>(); [ServerRpc(RequireOwnership = false)] private void SetPaintSizeServerRpc(float value) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(58249432u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref value, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 58249432u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { PaintSize.ServerSet(value); } } } private PlayerNetExt() { PaintSize = new NetVar<float>(out paintSize, SetPaintSizeServerRpc, () => instance.IsLocalPlayer(), 1f, null, null, null, (float value) => Mathf.Clamp(value, 0.1f, SessionData.MaxSize)); netVars = INetVar.GetAllNetVars(this); } public override void OnNetworkSpawn() { ((NetworkBehaviour)this).OnNetworkSpawn(); } private void Update() { INetVar[] array = netVars; for (int i = 0; i < array.Length; i++) { array[i].Synchronize(); } } public override void OnNetworkDespawn() { ((NetworkBehaviour)this).OnNetworkDespawn(); INetVar[] array = netVars; for (int i = 0; i < array.Length; i++) { array[i].Dispose(); } } protected override void __initializeVariables() { if (paintSize == null) { throw new Exception("PlayerNetExt.paintSize cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)paintSize).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)paintSize, "paintSize"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)paintSize); ((NetworkBehaviour)this).__initializeVariables(); } [RuntimeInitializeOnLoadMethod] internal static void InitializeRPCS_PlayerNetExt() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown NetworkManager.__rpc_func_table.Add(58249432u, new RpcReceiveHandler(__rpc_handler_58249432)); } private static void __rpc_handler_58249432(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { float paintSizeServerRpc = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref paintSizeServerRpc, default(ForPrimitives)); target.__rpc_exec_stage = (__RpcExecStage)1; ((PlayerNetExt)(object)target).SetPaintSizeServerRpc(paintSizeServerRpc); target.__rpc_exec_stage = (__RpcExecStage)0; } } protected internal override string __getTypeName() { return "PlayerNetExt"; } } internal static class NgoHelper { internal static List<Action> cleanupActions = new List<Action>(); internal static GameObject? prefabContainer = null; private static List<(Type custom, Type native, Type? excluded)> BehaviourBindings { get; } = new List<(Type, Type, Type)>(); internal static void RegisterPrefab<T>(GameObject prefab, string name) where T : MonoBehaviour { GameObject prefab2 = prefab; prefab2.AddComponent<T>(); ((Object)prefab2).hideFlags = (HideFlags)61; prefab2.transform.SetParent(prefabContainer.transform); NetworkObject obj = prefab2.AddComponent<NetworkObject>(); string s = "taffyko.BetterSprayPaint." + name; byte[] value = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(s)); obj.GlobalObjectIdHash = BitConverter.ToUInt32(value, 0); NetworkManager.Singleton.AddNetworkPrefab(prefab2); cleanupActions.Add(delegate { MonoBehaviour[] array = (MonoBehaviour[])(object)Resources.FindObjectsOfTypeAll<T>(); array = array; foreach (MonoBehaviour obj2 in array) { NetworkManager.Singleton.RemoveNetworkPrefab(prefab2); Object.Destroy((Object)(object)((Component)obj2).gameObject); } }); } internal static void AddScriptToInstances<TCustomBehaviour, TNativeBehaviour>(bool updatePrefabs = false, Type? excluded = null) where TCustomBehaviour : NetworkBehaviour where TNativeBehaviour : NetworkBehaviour { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) TNativeBehaviour[] array = Resources.FindObjectsOfTypeAll<TNativeBehaviour>(); foreach (TNativeBehaviour val in array) { if ((excluded != null && ((object)val).GetType().IsInstanceOfType(excluded)) || (Object)(object)((Component)(object)val).gameObject.GetComponent<TCustomBehaviour>() != (Object)null) { continue; } Scene scene = ((Component)(object)val).gameObject.scene; bool flag = !((Scene)(ref scene)).IsValid(); if (flag && updatePrefabs) { NetworkPrefabs prefabs = NetworkManager.Singleton.NetworkConfig.Prefabs; NetworkObject networkObject = ((Component)(object)val).gameObject.GetComponent<NetworkObject>(); NetworkPrefab val2 = prefabs.m_Prefabs.Find((NetworkPrefab p) => p.SourcePrefabGlobalObjectIdHash == networkObject.GlobalObjectIdHash); foreach (NetworkPrefabsList networkPrefabsList in prefabs.NetworkPrefabsLists) { networkPrefabsList.Remove(val2); } NetworkManager.Singleton.RemoveNetworkPrefab(((Component)(object)val).gameObject); if (val2 != null) { _ = val2.SourcePrefabGlobalObjectIdHash; prefabs.NetworkPrefabOverrideLinks.Remove(val2.SourcePrefabGlobalObjectIdHash); } if (val2 != null) { _ = val2.TargetPrefabGlobalObjectIdHash; prefabs.OverrideToNetworkPrefab.Remove(val2.TargetPrefabGlobalObjectIdHash); } } ((NetworkBehaviour)(object)((Component)(object)val).gameObject.AddComponent<TCustomBehaviour>()).SyncWithNetworkObject(((Component)(object)val).gameObject.GetComponent<NetworkObject>()); if (flag && updatePrefabs) { NetworkManager.Singleton.AddNetworkPrefab(((Component)(object)val).gameObject); } } } internal static void RegisterScriptWithExistingPrefab<TCustomBehaviour, TNativeBehaviour>(Type? excluded = null) where TCustomBehaviour : NetworkBehaviour where TNativeBehaviour : NetworkBehaviour { Type excluded2 = excluded; AddScriptToInstances<TCustomBehaviour, TNativeBehaviour>(updatePrefabs: true, excluded2); UnityAction<Scene, LoadSceneMode> handler = delegate { AddScriptToInstances<TCustomBehaviour, TNativeBehaviour>(updatePrefabs: false, excluded2); }; SceneManager.sceneLoaded += handler; cleanupActions.Add(delegate { SceneManager.sceneLoaded -= handler; TNativeBehaviour[] array = Resources.FindObjectsOfTypeAll<TNativeBehaviour>(); for (int i = 0; i < array.Length; i++) { Object.Destroy((Object)(object)((Component)(object)array[i]).gameObject.GetComponent<TCustomBehaviour>()); } }); BindToPreExistingObjectByBehaviourPatch<TCustomBehaviour, TNativeBehaviour>(excluded2); } private static void RegisterCustomScripts() { NgoHelper.RegisterPrefab<SessionData>(SessionData.prefab, "SessionData"); NetworkManager.Singleton.OnServerStarted += SessionData.ServerSpawn; cleanupActions.Add(delegate { NetworkManager.Singleton.OnServerStarted -= SessionData.ServerSpawn; }); NetworkManager.Singleton.OnClientStopped += SessionData.Despawn; cleanupActions.Add(delegate { NetworkManager.Singleton.OnClientStopped -= SessionData.Despawn; }); NgoHelper.RegisterScriptWithExistingPrefab<SprayPaintItemNetExt, SprayPaintItem>((Type?)null); NgoHelper.RegisterScriptWithExistingPrefab<PlayerNetExt, PlayerControllerB>((Type?)null); } public static void BindToPreExistingObjectByBehaviourPatch<TCustomBehaviour, TNativeBehaviour>(Type? excluded = null) where TCustomBehaviour : NetworkBehaviour where TNativeBehaviour : NetworkBehaviour { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown Type typeFromHandle = typeof(TCustomBehaviour); Type typeFromHandle2 = typeof(TNativeBehaviour); BehaviourBindings.Add((typeFromHandle, typeFromHandle2, excluded)); MethodInfo methodInfo = null; try { methodInfo = typeFromHandle2.GetMethod("Awake", BindingFlags.Instance); } catch (Exception) { } if (methodInfo != null) { MethodBase methodBase = AccessTools.Method(typeFromHandle2, "Awake", (Type[])null, (Type[])null); HarmonyMethod val = new HarmonyMethod(typeof(NgoHelper), "BindBehaviourOnAwake", (Type[])null); Plugin.harmony.Patch(methodBase, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } internal static void BindBehaviourOnAwake(NetworkBehaviour __instance, MethodBase __originalMethod) { MethodBase __originalMethod2 = __originalMethod; Type type = ((object)__instance).GetType(); Component val = default(Component); foreach (var item in BehaviourBindings.Where<(Type, Type, Type)>(((Type custom, Type native, Type excluded) obj) => (obj.native == __originalMethod2.DeclaringType || type == obj.native) && (obj.excluded == null || !type.IsInstanceOfType(obj.excluded)))) { if (!((Component)__instance).gameObject.TryGetComponent(item.Item1, ref val)) { Component obj2 = ((Component)__instance).gameObject.AddComponent(item.Item1); ((NetworkBehaviour)(object)((obj2 is NetworkBehaviour) ? obj2 : null)).SyncWithNetworkObject(((Component)__instance).gameObject.GetComponent<NetworkObject>()); } } } internal static void NetcodeInit() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if ((Object)(object)prefabContainer != (Object)null) { throw new Exception("Ran NetcodeInit() more than once"); } prefabContainer = new GameObject(); prefabContainer.SetActive(false); ((Object)prefabContainer).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)prefabContainer); RegisterCustomScripts(); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); for (int i = 0; i < types.Length; i++) { MethodInfo[] methods = types[i].GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0) { methodInfo.Invoke(null, null); } } } } public static GameObject? FindBuiltinPrefabByScript<T>() where T : MonoBehaviour { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) GameObject result = null; T[] array = Resources.FindObjectsOfTypeAll<T>(); foreach (T val in array) { Scene scene = ((Component)(object)val).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { result = ((Component)(object)val).gameObject; break; } } return result; } public static void NetcodeUnload() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown Plugin.log.LogInfo("Unloading NGO for BetterSprayPaint"); NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && ((Behaviour)singleton).isActiveAndEnabled && (Object)(object)prefabContainer != (Object)null) { foreach (Transform item in prefabContainer.transform) { Transform val = item; NetworkManager.Singleton.RemoveNetworkPrefab(((Component)val).gameObject); Object.Destroy((Object)(object)((Component)val).gameObject); } Object.Destroy((Object)(object)prefabContainer); } foreach (Action cleanupAction in cleanupActions) { cleanupAction(); } cleanupActions.Clear(); } } [HarmonyPatch] internal class NetcodeInitPatch { private static bool loaded; [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "Start")] public static void GameNetworkManagerStart(GameNetworkManager __instance) { if (!loaded && (Object)(object)NetworkManager.Singleton != (Object)null) { if ((Object)(object)NgoHelper.prefabContainer == (Object)null) { NgoHelper.NetcodeInit(); } loaded = true; } } } public class SessionData : NetworkBehaviour { internal static GameObject prefab = new GameObject("SessionData"); internal static SessionData? instance = null; internal NetworkVariable<bool> allowColorChange = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> allowErasing = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> infiniteTank = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<float> tankCapacity = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<float> shakeEfficiency = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> shakingNotNeeded = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<float> range = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<float> maxSize = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> clientsCanPaintShip = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); public static bool AllowColorChange => instance?.allowColorChange?.Value ?? Plugin.AllowColorChange; public static bool AllowErasing => instance?.allowErasing?.Value ?? Plugin.AllowErasing; public static bool InfiniteTank => instance?.infiniteTank?.Value ?? Plugin.InfiniteTank; public static float TankCapacity => instance?.tankCapacity?.Value ?? Plugin.TankCapacity; public static float ShakeEfficiency => instance?.shakeEfficiency?.Value ?? Plugin.ShakeEfficiency; public static bool ShakingNotNeeded => instance?.shakingNotNeeded?.Value ?? Plugin.ShakingNotNeeded; public static float Range => instance?.range?.Value ?? Plugin.Range; public static float MaxSize => instance?.maxSize?.Value ?? Plugin.MaxSize; public static bool ClientsCanPaintShip => instance?.clientsCanPaintShip?.Value ?? Plugin.ClientsCanPaintShip; public override void OnNetworkSpawn() { instance = ((Component)this).GetComponent<SessionData>(); } public override void OnDestroy() { instance = null; } internal static void ServerSpawn() { if (NetworkManager.Singleton.IsServer && (Object)(object)instance == (Object)null) { Object.Instantiate<GameObject>(prefab).GetComponent<NetworkObject>().Spawn(false); } } internal static void Despawn(bool _) { SessionData? sessionData = instance; Object.Destroy((Object)(object)((sessionData != null) ? ((Component)sessionData).gameObject : null)); } protected override void __initializeVariables() { if (allowColorChange == null) { throw new Exception("SessionData.allowColorChange cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)allowColorChange).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)allowColorChange, "allowColorChange"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)allowColorChange); if (allowErasing == null) { throw new Exception("SessionData.allowErasing cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)allowErasing).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)allowErasing, "allowErasing"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)allowErasing); if (infiniteTank == null) { throw new Exception("SessionData.infiniteTank cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)infiniteTank).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)infiniteTank, "infiniteTank"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)infiniteTank); if (tankCapacity == null) { throw new Exception("SessionData.tankCapacity cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)tankCapacity).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)tankCapacity, "tankCapacity"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)tankCapacity); if (shakeEfficiency == null) { throw new Exception("SessionData.shakeEfficiency cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)shakeEfficiency).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)shakeEfficiency, "shakeEfficiency"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)shakeEfficiency); if (shakingNotNeeded == null) { throw new Exception("SessionData.shakingNotNeeded cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)shakingNotNeeded).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)shakingNotNeeded, "shakingNotNeeded"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)shakingNotNeeded); if (range == null) { throw new Exception("SessionData.range cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)range).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)range, "range"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)range); if (maxSize == null) { throw new Exception("SessionData.maxSize cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)maxSize).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)maxSize, "maxSize"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)maxSize); if (clientsCanPaintShip == null) { throw new Exception("SessionData.clientsCanPaintShip cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)clientsCanPaintShip).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)clientsCanPaintShip, "clientsCanPaintShip"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)clientsCanPaintShip); ((NetworkBehaviour)this).__initializeVariables(); } protected internal override string __getTypeName() { return "SessionData"; } } public class SprayPaintItemNetExt : NetworkBehaviour { private NetworkVariable<bool> _isErasing = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); private bool _localIsErasing; public NetworkVariable<float> ShakeMeter = new NetworkVariable<float>(1f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); public NetworkVariable<Color> _currentColor = new NetworkVariable<Color>(default(Color), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); private Color _localCurrentColor; public NetworkVariable<NetworkObjectReference> PlayerHeldBy = new NetworkVariable<NetworkObjectReference>(default(NetworkObjectReference), (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); public int sprayPaintMask; public Material? baseParticleMaterial; public Material? sprayEraseParticleMaterial; public Material? baseDecalMaterial; public ParticleSystem? sprayCanColorChangeParticle; private List<Action> cleanupActions = new List<Action>(); public static Dictionary<Color, WeakReference<Material>> AllDecalMaterials = new Dictionary<Color, WeakReference<Material>>(); public static Dictionary<Color, WeakReference<Material>> AllParticleMaterials = new Dictionary<Color, WeakReference<Material>>(); public List<Color> ColorPalette = new List<Color>(); private SprayPaintItem instance => ((Component)this).GetComponent<SprayPaintItem>(); public bool HeldByLocalPlayer { get { if (((GrabbableObject)instance).playerHeldBy.IsLocalPlayer()) { return ((GrabbableObject)instance).playerHeldBy.ItemSlots.Any((GrabbableObject item) => (Object)(object)item == (Object)(object)instance); } return false; } } public bool InActiveSlot { get { if ((Object)(object)((GrabbableObject)instance).playerHeldBy != (Object)null) { return (Object)(object)((GrabbableObject)instance).playerHeldBy.ItemSlots[((GrabbableObject)instance).playerHeldBy.currentItemSlot] == (Object)(object)instance; } return false; } } private static SessionData sessionData => SessionData.instance; public bool IsErasing { get { if (!HeldByLocalPlayer) { return _isErasing.Value; } return _localIsErasing; } set { if (_localIsErasing != value) { _localIsErasing = value; ToggleErasingServerRpc(value); } } } public float PaintSize { get { PlayerNetExt playerNetExt = null; if ((Object)(object)((GrabbableObject)instance).playerHeldBy != (Object)null) { playerNetExt = ((GrabbableObject)instance).playerHeldBy.NetExt(); } if ((Object)(object)playerNetExt == (Object)null) { return 1f; } return playerNetExt.PaintSize.Value; } set { if ((Object)(object)((GrabbableObject)instance).playerHeldBy != (Object)null) { PlayerNetExt playerNetExt = ((GrabbableObject)instance).playerHeldBy.NetExt(); if ((Object)(object)playerNetExt != (Object)null) { playerNetExt.PaintSize.Value = value; } else { Plugin.log.LogWarning("Tried to set PaintSize but playerHeldBy.NetExt() is null"); } } else { Plugin.log.LogWarning("Tried to set PaintSize but playerHeldBy is null"); } } } public Color CurrentColor { get { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!HeldByLocalPlayer) { return _currentColor.Value; } return _localCurrentColor; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (_localCurrentColor != value) { _localCurrentColor = value; SetCurrentColorServerRpc(value); } } } [ServerRpc(RequireOwnership = false)] public void ToggleErasingServerRpc(bool active) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(2165861534u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref active, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 2165861534u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { _isErasing.Value = active; } } } public void OnChangeErasing(bool previous, bool current) { if (!HeldByLocalPlayer) { UpdateParticles(); } } [ServerRpc(RequireOwnership = false)] public void SetCurrentColorServerRpc(Color color) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3718705491u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref color); ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3718705491u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { _currentColor.Value = color; } } } [ServerRpc(RequireOwnership = false)] public void SetPlayerHeldByServerRpc(NetworkObjectReference playerRef) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(1553169032u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkObjectReference>(ref playerRef, default(ForNetworkSerializable)); ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 1553169032u, val, (RpcDelivery)0); } NetworkObject val3 = default(NetworkObject); PlayerControllerB val4 = default(PlayerControllerB); if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && ((NetworkObjectReference)(ref playerRef)).TryGet(ref val3, (NetworkManager)null) && ((Component)val3).TryGetComponent<PlayerControllerB>(ref val4)) { PlayerHeldBy.Value = playerRef; } } } public int posmod(int n, int d) { return (n % d + d) % d; } public Material DecalMaterialForColor(Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (AllDecalMaterials.TryGetValue(color, out WeakReference<Material> value) && value.TryGetTarget(out var target) && (Object)(object)target != (Object)null && target.color == color) { return target; } target = new Material(baseDecalMaterial) { color = color }; AllDecalMaterials[color] = new WeakReference<Material>(target); return target; } public Material ParticleMaterialForColor(Color color) { //IL_0005: 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_0026: 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) //IL_002e: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (AllParticleMaterials.TryGetValue(color, out WeakReference<Material> value) && value.TryGetTarget(out var target)) { return target; } target = new Material(baseParticleMaterial) { color = color }; AllParticleMaterials[color] = new WeakReference<Material>(target); return target; } public override void OnNetworkSpawn() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) ((NetworkBehaviour)this).OnNetworkSpawn(); if (!instance.isWeedKillerSprayBottle) { sprayPaintMask = Traverse.Create((object)instance).Field("sprayPaintMask").GetValue<int>(); int value = Traverse.Create((object)instance).Field<int>("sprayCanMatsIndex").Value; baseParticleMaterial = instance.particleMats[value]; baseDecalMaterial = instance.sprayCanMats[value]; if (((NetworkBehaviour)this).IsServer) { Random random = new Random(); Material val = instance.sprayCanMats[random.Next(instance.sprayCanMats.Length)]; CurrentColor = val.color; } sprayEraseParticleMaterial = new Material(baseParticleMaterial); sprayEraseParticleMaterial.color = new Color(0.5f, 0.5f, 0.5f, 1f); ColorPalette = instance.sprayCanMats.Select((Material mat) => mat.color).ToList(); Material[] sprayCanMats = instance.sprayCanMats; foreach (Material val2 in sprayCanMats) { AllDecalMaterials[val2.color] = new WeakReference<Material>(val2); } sprayCanMats = instance.particleMats; foreach (Material val3 in sprayCanMats) { AllParticleMaterials[val3.color] = new WeakReference<Material>(val3); } GameObject val4 = Object.Instantiate<GameObject>(((Component)instance.sprayCanNeedsShakingParticle).gameObject); ((Object)val4).name = "ColorChangeParticle"; sprayCanColorChangeParticle = val4.GetComponent<ParticleSystem>(); ((Component)sprayCanColorChangeParticle).transform.SetParent(((Component)instance).transform, false); MainModule main = sprayCanColorChangeParticle.main; ((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0; ((MainModule)(ref main)).startSpeedMultiplier = 2f; ((MainModule)(ref main)).startLifetimeMultiplier = 0.1f; EmissionModule emission = sprayCanColorChangeParticle.emission; ((EmissionModule)(ref emission)).rateOverTimeMultiplier = 100f; ShapeModule shape = sprayCanColorChangeParticle.shape; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; NetworkVariable<bool> isErasing = _isErasing; isErasing.OnValueChanged = (OnValueChangedDelegate<bool>)(object)Delegate.Combine((Delegate?)(object)isErasing.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<bool>(OnChangeErasing)); } } public IEnumerator ChangeColorCoroutine(Color color) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) CurrentColor = color; UpdateParticles(); if (Traverse.Create((object)instance).Field("sprayCanTank").GetValue<float>() > 0f) { sprayCanColorChangeParticle.Play(); yield return (object)new WaitForSeconds(0.1f); sprayCanColorChangeParticle.Stop(); } } public IEnumerator ChangeSizeCoroutine() { bool increase = Plugin.inputActions.SprayPaintIncreaseSize.IsPressed(); bool decrease = Plugin.inputActions.SprayPaintDecreaseSize.IsPressed(); PaintSize += (increase ? 0.1f : (-0.1f)); yield return (object)new WaitForSeconds(0.1f); while (HeldByLocalPlayer && (increase || decrease)) { increase = Plugin.inputActions.SprayPaintIncreaseSize.IsPressed(); decrease = Plugin.inputActions.SprayPaintDecreaseSize.IsPressed(); PaintSize += (increase ? 0.1f : (-0.1f)); yield return (object)new WaitForSeconds(0.025f); } } public void UpdateParticles() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) //IL_0126: 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_00d7: Unknown result type (might be due to invalid IL or missing references) ShapeModule shape = instance.sprayParticle.shape; MainModule main = instance.sprayParticle.main; float num = Mathf.Min(1.5f, PaintSize); ((MainModule)(ref main)).startSizeMultiplier = 0.5f * num; ((ShapeModule)(ref shape)).scale = new Vector3(num, num, num); Material material = ParticleMaterialForColor(CurrentColor); ((Renderer)((Component)sprayCanColorChangeParticle).GetComponent<ParticleSystemRenderer>()).material = material; if (SessionData.AllowErasing && IsErasing) { Material material2 = sprayEraseParticleMaterial; ((Renderer)((Component)instance.sprayCanNeedsShakingParticle).GetComponent<ParticleSystemRenderer>()).material = material2; ((Renderer)((Component)instance.sprayParticle).GetComponent<ParticleSystemRenderer>()).material = material2; ((ShapeModule)(ref shape)).angle = 5f; ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(50f); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.1f); } else { ((Renderer)((Component)instance.sprayCanNeedsShakingParticle).GetComponent<ParticleSystemRenderer>()).material = material; ((Renderer)((Component)instance.sprayParticle).GetComponent<ParticleSystemRenderer>()).material = material; ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(100f); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.05f); ((ShapeModule)(ref shape)).angle = 0f; } } public override void OnNetworkDespawn() { ((NetworkBehaviour)this).OnNetworkDespawn(); if (instance.isWeedKillerSprayBottle) { return; } NetworkVariable<bool> isErasing = _isErasing; isErasing.OnValueChanged = (OnValueChangedDelegate<bool>)(object)Delegate.Remove((Delegate?)(object)isErasing.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<bool>(OnChangeErasing)); foreach (Action cleanupAction in cleanupActions) { cleanupAction(); } } public void Update() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!instance.isWeedKillerSprayBottle) { if (HeldByLocalPlayer && InActiveSlot) { UpdateTooltips(); } if (!HeldByLocalPlayer && _localCurrentColor != _currentColor.Value) { _localCurrentColor = _currentColor.Value; } if (!HeldByLocalPlayer && (Object)(object)((GrabbableObject)instance).playerHeldBy != (Object)null) { UpdateParticles(); } } } public void UpdateTooltips() { if (HUDManager.Instance.controlTipLines.Length >= 4) { ((TMP_Text)HUDManager.Instance.controlTipLines[3]).text = $"Size : {PaintSize:0.0}"; } } [ServerRpc(RequireOwnership = false)] public void UpdateShakeMeterServerRpc(float shakeMeter) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(1150776642u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref shakeMeter, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 1150776642u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { ShakeMeter.Value = shakeMeter; } } } [ServerRpc(RequireOwnership = false)] public void EraseServerRpc(Vector3 sprayPos, ServerRpcParams rpc = default(ServerRpcParams)) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(1724506213u, rpc, (RpcDelivery)0); ((FastBufferWriter)(ref val)).WriteValueSafe(ref sprayPos); ((NetworkBehaviour)this).__endSendServerRpc(ref val, 1724506213u, rpc, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && SessionData.AllowErasing) { EraseClientRpc(sprayPos); } } } [ClientRpc] public void EraseClientRpc(Vector3 sprayPos) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(641093140u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref sprayPos); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 641093140u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && SessionData.AllowErasing && !HeldByLocalPlayer) { Patches.EraseSprayPaintAtPoint(instance,