using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using IL;
using IL.GameNetcodeStuff;
using LethalNetworkAPI;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On;
using On.GameNetcodeStuff;
using Unity.Netcode;
using UnityEngine;
using moe.sylvi.SaveItemRotations.Features;
using moe.sylvi.SaveItemRotations.NetcodePatcher;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("moe.sylvi.SaveItemRotations")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+db532e148358b75214ef624b9188e57c19c63e50")]
[assembly: AssemblyProduct("SaveItemRotations")]
[assembly: AssemblyTitle("moe.sylvi.SaveItemRotations")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
static <Module>()
{
}
}
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 moe.sylvi.SaveItemRotations
{
public class Config
{
public static Config Instance { get; internal set; }
public ConfigEntry<bool> SyncOnLoad { get; internal set; }
public Config(ConfigFile cfg)
{
Instance = this;
SyncOnLoad = cfg.Bind<bool>("General", "SyncOnLoad", true, "Whether to sync item rotations to clients when they join the game. Should only be disabled if it causes issues.");
}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("moe.sylvi.SaveItemRotations", "SaveItemRotations", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const int FormatVersion = 1;
public static Plugin Instance { get; private set; }
internal static ManualLogSource Logger { get; private set; }
private void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
Instance = this;
new Config(((BaseUnityPlugin)this).Config);
Common.Patches.Initialize();
FixItemDrop.Patches.Initialize();
SaveRotations.Patches.Initialize();
SyncRotations.Patches.Initialize();
NetcodePatcher();
Logger.LogInfo((object)"moe.sylvi.SaveItemRotations v1.0.0 has loaded!");
}
private void NetcodePatcher()
{
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
Type[] array = types;
foreach (Type type in array)
{
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
MethodInfo[] array2 = methods;
foreach (MethodInfo methodInfo in array2)
{
object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
if (customAttributes.Length != 0)
{
methodInfo.Invoke(null, null);
}
}
}
}
}
public static class SaveKeys
{
public const string FormatVersion = "moe.sylvi.SaveItemRotations_formatVersion";
public const string ParityStepsTaken = "moe.sylvi.SaveItemRotations_parityStepsTaken";
public const string ItemRotations = "moe.sylvi.SaveItemRotations_itemRotations";
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "moe.sylvi.SaveItemRotations";
public const string PLUGIN_NAME = "SaveItemRotations";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace moe.sylvi.SaveItemRotations.Features
{
public static class Common
{
public static class Patches
{
[CompilerGenerated]
private static class <>O
{
public static hook_SaveItemsInShip <0>__GameNetworkManager_SaveItemsInShip;
public static hook_SetTimeAndPlanetToSavedSettings <1>__StartOfRound_SetTimeAndPlanetToSavedSettings;
}
public static void Initialize()
{
//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_001c: Expected O, but got Unknown
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
object obj = <>O.<0>__GameNetworkManager_SaveItemsInShip;
if (obj == null)
{
hook_SaveItemsInShip val = GameNetworkManager_SaveItemsInShip;
<>O.<0>__GameNetworkManager_SaveItemsInShip = val;
obj = (object)val;
}
GameNetworkManager.SaveItemsInShip += (hook_SaveItemsInShip)obj;
object obj2 = <>O.<1>__StartOfRound_SetTimeAndPlanetToSavedSettings;
if (obj2 == null)
{
hook_SetTimeAndPlanetToSavedSettings val2 = StartOfRound_SetTimeAndPlanetToSavedSettings;
<>O.<1>__StartOfRound_SetTimeAndPlanetToSavedSettings = val2;
obj2 = (object)val2;
}
StartOfRound.SetTimeAndPlanetToSavedSettings += (hook_SetTimeAndPlanetToSavedSettings)obj2;
}
private static void GameNetworkManager_SaveItemsInShip(orig_SaveItemsInShip orig, GameNetworkManager self)
{
if (!StartOfRound.Instance.isChallengeFile)
{
SaveInitialValues(self);
}
orig.Invoke(self);
}
private static void StartOfRound_SetTimeAndPlanetToSavedSettings(orig_SetTimeAndPlanetToSavedSettings orig, StartOfRound self)
{
orig.Invoke(self);
LoadInitialValues(self);
}
}
public static int LoadedFormatVersion;
public static bool LoadedParityCheck;
public static void SaveInitialValues(GameNetworkManager gameNetworkManager)
{
ES3.Save<int>("moe.sylvi.SaveItemRotations_formatVersion", 1, gameNetworkManager.currentSaveFileName);
ES3.Save<int>("moe.sylvi.SaveItemRotations_parityStepsTaken", StartOfRound.Instance.gameStats.allStepsTaken, gameNetworkManager.currentSaveFileName);
}
public static void LoadInitialValues(StartOfRound startOfRound)
{
string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName;
if (!ES3.KeyExists("moe.sylvi.SaveItemRotations_formatVersion", currentSaveFileName))
{
LoadedFormatVersion = 0;
LoadedParityCheck = false;
Plugin.Logger.LogWarning((object)"Load | No SaveItemRotations save data found, skipping all");
return;
}
LoadedFormatVersion = ES3.Load<int>("moe.sylvi.SaveItemRotations_formatVersion", currentSaveFileName, 1);
int num = ES3.Load<int>("moe.sylvi.SaveItemRotations_parityStepsTaken", currentSaveFileName, startOfRound.gameStats.allStepsTaken);
if (num != startOfRound.gameStats.allStepsTaken)
{
LoadedParityCheck = false;
Plugin.Logger.LogWarning((object)$"Load | Steps Taken mismatch (Expected {num}, got {startOfRound.gameStats.allStepsTaken}), likely outdated save, skipping all");
}
else
{
LoadedParityCheck = true;
}
}
}
public static class FixItemDrop
{
public static class Patches
{
[CompilerGenerated]
private static class <>O
{
public static Manipulator <0>__PlayerControllerB_ThrowObjectClientRpc;
public static Func<int, int, int> <1>__Apply;
}
public static void Initialize()
{
//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_001c: Expected O, but got Unknown
object obj = <>O.<0>__PlayerControllerB_ThrowObjectClientRpc;
if (obj == null)
{
Manipulator val = PlayerControllerB_ThrowObjectClientRpc;
<>O.<0>__PlayerControllerB_ThrowObjectClientRpc = val;
obj = (object)val;
}
PlayerControllerB.ThrowObjectClientRpc += (Manipulator)obj;
}
private static void PlayerControllerB_ThrowObjectClientRpc(ILContext il)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchLdcI4(instr, -1)
}))
{
val.Emit(OpCodes.Ldarg, 5);
val.EmitDelegate<Func<int, int, int>>((Func<int, int, int>)Apply);
}
}
}
public static int Apply(int orig, int actualRotation)
{
return actualRotation;
}
}
public static class SaveRotations
{
public static class Patches
{
[CompilerGenerated]
private static class <>O
{
public static Manipulator <0>__GameNetworkManager_SaveItemsInShip;
public static Manipulator <1>__StartOfRound_LoadShipGrabbableItems;
public static hook_Update <2>__GrabbableObject_Update;
public static Action <3>__PreSave;
public static Action<GrabbableObject[], int> <4>__Save;
public static Action<GameNetworkManager> <5>__PostSave;
public static Action<int[]> <6>__PreLoad;
public static Action<int, GrabbableObject> <7>__Load;
}
public static void Initialize()
{
//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_001c: Expected O, but got Unknown
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
object obj = <>O.<0>__GameNetworkManager_SaveItemsInShip;
if (obj == null)
{
Manipulator val = GameNetworkManager_SaveItemsInShip;
<>O.<0>__GameNetworkManager_SaveItemsInShip = val;
obj = (object)val;
}
GameNetworkManager.SaveItemsInShip += (Manipulator)obj;
object obj2 = <>O.<1>__StartOfRound_LoadShipGrabbableItems;
if (obj2 == null)
{
Manipulator val2 = StartOfRound_LoadShipGrabbableItems;
<>O.<1>__StartOfRound_LoadShipGrabbableItems = val2;
obj2 = (object)val2;
}
StartOfRound.LoadShipGrabbableItems += (Manipulator)obj2;
object obj3 = <>O.<2>__GrabbableObject_Update;
if (obj3 == null)
{
hook_Update val3 = GrabbableObject_Update;
<>O.<2>__GrabbableObject_Update = val3;
obj3 = (object)val3;
}
GrabbableObject.Update += (hook_Update)obj3;
}
private static void GameNetworkManager_SaveItemsInShip(ILContext il)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
//IL_0298: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchCallOrCallvirt<Object>(instr, "FindObjectsByType")
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for GameNetworkManager.SaveItemsInShip @ Find grabbable objects");
return;
}
int grabbableObjectsLoc = -1;
if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchStloc(instr, ref grabbableObjectsLoc)
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for GameNetworkManager.SaveItemsInShip @ Get grabbable objects local");
return;
}
int[] array = new int[4];
for (int i = 0; i < array.Length; i++)
{
int loc = -1;
if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchStloc(instr, ref loc)
}))
{
Plugin.Logger.LogError((object)$"Failed IL hook for GameNetworkManager.SaveItemsInShip @ Get list {i} local");
return;
}
array[i] = loc;
}
int num = array[0];
int posLoc = array[1];
int num2 = array[2];
int num3 = array[3];
int iLoc = -1;
ILLabel val2 = default(ILLabel);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[3]
{
(Instruction instr1) => ILPatternMatchingExt.MatchLdcI4(instr1, 0),
(Instruction instr2) => ILPatternMatchingExt.MatchStloc(instr2, ref iLoc),
(Instruction instr3) => ILPatternMatchingExt.MatchBr(instr3, ref val2)
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for GameNetworkManager.SaveItemsInShip @ Get loop 'i' local");
return;
}
Instruction next = val.Next;
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchLdloc(instr, posLoc)
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for GameNetworkManager.SaveItemsInShip @ Before add item position");
return;
}
Instruction next2 = val.Next;
if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchCallOrCallvirt<ES3>(instr, "Save")
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for GameNetworkManager.SaveItemsInShip @ First save call");
return;
}
Instruction next3 = val.Next;
val.Goto(next, (MoveType)0, false);
val.EmitDelegate<Action>((Action)PreSave);
val.Goto(next2, (MoveType)0, false);
val.Emit(OpCodes.Ldloc, grabbableObjectsLoc);
val.Emit(OpCodes.Ldloc, iLoc);
val.EmitDelegate<Action<GrabbableObject[], int>>((Action<GrabbableObject[], int>)Save);
val.Goto(next3, (MoveType)0, false);
val.Emit(OpCodes.Ldarg_0);
val.EmitDelegate<Action<GameNetworkManager>>((Action<GameNetworkManager>)PostSave);
}
private static void StartOfRound_LoadShipGrabbableItems(ILContext il)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
int idsLoc = -1;
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchLdstr(instr, "shipGrabbableItemIDs")
}) || !val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchStloc(instr, ref idsLoc)
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for StartOfRound.LoadShipGrabbableItems @ Get item IDs local");
return;
}
Instruction next = val.Next;
int iLoc = -1;
ILLabel val2 = default(ILLabel);
if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[3]
{
(Instruction instr1) => ILPatternMatchingExt.MatchLdcI4(instr1, 0),
(Instruction instr2) => ILPatternMatchingExt.MatchStloc(instr2, ref iLoc),
(Instruction instr3) => ILPatternMatchingExt.MatchBr(instr3, ref val2)
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for StartOfRound.LoadShipGrabbableItems @ Get loop 'i' local");
return;
}
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchCallOrCallvirt<GameObject>(instr, "GetComponent")
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for StartOfRound.LoadShipGrabbableItems @ Grabbable object instantiation");
return;
}
int grabbableObjectLoc = -1;
if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction instr) => ILPatternMatchingExt.MatchStloc(instr, ref grabbableObjectLoc)
}))
{
Plugin.Logger.LogError((object)"Failed IL hook for StartOfRound.LoadShipGrabbableItems @ Get grabbable object local");
return;
}
Instruction next2 = val.Next;
val.Goto(next, (MoveType)0, false);
val.Emit(OpCodes.Ldloc, idsLoc);
val.EmitDelegate<Action<int[]>>((Action<int[]>)PreLoad);
val.Goto(next2, (MoveType)0, false);
val.Emit(OpCodes.Ldloc, iLoc);
val.Emit(OpCodes.Ldloc, grabbableObjectLoc);
val.EmitDelegate<Action<int, GrabbableObject>>((Action<int, GrabbableObject>)Load);
}
private static void GrabbableObject_Update(orig_Update orig, GrabbableObject self)
{
orig.Invoke(self);
Apply(self);
}
}
public static Vector3[]? LoadedItemRotations;
public static Dictionary<GrabbableObject, Vector3> NeedsItemRotation = new Dictionary<GrabbableObject, Vector3>();
public static List<Vector3>? SavedItemRotations;
public static void PreSave()
{
SavedItemRotations = new List<Vector3>();
}
public static void Save(GrabbableObject[] grabbableObjects, int i)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
GrabbableObject val = grabbableObjects[i];
SavedItemRotations?.Add(((Component)val).transform.eulerAngles);
}
public static void PostSave(GameNetworkManager gameNetworkManager)
{
if (SavedItemRotations != null)
{
ES3.Save<Vector3[]>("moe.sylvi.SaveItemRotations_itemRotations", SavedItemRotations.ToArray(), gameNetworkManager.currentSaveFileName);
}
}
public static void PreLoad(int[] ids)
{
LoadedItemRotations = null;
NeedsItemRotation = new Dictionary<GrabbableObject, Vector3>();
string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName;
if (!Common.LoadedParityCheck)
{
return;
}
if (!ES3.KeyExists("moe.sylvi.SaveItemRotations_itemRotations", currentSaveFileName))
{
Plugin.Logger.LogWarning((object)"Load | No item rotation save data found, skipping load item rotation");
return;
}
LoadedItemRotations = ES3.Load<Vector3[]>("moe.sylvi.SaveItemRotations_itemRotations", currentSaveFileName);
if (LoadedItemRotations.Length != ids.Length)
{
Plugin.Logger.LogError((object)$"Load | Item count mismatch (Expected {LoadedItemRotations.Length}, got {ids.Length}), likely outdated save, skipping load item rotation");
LoadedItemRotations = null;
}
}
public static void Load(int i, GrabbableObject grabbableObject)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
if (LoadedItemRotations != null)
{
if (i >= LoadedItemRotations.Length)
{
Plugin.Logger.LogError((object)"Load | Item index outside bounds of saved rotations, this shouldn't happen");
return;
}
NeedsItemRotation.Add(grabbableObject, LoadedItemRotations[i]);
ApplyRotationTo(grabbableObject, LoadedItemRotations[i]);
}
}
public static void Apply(GrabbableObject grabbableObject)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
if (((NetworkBehaviour)grabbableObject).IsServer && NeedsItemRotation.TryGetValue(grabbableObject, out var value))
{
ApplyRotationTo(grabbableObject, value);
NeedsItemRotation.Remove(grabbableObject);
}
}
private static void ApplyRotationTo(GrabbableObject grabbableObject, Vector3 eulerAngles)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
grabbableObject.floorYRot = -1;
((Component)grabbableObject).transform.rotation = Quaternion.Euler(((Component)grabbableObject).transform.eulerAngles.x, eulerAngles.y, ((Component)grabbableObject).transform.eulerAngles.z);
}
}
public static class SyncRotations
{
public class ItemData
{
public NetworkObjectReference NetworkObject;
public Vector3 EulerAngles;
}
public static class Patches
{
[CompilerGenerated]
private static class <>O
{
public static hook_ConnectClientToPlayerObject <0>__PlayerControllerB_ConnectClientToPlayerObject;
}
public static void Initialize()
{
//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_001c: Expected O, but got Unknown
object obj = <>O.<0>__PlayerControllerB_ConnectClientToPlayerObject;
if (obj == null)
{
hook_ConnectClientToPlayerObject val = PlayerControllerB_ConnectClientToPlayerObject;
<>O.<0>__PlayerControllerB_ConnectClientToPlayerObject = val;
obj = (object)val;
}
PlayerControllerB.ConnectClientToPlayerObject += (hook_ConnectClientToPlayerObject)obj;
}
private static void PlayerControllerB_ConnectClientToPlayerObject(orig_ConnectClientToPlayerObject orig, PlayerControllerB self)
{
orig.Invoke(self);
InitializeNetworkingAndSync();
}
}
public static LNetworkEvent RequestSyncEvent = LNetworkEvent.Connect("RequestItemSync", (Action<ulong>)OnRequestSync, (Action)null, (Action<ulong>)null);
public static LNetworkMessage<List<ItemData>> SyncItemMessage = LNetworkMessage<List<ItemData>>.Connect("SyncItemData", (Action<List<ItemData>, ulong>)null, (Action<List<ItemData>>)OnReceiveSync, (Action<List<ItemData>, ulong>)null);
private static void OnReceiveSync(List<ItemData> dataList)
{
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
if (!Config.Instance.SyncOnLoad.Value)
{
Plugin.Logger.LogInfo((object)"Sync | Got item sync from server but SyncOnLoad is disabled, ignoring");
return;
}
Plugin.Logger.LogInfo((object)$"Sync | Got item sync from server with {dataList.Count} object(s)");
NetworkObject val = default(NetworkObject);
foreach (ItemData data in dataList)
{
if (!((NetworkObjectReference)(ref data.NetworkObject)).TryGet(ref val, (NetworkManager)null))
{
Plugin.Logger.LogWarning((object)$"Sync | Unknown object reference {((NetworkObjectReference)(ref data.NetworkObject)).NetworkObjectId}");
Plugin.Logger.LogWarning((object)$"Sync | - Supplied rotation: {data.EulerAngles}");
continue;
}
GrabbableObject component = ((Component)val).gameObject.GetComponent<GrabbableObject>();
if ((Object)(object)component != (Object)null && IsValidObject(component))
{
ApplyRotationTo(component, data.EulerAngles);
}
else
{
Plugin.Logger.LogWarning((object)$"Sync | Attempted to sync invalid item {((NetworkObjectReference)(ref data.NetworkObject)).NetworkObjectId}");
}
}
}
private static void OnRequestSync(ulong clientId)
{
if (!Config.Instance.SyncOnLoad.Value)
{
Plugin.Logger.LogInfo((object)$"Sync | Got item sync request from client {clientId} but SyncOnLoad is disabled, ignoring");
return;
}
Plugin.Logger.LogInfo((object)$"Sync | Got item sync request from client {clientId}");
IEnumerable<ItemData> source = from grabbableObject in Object.FindObjectsOfType<GrabbableObject>().Where(IsValidObject)
select new ItemData
{
NetworkObject = NetworkObjectReference.op_Implicit(((NetworkBehaviour)grabbableObject).NetworkObject),
EulerAngles = ((Component)grabbableObject).transform.eulerAngles
};
SyncItemMessage.SendClient(source.ToList(), clientId);
}
public static void InitializeNetworkingAndSync()
{
if (!NetworkManager.Singleton.IsHost)
{
if (!Config.Instance.SyncOnLoad.Value)
{
Plugin.Logger.LogInfo((object)"Sync | SyncOnLoad is disabled, skipping item sync");
return;
}
Plugin.Logger.LogInfo((object)"Sync | Requesting item sync");
RequestSyncEvent.InvokeServer();
}
}
private static bool IsValidObject(GrabbableObject grabbableObject)
{
return !grabbableObject.isHeld && (Object)(object)grabbableObject.parentObject == (Object)null && grabbableObject.reachedFloorTarget;
}
private static void ApplyRotationTo(GrabbableObject grabbableObject, Vector3 eulerAngles)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
grabbableObject.floorYRot = -1;
((Component)grabbableObject).transform.rotation = Quaternion.Euler(((Component)grabbableObject).transform.eulerAngles.x, eulerAngles.y, ((Component)grabbableObject).transform.eulerAngles.z);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}
namespace moe.sylvi.SaveItemRotations.NetcodePatcher
{
[AttributeUsage(AttributeTargets.Module)]
internal class NetcodePatchedAssemblyAttribute : Attribute
{
}
}