r2mods/ilspy_dump/ror2_csproj/RoR2/OutsideInteractableLocker.cs

241 lines
5.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using HG;
using RoR2.CharacterAI;
using UnityEngine;
using UnityEngine.Networking;
namespace RoR2;
public class OutsideInteractableLocker : MonoBehaviour
{
private struct Candidate
{
public PurchaseInteraction purchaseInteraction;
public float distanceSqr;
}
private class LockInfo
{
public GameObject lockObj;
public float distSqr;
public bool IsLocked()
{
return lockObj != null;
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
private struct CandidateDistanceCompararer : IComparer<Candidate>
{
public int Compare(Candidate a, Candidate b)
{
return a.distanceSqr.CompareTo(b.distanceSqr);
}
}
[Tooltip("The networked object which will be instantiated to lock purchasables.")]
public GameObject lockPrefab;
[Tooltip("How long to wait between steps.")]
public float updateInterval = 0.1f;
[Tooltip("Whether or not to invert the requirements.")]
public bool lockInside;
private Dictionary<PurchaseInteraction, GameObject> lockObjectMap;
private Dictionary<LemurianEggController, LockInfo> eggLockInfoMap;
private float updateTimer;
private IEnumerator currentCoroutine;
public float radius { get; set; }
private void Awake()
{
if (NetworkServer.active)
{
lockObjectMap = new Dictionary<PurchaseInteraction, GameObject>();
if (DevotionInventoryController.isDevotionEnable)
{
eggLockInfoMap = new Dictionary<LemurianEggController, LockInfo>();
}
}
else
{
base.enabled = false;
}
}
private void OnEnable()
{
if (NetworkServer.active)
{
currentCoroutine = ChestLockCoroutine();
updateTimer = updateInterval;
}
}
private void OnDisable()
{
if (NetworkServer.active)
{
currentCoroutine = null;
UnlockAll();
}
}
private void FixedUpdate()
{
updateTimer -= Time.fixedDeltaTime;
if (updateTimer <= 0f)
{
updateTimer = updateInterval;
currentCoroutine?.MoveNext();
}
}
private void LockPurchasable(PurchaseInteraction purchaseInteraction)
{
if (!purchaseInteraction.lockGameObject)
{
GameObject gameObject = UnityEngine.Object.Instantiate(lockPrefab, purchaseInteraction.transform.position, Quaternion.identity);
NetworkServer.Spawn(gameObject);
purchaseInteraction.NetworklockGameObject = gameObject;
lockObjectMap.Add(purchaseInteraction, gameObject);
}
}
private void UnlockPurchasable(PurchaseInteraction purchaseInteraction)
{
if (lockObjectMap.TryGetValue(purchaseInteraction, out var value) && !(value != purchaseInteraction.lockGameObject))
{
UnityEngine.Object.Destroy(value);
lockObjectMap.Remove(purchaseInteraction);
}
}
private void UnlockAll()
{
foreach (GameObject value in lockObjectMap.Values)
{
UnityEngine.Object.Destroy(value);
}
lockObjectMap.Clear();
if (eggLockInfoMap == null)
{
return;
}
foreach (KeyValuePair<LemurianEggController, LockInfo> item in eggLockInfoMap)
{
UnlockLemurianEgg(item.Key);
}
eggLockInfoMap.Clear();
}
private void LockLemurianEgg(LemurianEggController egg)
{
GameObject gameObject = UnityEngine.Object.Instantiate(lockPrefab, egg.transform.position, Quaternion.identity);
NetworkServer.Spawn(gameObject);
eggLockInfoMap[egg].lockObj = gameObject;
egg.SetInteractability(interactable: false);
}
private void UnlockLemurianEgg(LemurianEggController egg)
{
LockInfo lockInfo = eggLockInfoMap[egg];
if ((bool)lockInfo.lockObj)
{
NetworkServer.Destroy(lockInfo.lockObj);
lockInfo.lockObj = null;
}
egg.SetInteractability(interactable: true);
}
private IEnumerator ChestLockCoroutine()
{
Candidate[] candidates = new Candidate[64];
int candidatesCount = 0;
if (DevotionInventoryController.isDevotionEnable)
{
foreach (LemurianEggController instances in InstanceTracker.GetInstancesList<LemurianEggController>())
{
LockInfo lockInfo = new LockInfo();
lockInfo.lockObj = null;
lockInfo.distSqr = (instances.transform.position - base.transform.position).sqrMagnitude;
eggLockInfoMap[instances] = lockInfo;
}
}
while (true)
{
Vector3 position = base.transform.position;
if (DevotionInventoryController.isDevotionEnable)
{
foreach (KeyValuePair<LemurianEggController, LockInfo> item in eggLockInfoMap)
{
float num = radius * radius;
LockInfo value = item.Value;
bool flag = value.distSqr <= num;
value.IsLocked();
if (flag != lockInside)
{
UnlockLemurianEgg(item.Key);
}
else
{
LockLemurianEgg(item.Key);
}
}
}
List<PurchaseInteraction> instancesList = InstanceTracker.GetInstancesList<PurchaseInteraction>();
int num2 = candidatesCount;
candidatesCount = instancesList.Count;
ArrayUtils.EnsureCapacity(ref candidates, candidatesCount);
for (int j = num2; j < candidatesCount; j++)
{
candidates[j] = default(Candidate);
}
for (int k = 0; k < candidatesCount; k++)
{
PurchaseInteraction purchaseInteraction = instancesList[k];
candidates[k] = new Candidate
{
purchaseInteraction = purchaseInteraction,
distanceSqr = (purchaseInteraction.transform.position - position).sqrMagnitude
};
}
yield return null;
Array.Sort(candidates, 0, candidatesCount, default(CandidateDistanceCompararer));
yield return null;
int i = 0;
while (i < candidatesCount)
{
PurchaseInteraction purchaseInteraction2 = candidates[i].purchaseInteraction;
if ((bool)purchaseInteraction2)
{
float num3 = radius * radius;
if (candidates[i].distanceSqr <= num3 != lockInside || !purchaseInteraction2.available)
{
UnlockPurchasable(purchaseInteraction2);
}
else
{
LockPurchasable(purchaseInteraction2);
}
yield return null;
}
int num4 = i + 1;
i = num4;
}
yield return null;
}
}
}