using System;
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 BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CrackCartUnloader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CrackCartUnloader")]
[assembly: AssemblyTitle("CrackCartUnloader")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace CrackCartUnloader
{
[BepInPlugin("com.altma.crackhost.cartunloader", "CRACK Cart Unloader", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "com.altma.crackhost.cartunloader";
public const string Name = "CRACK Cart Unloader";
public const string Version = "0.1.0";
internal static ManualLogSource Log;
internal static ConfigEntry<float> Radius;
internal static ConfigEntry<float> GlideSeconds;
internal static ConfigEntry<bool> ReturnEmpties;
private void Awake()
{
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
Radius = ((BaseUnityPlugin)this).Config.Bind<float>("Unloader", "Radius", 5f, "How close (metres) a cart has to be to the deposit conveyor to be unloaded.");
GlideSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Unloader", "GlideSeconds", 0.6f, "How long each bucket takes to move between cart and belt.");
ReturnEmpties = ((BaseUnityPlugin)this).Config.Bind<bool>("Unloader", "ReturnEmpties", true, "Load emptied buckets back onto the cart as they come out of the machine.");
new Harmony("com.altma.crackhost.cartunloader").PatchAll(typeof(Plugin).Assembly);
Log.LogInfo((object)"CRACK Cart Unloader 0.1.0 loaded");
}
}
[HarmonyPatch(typeof(DepositMachine), "OnStartServer")]
internal static class AttachPatch
{
private static void Postfix(DepositMachine __instance)
{
Unloader.Attach(__instance);
}
}
internal sealed class Unloader : MonoBehaviour
{
private sealed class Returning
{
public Bucket bucket;
public CartCargoBed bed;
public bool seized;
public float waited;
}
private const float SeizeTimeout = 5f;
private const float ExitSettle = 0.4f;
private const float ReturnRangeFactor = 2f;
private static readonly FieldRef<DepositMachine, BadgeReader> ReaderRef = AccessTools.FieldRefAccess<DepositMachine, BadgeReader>("badgeReader");
private static readonly FieldRef<DepositMachine, Transform> EnterStartRef = AccessTools.FieldRefAccess<DepositMachine, Transform>("enterStart");
private static readonly FieldRef<DepositMachine, bool> AcceptingRef = AccessTools.FieldRefAccess<DepositMachine, bool>("_accepting");
private static readonly FieldRef<CartCargoBed, Transform[]> SlotsRef = AccessTools.FieldRefAccess<CartCargoBed, Transform[]>("slots");
private static readonly FieldInfo BedsField = AccessTools.Field(typeof(CartCargoBed), "Beds");
private static readonly FieldInfo ServerSlotsField = AccessTools.Field(typeof(CartCargoBed), "_server");
private static readonly FieldInfo SlotItemField = AccessTools.Field(ServerSlotsField.FieldType.GetElementType(), "item");
private DepositMachine _machine;
private Coroutine _feeding;
private bool _badgeWasIn;
private readonly List<Returning> _returning = new List<Returning>();
private Vector3 Intake
{
get
{
//IL_003b: 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)
if (!((Object)(object)EnterStartRef.Invoke(_machine) != (Object)null))
{
return ((Component)_machine).transform.position;
}
return EnterStartRef.Invoke(_machine).position;
}
}
internal static void Attach(DepositMachine machine)
{
if (!((Object)(object)machine == (Object)null) && !((Object)(object)((Component)machine).GetComponent<Unloader>() != (Object)null))
{
((Component)machine).gameObject.AddComponent<Unloader>()._machine = machine;
}
}
private bool BadgeIn()
{
BadgeReader val = ReaderRef.Invoke(_machine);
if ((Object)(object)val != (Object)null)
{
return val.HasBadgeAuthoritative;
}
return false;
}
private bool InRange(CartCargoBed bed, float radius)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//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)
if ((Object)(object)bed != (Object)null)
{
Vector3 val = ((Component)bed).transform.position - Intake;
return ((Vector3)(ref val)).sqrMagnitude <= radius * radius;
}
return false;
}
private CartCargoBed NearestBed()
{
return (BedsField.GetValue(null) as List<CartCargoBed>)?.Where((CartCargoBed b) => (Object)(object)b != (Object)null && ((Behaviour)b).isActiveAndEnabled && (int)b.Accepts == 0 && InRange(b, Plugin.Radius.Value)).OrderBy(delegate(CartCargoBed b)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: 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)
Vector3 val = ((Component)b).transform.position - Intake;
return ((Vector3)(ref val)).sqrMagnitude;
}).FirstOrDefault();
}
private static HeldItem SlotItem(CartCargoBed bed, int slot)
{
if (!(ServerSlotsField.GetValue(bed) is Array array) || slot >= array.Length)
{
return null;
}
object value = array.GetValue(slot);
if (value == null)
{
return null;
}
object? value2 = SlotItemField.GetValue(value);
return (HeldItem)((value2 is HeldItem) ? value2 : null);
}
private static int FindSlot(CartCargoBed bed, Func<int, bool> match)
{
int num = (ServerSlotsField.GetValue(bed) as Array)?.Length ?? 0;
for (int i = 0; i < num; i++)
{
if (match(i))
{
return i;
}
}
return -1;
}
private IEnumerator Feed()
{
CartCargoBed bed = NearestBed();
Transform drop = (from p in DepositDropPoint.All.Where((DepositDropPoint p) => (Object)(object)p != (Object)null).OrderBy(delegate(DepositDropPoint p)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: 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)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = ((Component)p).transform.position - Intake;
return ((Vector3)(ref val)).sqrMagnitude;
})
select ((Component)p).transform).FirstOrDefault();
if ((Object)(object)bed == (Object)null || (Object)(object)drop == (Object)null)
{
_feeding = null;
yield break;
}
Plugin.Log.LogInfo((object)("Unloading '" + ((Object)bed).name + "' at '" + ((Object)_machine).name + "'"));
while (BadgeIn() && InRange(bed, Plugin.Radius.Value))
{
int slot = FindSlot(bed, delegate(int i)
{
HeldItem obj = SlotItem(bed, i);
Bucket val = (Bucket)(object)((obj is Bucket) ? obj : null);
return val != null && val.CurrentUnits > 0;
});
if (slot < 0)
{
break;
}
Bucket bucket = (Bucket)SlotItem(bed, slot);
while (AcceptingRef.Invoke(_machine))
{
yield return null;
}
if (!BadgeIn())
{
break;
}
bed.ServerReleaseSlot(slot, false);
yield return Glide(bucket, drop.position, Quaternion.Euler(0f, ((Component)bucket).transform.eulerAngles.y, 0f));
Release(bucket, physics: true);
Returning entry = new Returning
{
bucket = bucket,
bed = bed
};
float t = 0f;
while (!DepositMachine.InAnyPipeline(((NetworkBehaviour)bucket).netId))
{
float num;
t = (num = t + Time.deltaTime);
if (!(num < 5f))
{
break;
}
yield return null;
}
if (!DepositMachine.InAnyPipeline(((NetworkBehaviour)bucket).netId))
{
break;
}
entry.seized = true;
if (Plugin.ReturnEmpties.Value)
{
_returning.Add(entry);
}
}
_feeding = null;
}
private void Update()
{
if (!NetworkServer.active || (Object)(object)_machine == (Object)null)
{
return;
}
bool flag = BadgeIn();
if (flag && !_badgeWasIn && _feeding == null)
{
_feeding = ((MonoBehaviour)this).StartCoroutine(Feed());
}
_badgeWasIn = flag;
for (int num = _returning.Count - 1; num >= 0; num--)
{
Returning r = _returning[num];
if ((Object)(object)r.bucket == (Object)null || (Object)(object)r.bed == (Object)null)
{
_returning.RemoveAt(num);
}
else if (!DepositMachine.InAnyPipeline(((NetworkBehaviour)r.bucket).netId))
{
if ((Object)(object)((HeldItem)r.bucket).Holder != (Object)null || RobotCargo.IsCarried((Component)(object)r.bucket))
{
_returning.RemoveAt(num);
}
else if (!((r.waited += Time.deltaTime) < 0.4f))
{
_returning.RemoveAt(num);
if (InRange(r.bed, Plugin.Radius.Value * 2f))
{
int num2 = FindSlot(r.bed, (int s) => (Object)(object)SlotItem(r.bed, s) == (Object)null && (Object)(object)SlotsRef.Invoke(r.bed)[s] != (Object)null);
if (num2 >= 0)
{
((MonoBehaviour)this).StartCoroutine(Stow(r.bucket, r.bed, num2));
}
}
}
}
}
}
private IEnumerator Stow(Bucket bucket, CartCargoBed bed, int slot)
{
Transform val = SlotsRef.Invoke(bed)[slot];
yield return Glide(bucket, val.position, val.rotation);
Release(bucket, physics: false);
if (!bed.ServerStow((HeldItem)(object)bucket, slot))
{
Release(bucket, physics: true);
}
}
private IEnumerator Glide(Bucket bucket, Vector3 to, Quaternion toRot)
{
//IL_0015: 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)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
((HeldItem)bucket).ServerGiveToHost();
((HeldItem)bucket).ServerEnsureNetworkTransform();
RobotCargo.ForceClaim((Component)(object)bucket, (Component)(object)this);
RobotCargo.SetCarried((Component)(object)bucket, (Component)(object)this);
Rigidbody component = ((Component)bucket).GetComponent<Rigidbody>();
if ((Object)(object)component != (Object)null)
{
component.isKinematic = true;
component.linearVelocity = Vector3.zero;
component.angularVelocity = Vector3.zero;
}
Vector3 from = ((Component)bucket).transform.position;
Quaternion fromRot = ((Component)bucket).transform.rotation;
float lift = Mathf.Clamp(Vector3.Distance(from, to) * 0.25f, 0.3f, 1f);
float duration = Mathf.Max(0.05f, Plugin.GlideSeconds.Value);
for (float t = 0f; t < 1f; t += Time.deltaTime / duration)
{
if (!((Object)(object)bucket != (Object)null))
{
break;
}
float num = t * t * (3f - 2f * t);
((Component)bucket).transform.SetPositionAndRotation(Vector3.Lerp(from, to, num) + Vector3.up * (lift * 4f * num * (1f - num)), Quaternion.Slerp(fromRot, toRot, num));
yield return null;
}
if ((Object)(object)bucket != (Object)null)
{
((Component)bucket).transform.SetPositionAndRotation(to, toRot);
}
}
private void Release(Bucket bucket, bool physics)
{
//IL_0034: 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)
if (!((Object)(object)bucket == (Object)null))
{
RobotCargo.ClearCarried((Component)(object)bucket, (Component)(object)this);
RobotCargo.Release((Component)(object)bucket, (Component)(object)this);
Rigidbody component = ((Component)bucket).GetComponent<Rigidbody>();
if (!((Object)(object)component == (Object)null) && physics)
{
component.isKinematic = false;
component.linearVelocity = Vector3.zero;
component.angularVelocity = Vector3.zero;
}
}
}
}
}