Decompiled source of ClientSideBlock v1.1.2

plugins\ClientSideBlock.dll

Decompiled 6 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Landfall.Network;
using On;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnboundLib;
using UnboundLib.Networking;
using UnboundLib.Utils.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
internal class ThisAssembly
{
	[GeneratedCode("ThisAssembly.Project", "1.0.0")]
	[CompilerGenerated]
	public static class Project
	{
		public const string RootNamespace = "ClientSideBlock";

		public const string AssemblyName = "ClientSideBlock";

		public const string TargetFrameworkVersion = "v4.7.2";

		public const string TargetFrameworkIdentifier = ".NETFramework";

		public const string TargetFrameworkMoniker = ".NETFramework,Version=v4.7.2";

		public const string Version = "1.1.2";
	}
}
namespace ClientSideBlock;

[BepInPlugin("io.olavim.rounds.clientsideblock", "ClientSideBlock", "1.1.2")]
public sealed class ClientSideBlock : BaseUnityPlugin
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static hook_Awake <>9__18_0;

		public static UnityAction <>9__19_0;

		public static UnityAction<bool> <>9__20_0;

		internal void <Awake>b__18_0(orig_Awake orig, MainMenuHandler self)
		{
			orig.Invoke(self);
			OptimisticSyncEnabled = s_optimisticSyncEnabledConfig.Value;
		}

		internal void <Start>b__19_0()
		{
		}

		internal void <BuildSettingsGUI>b__20_0(bool value)
		{
			s_optimisticSyncEnabledConfig.Value = value;
			OptimisticSyncEnabled = value;
		}
	}

	public const string ModId = "io.olavim.rounds.clientsideblock";

	public const string ModName = "ClientSideBlock";

	public const string ModNameUI = "Client Side Block";

	public const string ModVersion = "1.1.2";

	internal const int OptimisticSyncAdditionalDelay = 20;

	private static readonly string[] OptimisticSyncDescription = new string[2] { "Enable to make damaging and blocking feel more responsive for the shooter.", "Disable if players have highly fluctuating ping and you experience issues with blocking." };

	private static ConfigEntry<bool> s_optimisticSyncEnabledConfig { get; set; }

	internal static bool OptimisticSyncEnabled { get; set; }

	internal static ClientSideBlock Instance { get; private set; }

	private void Awake()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Expected O, but got Unknown
		//IL_0059: 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)
		//IL_0064: Expected O, but got Unknown
		Instance = this;
		Harmony val = new Harmony("io.olavim.rounds.clientsideblock");
		val.PatchAll();
		s_optimisticSyncEnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("ClientSideBlock", "optimisticSyncing", true, string.Join(" ", OptimisticSyncDescription));
		object obj = <>c.<>9__18_0;
		if (obj == null)
		{
			hook_Awake val2 = delegate(orig_Awake orig, MainMenuHandler self)
			{
				orig.Invoke(self);
				OptimisticSyncEnabled = s_optimisticSyncEnabledConfig.Value;
			};
			<>c.<>9__18_0 = val2;
			obj = (object)val2;
		}
		MainMenuHandler.Awake += (hook_Awake)obj;
	}

	private void Start()
	{
		//IL_001a: 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_0025: Expected O, but got Unknown
		object obj = <>c.<>9__19_0;
		if (obj == null)
		{
			UnityAction val = delegate
			{
			};
			<>c.<>9__19_0 = val;
			obj = (object)val;
		}
		Unbound.RegisterMenu("Client Side Block", (UnityAction)obj, (Action<GameObject>)BuildSettingsGUI, (GameObject)null, false);
		Unbound.RegisterHandshake("io.olavim.rounds.clientsideblock", (Action)OnHandShakeCompleted);
	}

	private void BuildSettingsGUI(GameObject menu)
	{
		TextMeshProUGUI val = default(TextMeshProUGUI);
		MenuHandler.CreateText("Client Side Block", menu, ref val, 60, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText(" ", menu, ref val, 24, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText("Optimistic Syncing", menu, ref val, 40, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText(OptimisticSyncDescription[0], menu, ref val, 24, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateText(OptimisticSyncDescription[1], menu, ref val, 24, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
		MenuHandler.CreateToggle(s_optimisticSyncEnabledConfig.Value, "Enable", menu, (UnityAction<bool>)delegate(bool value)
		{
			s_optimisticSyncEnabledConfig.Value = value;
			OptimisticSyncEnabled = value;
		}, 30, false, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null);
	}

	private void OnHandShakeCompleted()
	{
		if (PhotonNetwork.IsMasterClient)
		{
			NetworkingManager.RPC_Others(typeof(ClientSideBlock), "SyncSettings", new object[1] { OptimisticSyncEnabled });
		}
	}

	[UnboundRPC]
	private static void SyncSettings(bool optimisticSyncEnabled)
	{
		OptimisticSyncEnabled = optimisticSyncEnabled;
	}

	internal static IEnumerator GetTargetBlocked(ProjectileHit hit, int targetViewId)
	{
		return OptimisticSyncEnabled ? GetTargetBlockedOptimistic(hit, targetViewId) : GetTargetBlockedPessimistic(hit, targetViewId);
	}

	private static IEnumerator GetTargetBlockedOptimistic(ProjectileHit hit, int targetViewId)
	{
		PhotonView targetView = PhotonNetwork.GetPhotonView(targetViewId);
		if (targetView.IsMine)
		{
			hit.GetExtraData().IsBlockingAnswered[targetViewId] = true;
			hit.GetExtraData().IsBlocking[targetViewId] = ((Component)targetView).GetComponent<Block>().IsBlocking();
			yield break;
		}
		hit.GetExtraData().IsBlockingAnswered[targetViewId] = false;
		int myPing = (int)PhotonNetwork.LocalPlayer.CustomProperties[(object)"Ping"];
		int targetPing = (int)targetView.Owner.CustomProperties[(object)"Ping"];
		float delayToTarget = (float)(myPing + targetPing) / 2f;
		yield return (object)new WaitForSeconds((delayToTarget + 20f) / 1000f);
		hit.GetExtraData().IsBlockingAnswered[targetViewId] = true;
		hit.GetExtraData().IsBlocking[targetViewId] = ((Component)targetView).GetComponent<Block>().IsBlocking();
	}

	private static IEnumerator GetTargetBlockedPessimistic(ProjectileHit hit, int targetViewId)
	{
		hit.GetExtraData().IsBlockingAnswered[targetViewId] = false;
		NetworkingManager.RPC(typeof(ClientSideBlock), "RPC_AskIsBlocking", new object[2]
		{
			hit.view.ViewID,
			targetViewId
		});
		PhotonNetwork.SendAllOutgoingCommands();
		while (!hit.GetExtraData().IsBlockingAnswered[targetViewId])
		{
			yield return null;
		}
	}

	[UnboundRPC]
	private static void RPC_AskIsBlocking(int projectileViewId, int targetViewId)
	{
		PhotonView photonView = PhotonNetwork.GetPhotonView(targetViewId);
		if (photonView.IsMine)
		{
			bool flag = ((Component)photonView).GetComponent<Block>().IsBlocking();
			NetworkingManager.RPC(typeof(ClientSideBlock), "RPC_AnswerIsBlocking", new object[3] { projectileViewId, targetViewId, flag });
			PhotonNetwork.SendAllOutgoingCommands();
		}
	}

	[UnboundRPC]
	private static void RPC_AnswerIsBlocking(int projectileViewId, int targetViewId, bool isBlocking)
	{
		PhotonView photonView = PhotonNetwork.GetPhotonView(projectileViewId);
		if (photonView.IsMine)
		{
			ProjectileHit component = ((Component)photonView).GetComponent<ProjectileHit>();
			component.GetExtraData().IsBlockingAnswered[targetViewId] = true;
			component.GetExtraData().IsBlocking[targetViewId] = isBlocking;
		}
	}
}
[BepInPlugin("io.olavim.rounds.clientsideblock.debug", "ClientSideBlockDebug", "1.0.0")]
public sealed class ClientSideBlockDebug : BaseUnityPlugin
{
	public const string ModId = "io.olavim.rounds.clientsideblock.debug";

	public const string ModName = "ClientSideBlockDebug";

	public const string ModVersion = "1.0.0";

	private void Start()
	{
		bool autoHost = Environment.GetCommandLineArgs().Any((string arg) => arg == "-autoHost");
		int connectArgIdx = Array.FindIndex(Environment.GetCommandLineArgs(), (string arg) => arg == "-autoConnect");
		ExtensionMethods.ExecuteAfterSeconds((MonoBehaviour)(object)this, 1f, (Action)delegate
		{
			if (autoHost)
			{
				GameObject val = GameObject.Find("/Game/UI/UI_MainMenu/Canvas/ListSelector/Online/Group/Invite friend");
				Debug.Log((object)val);
				((UnityEvent)val.GetComponent<Button>().onClick).Invoke();
			}
			else if (connectArgIdx != -1)
			{
				string[] array = Environment.GetCommandLineArgs()[connectArgIdx + 1].Split(new char[1] { ':' });
				NetworkConnectionHandler.instance.ForceRegionJoin(array[0], array[1]);
			}
		});
	}
}
[HarmonyPatch(typeof(NetworkConnectionHandler))]
internal static class Debug_NetworkConnectionHandlerPatch
{
	[HarmonyPatch("CreateRoom")]
	[HarmonyPrefix]
	private static bool CreateRoomPrefix(RoomOptions roomOptions, ClientSteamLobby ___m_SteamLobby, ref bool ___m_ForceRegion)
	{
		if (___m_SteamLobby == null)
		{
			string text = "1234";
			int num = Array.FindIndex(Environment.GetCommandLineArgs(), (string arg) => arg == "-autoHost");
			if (num != -1)
			{
				string[] array = Environment.GetCommandLineArgs()[num + 1].Split(new char[1] { ':' });
				RegionSelector.region = array[0];
				___m_ForceRegion = true;
				text = array[1];
			}
			PhotonNetwork.CreateRoom(text, roomOptions, (TypedLobby)null, (string[])null);
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(ProjectileHit))]
internal static class ProjectileHitPatch
{
	[HarmonyPatch("Hit")]
	[HarmonyPrefix]
	private static bool HitPrefix(ProjectileHit __instance, MoveTransform ___move, List<HealthHandler> ___playersHit, HitInfo hit, bool forceCall)
	{
		if (!__instance.GetExtraData().HitPending)
		{
			__instance.GetExtraData().HitPending = true;
			((MonoBehaviour)ClientSideBlock.Instance).StartCoroutine(HitCoroutine(__instance, ___move, ___playersHit, hit, forceCall));
		}
		return false;
	}

	private static IEnumerator HitCoroutine(ProjectileHit hit, MoveTransform move, List<HealthHandler> playersHit, HitInfo hitInfo, bool forceCall)
	{
		Transform transform = hitInfo.transform;
		HealthHandler healthHandler = ((transform != null) ? ((Component)transform).GetComponent<HealthHandler>() : null);
		if (Object.op_Implicit((Object)(object)healthHandler) && playersHit.Contains(healthHandler))
		{
			hit.GetExtraData().HitPending = false;
			yield break;
		}
		bool wasBlocked = false;
		Vector2 origVelocity = Vector2.op_Implicit(move.velocity);
		if (hit.view.IsMine)
		{
			move.velocity = Vector2.op_Implicit(Vector2.zero);
		}
		Transform transform2 = hitInfo.transform;
		int? obj;
		if (transform2 == null)
		{
			obj = null;
		}
		else
		{
			PhotonView component = ((Component)transform2.root).GetComponent<PhotonView>();
			obj = ((component != null) ? new int?(component.ViewID) : null);
		}
		int targetViewId = obj ?? (-1);
		int targetColliderIdx = -1;
		if (targetViewId == -1)
		{
			Collider2D[] colliders = ((Component)MapManager.instance.currentMap.Map).GetComponentsInChildren<Collider2D>();
			targetColliderIdx = Array.FindIndex(colliders, (Collider2D c) => (Object)(object)c == (Object)(object)hitInfo.collider);
		}
		if (Object.op_Implicit((Object)(object)healthHandler))
		{
			if (hit.view.IsMine)
			{
				((Component)hit).gameObject.SetActive(false);
				yield return ClientSideBlock.GetTargetBlocked(hit, targetViewId);
				wasBlocked = hit.GetExtraData().IsBlocking[targetViewId];
				((Component)hit).gameObject.SetActive(true);
			}
			hit.AddPlayerToHeld(healthHandler);
		}
		if (!hit.view.IsMine && !forceCall)
		{
			hit.GetExtraData().HitPending = false;
		}
		else if (hit.sendCollisions)
		{
			hit.view.RPC("RPCA_DoHit", (RpcTarget)0, new object[6] { hitInfo.point, hitInfo.normal, origVelocity, targetViewId, targetColliderIdx, wasBlocked });
			PhotonNetwork.SendAllOutgoingCommands();
		}
		else
		{
			hit.RPCA_DoHit(hitInfo.point, hitInfo.normal, origVelocity, targetViewId, targetColliderIdx, wasBlocked);
		}
	}

	[HarmonyPatch("RPCA_DoHit")]
	[HarmonyPostfix]
	private static void DoHitPostfix(ProjectileHit __instance)
	{
		__instance.GetExtraData().HitPending = false;
	}
}
[HarmonyPatch(typeof(SyncPlayerMovement))]
internal static class SyncPlayerMovementPatch
{
	[HarmonyPatch("SendBlock", new Type[]
	{
		typeof(BlockTriggerType),
		typeof(bool)
	})]
	[HarmonyPostfix]
	private static void SendBlock1Postfix()
	{
		PhotonNetwork.SendAllOutgoingCommands();
	}

	[HarmonyPatch("SendBlock", new Type[]
	{
		typeof(BlockTriggerType),
		typeof(bool),
		typeof(bool)
	})]
	[HarmonyPostfix]
	private static void SendBlock2Postfix()
	{
		PhotonNetwork.SendAllOutgoingCommands();
	}
}
internal static class ProjectileHitExtensions
{
	internal class ProjectileHitExtraData
	{
		public bool HitPending { get; set; } = false;


		public Dictionary<int, bool> IsBlockingAnswered { get; } = new Dictionary<int, bool>();


		public Dictionary<int, bool> IsBlocking { get; } = new Dictionary<int, bool>();

	}

	private static ConditionalWeakTable<ProjectileHit, ProjectileHitExtraData> s_extraData = new ConditionalWeakTable<ProjectileHit, ProjectileHitExtraData>();

	public static ProjectileHitExtraData GetExtraData(this ProjectileHit projectileHit)
	{
		return s_extraData.GetOrCreateValue(projectileHit);
	}
}