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 BepInEx.NET.Common;
using BepInExResoniteShim;
using Elements.Core;
using FrooxEngine;
using FrooxEngine.Undo;
using HarmonyLib;
using SkyFrost.Base;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")]
[assembly: AssemblyCompany("art0007i")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5+33944bc83e7f3f769600605413ffe6e415852ad4")]
[assembly: AssemblyProduct("DuplicateFix")]
[assembly: AssemblyTitle("DuplicateFix")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/art0007i/DuplicateFix")]
[assembly: AssemblyVersion("1.0.5.0")]
[module: RefSafetyRules(11)]
namespace DuplicateFix;
public static class DuplicateExtensions
{
private static readonly global::System.Type InternalReferences = typeof(Worker).GetNestedType("InternalReferences", AccessTools.all);
private static readonly MethodInfo RunDuplicate = typeof(Component).GetMethod("RunDuplicate", AccessTools.all);
public static void MultiDuplicate(this global::System.Collections.Generic.IEnumerable<Slot> toDuplicate, List<Slot> newSlots, Slot duplicateRoot = null, bool keepGlobalTransform = true, DuplicationSettings settings = null, bool duplicateAsLocal = false)
{
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Expected O, but got Unknown
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_026a: Unknown result type (might be due to invalid IL or missing references)
//IL_026f: Unknown result type (might be due to invalid IL or missing references)
if (Enumerable.Any<Slot>(toDuplicate, (Func<Slot, bool>)((Slot x) => x.IsRootSlot)))
{
throw new global::System.Exception("Cannot duplicate root slot");
}
if (duplicateRoot != null && Enumerable.Any<Slot>(toDuplicate, (Func<Slot, bool>)((Slot x) => duplicateRoot.IsChildOf(x, false))))
{
throw new global::System.Exception("Target for the duplicate hierarchy cannot be within the hierarchy of the source");
}
object internalReferences = InternalReferences.GetConstructor(new global::System.Type[0]).Invoke((object[])null);
HashSet<ISyncRef> hashSet = Pool.BorrowHashSet<ISyncRef>();
HashSet<Slot> hashSet2 = Pool.BorrowHashSet<Slot>();
List<Action> postDuplication = Pool.BorrowList<Action>();
CollectionExtensions.Do<Slot>(toDuplicate, (Action<Slot>)delegate(Slot x)
{
x.ForeachComponentInChildren<IDuplicationHandler>((Action<IDuplicationHandler>)delegate(IDuplicationHandler h)
{
Action val = default(Action);
h.OnBeforeDuplicate(x, ref val);
if (val != null)
{
postDuplication.Add(val);
}
}, false, true);
});
CollectionExtensions.Do<Slot>(toDuplicate, (Action<Slot>)delegate(Slot x)
{
x.GenerateHierarchy(hashSet2, false);
});
CollectionExtensions.Do<Slot>(toDuplicate, (Action<Slot>)delegate(Slot x)
{
Traverse.Create((object)x).Method("CollectInternalReferences", new object[4] { x, internalReferences, hashSet, hashSet2 }).GetValue();
});
global::System.Collections.Generic.IEnumerator<Slot> enumerator = toDuplicate.GetEnumerator();
try
{
while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
{
Slot current = enumerator.Current;
newSlots.Add((Slot)((MethodBase)typeof(Slot).GetMethod("InternalDuplicate", AccessTools.all)).Invoke((object)current, new object[5]
{
duplicateRoot ?? current.Parent ?? ((Worker)current).World.RootSlot,
internalReferences,
hashSet,
settings,
duplicateAsLocal
}));
}
}
finally
{
((global::System.IDisposable)enumerator)?.Dispose();
}
if (keepGlobalTransform)
{
global::System.Collections.Generic.IEnumerator<Slot> enumerator2 = toDuplicate.GetEnumerator();
for (int num = 0; num < newSlots.Count; num++)
{
if (!((global::System.Collections.IEnumerator)enumerator2).MoveNext())
{
break;
}
newSlots[num].CopyTransform(enumerator2.Current);
}
}
Traverse.Create(internalReferences).Method("TransferReferences", new object[1] { false }).GetValue();
List<Component> list = Pool.BorrowList<Component>();
CollectionExtensions.Do<Slot>((global::System.Collections.Generic.IEnumerable<Slot>)newSlots, (Action<Slot>)delegate(Slot x)
{
x.GetComponentsInChildren<Component>(list, (Predicate<Component>)null, false, false, (Predicate<Slot>)null);
});
Enumerator<Component> enumerator3 = list.GetEnumerator();
try
{
while (enumerator3.MoveNext())
{
Component current2 = enumerator3.Current;
((MethodBase)RunDuplicate).Invoke((object)current2, (object[])null);
}
}
finally
{
((global::System.IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
}
Pool.Return<Component>(ref list);
Pool.Return<ISyncRef>(ref hashSet);
Traverse.Create(internalReferences).Method("Dispose", global::System.Array.Empty<object>());
Enumerator<Action> enumerator4 = postDuplication.GetEnumerator();
try
{
while (enumerator4.MoveNext())
{
enumerator4.Current.Invoke();
}
}
finally
{
((global::System.IDisposable)enumerator4/*cast due to .constrained prefix*/).Dispose();
}
Pool.Return<Action>(ref postDuplication);
}
}
[ResonitePlugin("art0007i.DuplicateFix", "DuplicateFix", "1.0.5", "art0007i", "https://github.com/art0007i/DuplicateFix")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BasePlugin
{
[HarmonyPatch(typeof(Grabber), "OnFocusChanged")]
private class UserspaceTransferPatch
{
public static bool Prefix(Grabber __instance, WorldFocus focus)
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: 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)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
if (!Enabled.Value)
{
return true;
}
if (!WorldPermissionsExtensoins.CanTransferObjectsOut(((Worker)__instance).World))
{
return false;
}
Action beforeUserspaceTransfer = __instance.BeforeUserspaceTransfer;
if (beforeUserspaceTransfer != null)
{
beforeUserspaceTransfer.Invoke();
}
Traverse.Create((object)__instance).Method("CleanupGrabbed", global::System.Array.Empty<object>()).GetValue();
if ((int)focus != 0 || !__instance.IsHoldingObjects)
{
return false;
}
global::System.Collections.Generic.IEnumerator<IGrabbable> enumerator = ((global::System.Collections.Generic.IEnumerable<IGrabbable>)__instance.GrabbedObjects).GetEnumerator();
try
{
while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
{
if (((IComponent)enumerator.Current).Slot.GetComponentInChildren<IItemPermissions>((Predicate<IItemPermissions>)((IItemPermissions p) => !p.CanSave), false, false) != null)
{
return false;
}
}
}
finally
{
((global::System.IDisposable)enumerator)?.Dispose();
}
float3 localPosition = __instance.HolderSlot.LocalPosition;
float3 zero = float3.Zero;
if ((ref localPosition) != (ref zero))
{
float3 localPosition2 = __instance.HolderSlot.LocalPosition;
__instance.HolderSlot.LocalPosition = float3.Zero;
Enumerator<Slot> enumerator2 = __instance.HolderSlot.Children.GetEnumerator();
try
{
while (enumerator2.MoveNext())
{
Slot current = enumerator2.Current;
localPosition = current.LocalPosition;
current.LocalPosition = (ref localPosition) + (ref localPosition2);
}
}
finally
{
((global::System.IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
}
}
if (Userspace.TryTransferToUserspaceGrabber(__instance.HolderSlot, __instance.LinkingKey))
{
__instance.DestroyGrabbed(true);
}
return false;
}
}
[HarmonyPatch(typeof(Userspace), "Paste")]
private class UserspacePastePatch
{
public static bool Prefix(Userspace __instance, ref Job<Slot> __result, SavedGraph data, Slot source, float3 userspacePos, floatQ userspaceRot, float3 userspaceScale, World targetWorld)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: 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_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: 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_007a: Expected O, but got Unknown
if (!Enabled.Value)
{
return true;
}
Job<Slot> task = new Job<Slot>();
World world = targetWorld ?? Engine.Current.WorldManager.FocusedWorld;
world.RunSynchronously((Action)delegate
{
//IL_0013: 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)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: 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_0049: 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_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Expected O, but got Unknown
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
Slot val = null;
if (WorldPermissionsExtensoins.CanSpawnObjects(world))
{
float3 globalPosition = WorldManager.TransferPoint(userspacePos, ((Worker)Userspace.Current).World, world);
floatQ globalRotation = WorldManager.TransferRotation(userspaceRot, ((Worker)Userspace.Current).World, world);
float3 globalScale = WorldManager.TransferScale(userspaceScale, ((Worker)Userspace.Current).World, world);
Slot obj = source;
if (((obj != null) ? ((Worker)obj).World : null) == world && !((ContainerWorker<Component>)(object)source).IsDestroyed)
{
source.ActiveSelf = true;
source.GlobalPosition = globalPosition;
source.GlobalRotation = globalRotation;
source.GlobalScale = globalScale;
task.SetResultAndFinish(source);
}
else
{
val = world.AddSlot("Paste", true);
val.LoadObject(data.Root, (IRecord)null, (Slot)null, (Predicate<global::System.Type>)null, (ReferenceTranslator)null, (Func<DataTreeNode, DataTreeNode>)null);
val.GlobalPosition = globalPosition;
val.GlobalRotation = globalRotation;
val.GlobalScale = globalScale;
Traverse.Create((object)val).Method("RunOnPaste", global::System.Array.Empty<object>()).GetValue();
if (val.Name == "Holder")
{
val.Destroy(val.Parent, false);
}
}
}
if (source != null && !((ContainerWorker<Component>)(object)source).IsDestroyed)
{
World world2 = ((Worker)source).World;
Slot obj2 = source;
world2.RunSynchronously(new Action(obj2.Destroy), false, (IUpdatable)null, false);
}
task.SetResultAndFinish(val);
}, false, (IUpdatable)null, false);
__result = task;
return false;
}
}
[HarmonyPatch(typeof(InteractionHandler), "DuplicateGrabbed", new global::System.Type[] { })]
private class DuplicateFixPatch
{
public static bool Prefix(InteractionHandler __instance)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
if (!Enabled.Value)
{
return true;
}
UndoManagerExtensions.BeginUndoBatch(((Worker)__instance).World, LocaleHelper.AsLocaleKey("Undo.DuplicateGrabbed", (string)null, true, (Dictionary<string, object>)null));
List<Slot> val = Pool.BorrowList<Slot>();
List<Slot> val2 = Pool.BorrowList<Slot>();
try
{
global::System.Collections.Generic.IEnumerator<IGrabbable> enumerator = ((global::System.Collections.Generic.IEnumerable<IGrabbable>)__instance.Grabber.GrabbedObjects).GetEnumerator();
try
{
while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
{
IGrabbable current = enumerator.Current;
if (__instance.Grabber.GrabbableGetComponentInParents<IDuplicateBlock>(((IComponent)current).Slot, (Predicate<IDuplicateBlock>)null, true) == null)
{
val.Add(ObjectRootExtensions.GetObjectRoot(((IComponent)current).Slot, ((Component)__instance.Grabber).Slot, false));
}
}
}
finally
{
((global::System.IDisposable)enumerator)?.Dispose();
}
((global::System.Collections.Generic.IEnumerable<Slot>)val).MultiDuplicate(val2);
CollectionExtensions.Do<Slot>((global::System.Collections.Generic.IEnumerable<Slot>)val2, (Action<Slot>)delegate(Slot x)
{
SpawnOrDestroyExtensions.CreateSpawnUndoPoint(x, (string)null, (Action<Worker>)null);
});
CollectionExtensions.Do<IGrabbable>(Enumerable.SelectMany<Slot, IGrabbable>((global::System.Collections.Generic.IEnumerable<Slot>)val2, (Func<Slot, global::System.Collections.Generic.IEnumerable<IGrabbable>>)((Slot x) => (global::System.Collections.Generic.IEnumerable<IGrabbable>)x.GetComponentsInChildren<IGrabbable>((Predicate<IGrabbable>)null, false, false, (Predicate<Slot>)null))), (Action<IGrabbable>)delegate(IGrabbable x)
{
if (x.IsGrabbed)
{
x.Release(x.Grabber, false);
}
});
}
catch (global::System.Exception ex)
{
((Worker)__instance).Debug.Error((object)("Exception duplicating items!\n" + (object)ex), true);
}
Pool.Return<Slot>(ref val2);
Pool.Return<Slot>(ref val);
UndoManagerExtensions.EndUndoBatch(((Worker)__instance).World);
return false;
}
}
internal static ManualLogSource Log;
internal static ConfigEntry<bool> Enabled;
public override void Load()
{
Log = ((BasePlugin)this).Log;
Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "When true the mod will be enabled.");
((BasePlugin)this).HarmonyInstance.PatchAll();
}
}
public static class PluginMetadata
{
public const string GUID = "art0007i.DuplicateFix";
public const string NAME = "DuplicateFix";
public const string VERSION = "1.0.5";
public const string AUTHORS = "art0007i";
public const string REPOSITORY_URL = "https://github.com/art0007i/DuplicateFix";
}