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);
}
}